]> git.sesse.net Git - vlc/commitdiff
Add OGT and CVD subtitle demuxers.
authorRocky Bernstein <rocky@videolan.org>
Sun, 4 Jan 2004 16:51:59 +0000 (16:51 +0000)
committerRocky Bernstein <rocky@videolan.org>
Sun, 4 Jan 2004 16:51:59 +0000 (16:51 +0000)
write_png: might be made into a module and moved elsewhere
cvd*: went over documentation a little bit.

configure.ac
doc/subtitles/cvd-subtitles.txt
modules/codec/ogt/.cvsignore [new file with mode: 0644]
modules/codec/ogt/Modules.am [new file with mode: 0644]
modules/codec/ogt/cvd.c
modules/codec/ogt/cvd_parse.c
modules/codec/ogt/write_png.c [new file with mode: 0644]
modules/codec/ogt/write_png.h [new file with mode: 0644]

index 14d0a7043279d952a99361d6498b4201614d6110..4d12d43d9ec84bf951cbc8b699f1f553e5587955 100644 (file)
@@ -1,5 +1,5 @@
 dnl Autoconf settings for vlc
-dnl $Id: configure.ac,v 1.141 2004/01/04 15:32:13 fenrir Exp $
+dnl $Id: configure.ac,v 1.142 2004/01/04 16:51:59 rocky Exp $
 
 AC_INIT(vlc,0.7.0)
 
@@ -869,8 +869,7 @@ dnl
 dnl  default modules
 dnl
 AX_ADD_PLUGINS([dummy rc logger gestures memcpy hotkeys])
-AX_ADD_PLUGINS([mpgv mpga m4v mpeg_system ps ts avi asf aac mp4 rawdv demux2 nsv real])
-AX_ADD_PLUGINS([spudec dvbsub mpeg_audio lpcm a52 dts cinepak])
+AX_ADD_PLUGINS([cvdsub svcdsub spudec dvbsub mpeg_audio lpcm a52 dts cinepak])
 AX_ADD_PLUGINS([deinterlace invert adjust wall transform distort clone crop motionblur])
 AX_ADD_PLUGINS([float32tos16 float32tos8 float32tou16 float32tou8 a52tospdif dtstospdif fixed32tofloat32 fixed32tos16 s16tofixed32 s16tofloat32 s16tofloat32swab s8tofloat32 u8tofixed32 u8tofloat32])
 AX_ADD_PLUGINS([trivial_resampler ugly_resampler linear_resampler bandlimited_resampler])
@@ -2209,7 +2208,10 @@ dnl   png
 dnl
 AC_CHECK_HEADERS(png.h, [
     AX_ADD_LDFLAGS([logo],[-lpng -lz])
-    AX_ADD_PLUGINS([logo])])
+    AX_ADD_PLUGINS([logo])
+    AX_ADD_LDFLAGS([svcdsub],[-lpng -lz])
+    AX_ADD_LDFLAGS([cvdsub],[-lpng -lz])
+    AC_DEFINE(HAVE_LIBPNG, [], [Define if you have the PNG library: libpng])])
 
 dnl
 dnl  Video plugins
@@ -3555,6 +3557,7 @@ AC_CONFIG_FILES([
   modules/codec/Makefile
   modules/codec/ffmpeg/Makefile
   modules/codec/ffmpeg/postprocessing/Makefile
+  modules/codec/ogt/Makefile
   modules/codec/spudec/Makefile
   modules/control/Makefile
   modules/control/corba/Makefile
index a116eb3332f4d7110031f53a4b3d2995d798d211..aedac44029f206c8548ce85d62497162cd8eec6e 100644 (file)
@@ -1,4 +1,4 @@
-$Id: cvd-subtitles.txt,v 1.1 2004/01/04 16:25:00 rocky Exp $
+$Id: cvd-subtitles.txt,v 1.2 2004/01/04 16:51:59 rocky Exp $
 The following information is culled from information from 
 Julio Sanchez Fernandez (http://subhandler.sourceforge.net)
 by Rocky Bernstein. 
@@ -18,10 +18,10 @@ subtitle data and the offset to the metadata - i.e. size of the image
 data plus the four bytes at the beginning.
 
 Data for single screen subtitle may come in several non-contiguous
-packets of a stream. From the scant data on the format, there is only
-only way known to detect the first packet in a subtitle.  The first
-packet seems to have a valid PTS while later packets for the same
-image don't.
+packets of a stream. From the scant data on the format, the only way
+known to detect the first packet in a subtitle.  The first packet
+seems to have a valid PTS while later packets for the same image
+don't.
 
 Image data comes interlaced and is run-length encoded (RLE). Each
 field is a four-bit nibbles that is further subdivided in a two-bit
@@ -56,23 +56,23 @@ code    Meaning
            x = ((p[1]&0x0f)<<6) + (p[2]>>2)
            y = ((p[2]&0x03)<<8) + p[3];
 
-0x1f   lower right x, y postion, each a 10-bit (0-1023) value,
+0x1f   lower right x, y position, each a 10-bit (0-1023) value,
         encoded as above 
 
 0x24    3 bytes primary palette 0 - 1 byte for each of y, u, and v 
-0x25    3 bytes primary palette 1 - 1 byte for each of y, u  and v
-0x26    3 bytes primary palette 2 - 1 byte for each of y, u  and v
-0x27    3 bytes primary palette 3 - 1 byte for each of y, u  and v
+0x25    3 bytes primary palette 1 - 1 byte for each of y, u, and v
+0x26    3 bytes primary palette 2 - 1 byte for each of y, u, and v
+0x27    3 bytes primary palette 3 - 1 byte for each of y, u, and v
 
 0x2c    3 bytes highlight palette 0 - 1 byte for each of y, u, and v 
-0x2d    3 bytes highlight palette 1 - 1 byte for each of y, u  and v
-0x2e    3 bytes highlight palette 2 - 1 byte for each of y, u  and v
-0x2f    3 bytes highlight palette 3 - 1 byte for each of y, u  and v
+0x2d    3 bytes highlight palette 1 - 1 byte for each of y, u, and v
+0x2e    3 bytes highlight palette 2 - 1 byte for each of y, u, and v
+0x2f    3 bytes highlight palette 3 - 1 byte for each of y, u, and v
 
-0x37    3 bytes transparancy for primary palette - 1 byte for each 
+0x37    3 bytes transparency for primary palette - 1 byte for each 
        of y, u  and v
 
-0x3f    3 bytes transparancy for highlight palette - 1 byte for each 
+0x3f    3 bytes transparency for highlight palette - 1 byte for each 
        of y, u  and v
 
 0x47    Offset to start of even rows of interlaced image.
diff --git a/modules/codec/ogt/.cvsignore b/modules/codec/ogt/.cvsignore
new file mode 100644 (file)
index 0000000..8615509
--- /dev/null
@@ -0,0 +1,3 @@
+Makefile
+Makefile.am
+Makefile.in
diff --git a/modules/codec/ogt/Modules.am b/modules/codec/ogt/Modules.am
new file mode 100644 (file)
index 0000000..011df4f
--- /dev/null
@@ -0,0 +1,25 @@
+SOURCES_svcdsub = \
+       common.c \
+       common.h \
+       ogt.c \
+       ogt.h \
+       subtitle.h \
+       ogt_parse.c \
+       render.c \
+       render.h \
+       write_png.c \
+       write_png.h \
+       $(NULL)
+
+SOURCES_cvdsub = \
+       common.c \
+       common.h \
+       cvd.c \
+       cvd.h \
+       subtitle.h \
+       cvd_parse.c \
+       render.c \
+       render.h \
+       write_png.c \
+       write_png.h \
+       $(NULL)
index 7e3a29ec534d94dc221a98d2b6c2b421ccac18b6..52639dfc42f59444169a36200f4ff7e311bae7b0 100644 (file)
@@ -2,7 +2,7 @@
  * cvd.c : CVD Subtitle decoder thread
  *****************************************************************************
  * Copyright (C) 2003 VideoLAN
- * $Id: cvd.c,v 1.7 2004/01/04 04:56:21 rocky Exp $
+ * $Id: cvd.c,v 1.8 2004/01/04 16:51:59 rocky Exp $
  *
  * Authors: Rocky Bernstein
  *   based on code from:
@@ -182,11 +182,11 @@ Packetize( decoder_t *p_dec, block_t **pp_block )
 /*****************************************************************************
  Reassemble:
 
- The data for single screen subtitle may come in one of many
- non-contiguous packets of a stream. This routine is called when the
- next packet in the stream comes in. The job of this routine is to
- parse the header, if this is the beginning, and combine the packets
into one complete subtitle unit.
+ Data for single screen subtitle may come in several non-contiguous
+ packets of a stream. This routine is called when the next packet in
+ the stream comes in. The job of this routine is to parse the header,
+ if this is the beginning, and combine the packets into one complete
+ subtitle unit.
 
  If everything is complete, we will return a block. Otherwise return
  NULL.
@@ -225,10 +225,10 @@ Reassemble( decoder_t *p_dec, block_t **pp_block )
     if( config_GetInt( p_dec, "spu-channel" ) != p_buffer[0] )
       return NULL;
 
-    /* There is little data on the format, but it does not seem to have a
-       good way to detect the first packet in the subtitle.  It seems,
-       however, that it has a valid pts while later packets for the same
-       image don't */
+    /* From the scant data on the format, there is only only way known
+       to detect the first packet in a subtitle.  The first packet
+       seems to have a valid PTS while later packets for the same
+       image don't. */
 
     if ( p_sys->state == SUBTITLE_BLOCK_EMPTY && p_block->i_pts == 0 ) {
       msg_Warn( p_dec, 
index 5af4107265068e65c55d12783bb3c6441988f99a..99a3eca9c5a21afedd371ac7e9ce9d7406d35385 100644 (file)
@@ -2,7 +2,7 @@
  * parse.c: Philips OGT (SVCD subtitle) packet parser
  *****************************************************************************
  * Copyright (C) 2003, 2004 VideoLAN
- * $Id: cvd_parse.c,v 1.6 2004/01/04 04:56:21 rocky Exp $
+ * $Id: cvd_parse.c,v 1.7 2004/01/04 16:51:59 rocky Exp $
  *
  * Authors: Rocky Bernstein 
  *   based on code from: 
@@ -55,12 +55,12 @@ static int  ParseImage         ( decoder_t *, subpicture_t * );
   origin. Thus, this is the result of reading some code whose
   correctness is not known and some experimentation.
   
-  CVD subtitles are different in severl ways from SVCD OGT subtitles.
-  First, the image comes first and the metadata is at the end.  So
-  that the metadata can be found easily, the subtitle packet starts
-  with two bytes (everything is big-endian again) that give the total
-  size of the subtitle data and the offset to the metadata - i.e. size
-  of the image data plus the four bytes at the beginning.
+  CVD subtitles are different in several ways from SVCD OGT subtitles.
+  Image comes first and metadata is at the end.  So that the metadata
+  can be found easily, the subtitle packet starts with two bytes
+  (everything is big-endian again) that give the total size of the
+  subtitle data and the offset to the metadata - i.e. size of the
+  image data plus the four bytes at the beginning.
  
   Image data comes interlaced is run-length encoded.  Each field is a
   four-bit nibble. Each nibble contains a two-bit repeat count and a
@@ -73,11 +73,6 @@ static int  ParseImage         ( decoder_t *, subpicture_t * );
   that the fill-line complete case above is not as described and the
   zero repeat count means fill line.  The sample code never produces
   this, so it may be untested.
-  The metadata section does not follow a fixed pattern, every
-  metadata item consists of a tag byte followed by parameters. In all
-  cases known, the block (including the tag byte) is exactly four
-  bytes in length.  Read the code for the rest.
 */
 
 void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block )
@@ -108,6 +103,20 @@ void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block )
 
 }
 
+#define ExtractXY(x, y)                    \
+  x = ((p[1]&0x0f)<<6) + (p[2]>>2); \
+  y = ((p[2]&0x03)<<8) + p[3];
+
+
+/* 
+  We parse the metadata information here. 
+
+  Although metadata information does not have to come in a fixed field
+  order, every metadata field consists of a tag byte followed by
+  parameters. In all cases known, the size including tag byte is
+  exactly four bytes in length.
+*/
+
 void E_(ParseMetaInfo)( decoder_t *p_dec  )
 {
   /* last packet in subtitle block. */
@@ -126,7 +135,7 @@ void E_(ParseMetaInfo)( decoder_t *p_dec  )
     
     switch ( p[0] ) {
       
-    case 0x04: /* Display duration in 1/90000ths of a second */
+    case 0x04: /* subtitle duration in 1/90000ths of a second */
       
       p_sys->i_duration = (p[1]<<16) + (p[2]<<8) + p[3];
       
@@ -134,25 +143,21 @@ void E_(ParseMetaInfo)( decoder_t *p_dec  )
                 "subtitle display duration %u", p_sys->i_duration);
       break;
       
-    case 0x0c: /* Unknown */
+    case 0x0c: /* unknown */
       dbg_print( DECODE_DBG_PACKET, 
                 "subtitle command unknown 0x%0x 0x%0x 0x%0x 0x%0x\n",
                 p[0], p[1], p[2], p[3]);
       break;
       
-    case 0x17: /* Position */
-      p_sys->i_x_start = ((p[1]&0x0f)<<6) + (p[2]>>2);
-      p_sys->i_y_start = ((p[2]&0x03)<<8) + p[3];
-      dbg_print( DECODE_DBG_PACKET, 
-                "start position (%d,%d): %.2x %.2x %.2x", 
-                p_sys->i_x_start, p_sys->i_y_start,
-                p[1], p[2], p[3] );
+    case 0x17: /* coordinates of subtitle upper left x, y position */
+      ExtractXY(p_sys->i_x_start, p_sys->i_y_start);
       break;
       
-    case 0x1f: /* Coordinates of the image bottom right */
+    case 0x1f: /* coordinates of subtitle bottom right x, y position */
       {
-       int lastx = ((p[1]&0x0f)<<6) + (p[2]>>2);
-       int lasty = ((p[2]&0x03)<<8) + p[3];
+       int lastx;
+       int lasty;
+       ExtractXY(lastx, lasty);
        p_sys->i_width  = lastx - p_sys->i_x_start + 1;
        p_sys->i_height = lasty - p_sys->i_y_start + 1;
        dbg_print( DECODE_DBG_PACKET, 
@@ -208,7 +213,7 @@ void E_(ParseMetaInfo)( decoder_t *p_dec  )
       p_sys->p_palette[3].s.t = p[2] >> 4;
       
       dbg_print( DECODE_DBG_PACKET,
-                "transparancy for primary palette 0..3: "
+                "transparency for primary palette 0..3: "
                 "0x%0x 0x%0x 0x%0x 0x%0x",
                 p_sys->p_palette[0].s.t,
                 p_sys->p_palette[1].s.t,
@@ -225,7 +230,7 @@ void E_(ParseMetaInfo)( decoder_t *p_dec  )
       p_sys->p_palette_highlight[3].s.t = p[1] >> 4;
       
       dbg_print( DECODE_DBG_PACKET,
-                "transparancy for primary palette 0..3: "
+                "transparency for primary palette 0..3: "
                 "0x%0x 0x%0x 0x%0x 0x%0x",
                 p_sys->p_palette_highlight[0].s.t,
                 p_sys->p_palette_highlight[1].s.t,
@@ -235,8 +240,8 @@ void E_(ParseMetaInfo)( decoder_t *p_dec  )
       break;
       
     case 0x47:
-      /* offset to first field data, we correct to make it relative
-        to comp_image_offset (usually 4) */
+      /* offset to start of even rows of interlaced image, we correct
+        to make it relative to comp_image_offset (usually 4) */
       p_sys->first_field_offset =
        (p[2] << 8) + p[3] - p_sys->comp_image_offset;
       dbg_print( DECODE_DBG_PACKET, 
@@ -244,8 +249,8 @@ void E_(ParseMetaInfo)( decoder_t *p_dec  )
       break;
       
     case 0x4f:
-      /* offset to second field data, we correct to make it relative to
-        comp_image_offset (usually 4) */
+      /* offset to start of odd rows of interlaced image, we correct
+        to make it relative to comp_image_offset (usually 4) */
       p_sys->second_field_offset =
        (p[2] << 8) + p[3] - p_sys->comp_image_offset;
       dbg_print( DECODE_DBG_PACKET, 
@@ -309,7 +314,7 @@ E_(ParsePacket)( decoder_t *p_dec)
     p_spu->i_height   = p_sys->i_height;
 
     p_spu->i_start    = p_sys->i_pts;
-    p_spu->i_stop     = p_sys->i_pts + (p_sys->i_duration * 5);
+    p_spu->i_stop     = p_sys->i_pts + (p_sys->i_duration);
     
     p_spu->p_sys->b_crop  = VLC_FALSE;
     p_spu->p_sys->i_debug = p_sys->i_debug;
@@ -517,7 +522,6 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
     }
 #endif /*HAVE_LIBPNG*/
 
-
     VCDInlinePalette( p_dest, p_sys, i_height, i_width );
 
     /* The video is automatically scaled. However subtitle bitmaps
diff --git a/modules/codec/ogt/write_png.c b/modules/codec/ogt/write_png.c
new file mode 100644 (file)
index 0000000..009044a
--- /dev/null
@@ -0,0 +1,238 @@
+/*****************************************************************************
+ * Dump an Image to a Portable Network Graphics (PNG) file
+ ****************************************************************************
+  Copyright (C) 2004 VideoLAN
+  Author: Rocky Bernstein
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef HAVE_LIBPNG
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "write_png.h"
+#include <setjmp.h>
+
+typedef void (*snapshot_messenger_t)(char *message);
+
+#define _(x) x
+
+/*
+ *   Error functions for use as callbacks by the png libraries
+ */
+
+void error_msg(char *message) 
+{
+  printf("error: %s\n", message);
+}
+
+void warning_msg(char *message) 
+{
+  printf("warning: %s\n", message);
+}
+
+static snapshot_messenger_t error_msg_cb = error_msg;
+static snapshot_messenger_t warning_msg_cb  = warning_msg;
+
+static void 
+user_error_fn(png_structp png_ptr, png_const_charp error_msg)
+{
+
+  if(error_msg_cb) {
+    char uerror[4096]; 
+
+    memset(&uerror, 0, sizeof(uerror));
+    sprintf(uerror, _("Error: %s\n"), error_msg);
+    error_msg_cb(uerror);
+  }
+}
+
+static void 
+user_warning_fn(png_structp png_ptr, png_const_charp warning_msg)
+{
+  if(error_msg_cb) {
+    char uerror[4096];
+    
+    memset(&uerror, 0, sizeof(uerror));
+    sprintf(uerror, _("Error: %s\n"), warning_msg);
+    warning_msg_cb(uerror);
+  }
+}
+
+/* 
+   Dump an image to a Portable Network Graphics (PNG) file. File_name
+   is where the file goes, i_height and i_width are the height and
+   width in pixels of the image. The data for the image is stored as a
+   linear array of one byte for each of red, green, and blue
+   components of an RGB pixel. Thus row[i] will begin at rgb_image +
+   i*(i_width*3) and the blue pixel at image[i][0] would be rgb_image +
+   i*(i_width*3) + 1.
+   
+ */
+void 
+write_png(const char *file_name, png_uint_32 i_height, png_uint_32 i_width,
+         void *rgb_image, /*in*/ png_text *text_ptr, int i_text_count )
+{
+  FILE *fp;
+  png_structp png_ptr;
+  png_infop info_ptr;
+  png_color_8 sig_bit;
+  png_bytep *row_pointers;
+
+  unsigned int i,j;
+
+  /* open the file */
+  fp = fopen(file_name, "wb");
+  if (fp == NULL)
+    return;
+  
+  /* Create and initialize the png_struct with the desired error handler
+   * functions.  If you want to use the default stderr and longjump method,
+   * you can supply NULL for the last three parameters.  We also check that
+   * the library version is compatible with the one used at compile time,
+   * in case we are using dynamically linked libraries.  REQUIRED.
+   */
+  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL,
+                                   user_error_fn, user_warning_fn);
+  
+  if (png_ptr == NULL)
+    {
+      fclose(fp);
+      return;
+    }
+  
+  /* Allocate/initialize the image information data.  REQUIRED */
+  info_ptr = png_create_info_struct(png_ptr);
+  if (info_ptr == NULL)
+    {
+      fclose(fp);
+      png_destroy_write_struct(&png_ptr,  (png_infopp)NULL);
+      return;
+    }
+  
+  /* Set error handling.  REQUIRED if you aren't supplying your own
+   * error handling functions in the png_create_write_struct() call.
+   */
+  if (setjmp(png_ptr->jmpbuf))
+    {
+      /* If we get here, we had a problem writing the file */
+      fclose(fp);
+      png_destroy_write_struct(&png_ptr,  (png_infopp) &info_ptr);
+      return;
+   }
+
+   /* Set up the output control using standard C streams. This
+      is required. */
+   png_init_io(png_ptr, fp);
+
+   /* Set the image information here.  i_width and i_height are up to 2^31,
+    * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
+    * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
+    * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
+    * or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
+    * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
+    * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
+    */
+   png_set_IHDR(png_ptr, info_ptr, i_width, i_height, 8, PNG_COLOR_TYPE_RGB,
+               PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, 
+               PNG_FILTER_TYPE_BASE);
+
+   /* For color images: */
+   sig_bit.red   = 8;
+   sig_bit.green = 8;
+   sig_bit.blue  = 8;
+
+   if (text_ptr)
+     png_set_text(png_ptr, info_ptr, text_ptr, i_text_count);
+
+   /* Write the file header information.  REQUIRED */
+   png_write_info(png_ptr, info_ptr);
+
+   /* Once we write out the header, the compression type on the text
+    * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or
+    * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again
+    * at the end.
+    */
+
+   /* Shift the pixels up to a legal bit depth and fill in
+    * as appropriate to correctly scale the image.
+    */
+   png_set_shift(png_ptr, &sig_bit);
+
+   /* pack pixels into bytes */
+   png_set_packing(png_ptr);
+
+   row_pointers = png_malloc(png_ptr, i_height*sizeof(png_bytep *));
+   for (i=0, j=0; i<i_height; i++, j+=i_width*3) {
+     row_pointers[i] = rgb_image + j; 
+   }
+   
+   png_set_rows   (png_ptr, info_ptr, row_pointers);
+   png_write_image(png_ptr, row_pointers);
+
+   /* You can write optional chunks like tEXt, zTXt, and tIME at the end
+    * as well.
+    */
+
+   /* It is REQUIRED to call this to finish writing the rest of the file */
+   png_write_end(png_ptr, info_ptr);
+
+   /* if you allocated any text comments, free them here */
+   /* free image data if allocated. */
+
+   /* clean up after the write, and free any memory allocated */
+   png_destroy_info_struct(png_ptr, &info_ptr);
+
+   /* clean up after the write, and free any memory allocated */
+   png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
+
+   fclose(fp);
+
+   return;
+}
+
+#ifdef STANDALONE
+int
+main(int argc, char **argv) 
+{
+  char image_data[3*16 * 3*16 * 3];
+  int i,j,k,l,m;
+  char r,g,b,t, or,og,ob;
+
+  or=0x00; og=0xFF; ob=0x0;
+  m=0;
+  for (i=0; i<3; i++) {
+    t=or; or=og; og=ob; ob=t;
+    for (j=0; j<16; j++) {
+      r=or; g=og; b=ob;
+      for (k=0; k<3; k++) {
+       for (l=0; l<16; l++) {
+         image_data[m++]=r;
+         image_data[m++]=g;
+         image_data[m++]=b;
+       }
+       t=r; r=g; g=b; b=t;
+      }
+    }
+  }
+  
+  write_png("/tmp/pngtest.png", 3*16, 3*16, (void *) image_data) ;
+  return 0;
+}
+#endif /*STANDALONE*/
+
+#endif /*HAVE_LIBPNG*/
diff --git a/modules/codec/ogt/write_png.h b/modules/codec/ogt/write_png.h
new file mode 100644 (file)
index 0000000..df9945f
--- /dev/null
@@ -0,0 +1,40 @@
+/*****************************************************************************
+ * Dump an Image to a Portable Network Graphics (PNG) file
+ ****************************************************************************
+  Copyright (C) 2004 VideoLAN
+  Author: Rocky Bernstein
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include <png.h>
+
+/* 
+   Dump an image to a Portable Network Graphics (PNG) file. File_name
+   is where the file goes, i_height and i_width are the height and
+   width in pixels of the image. The data for the image is stored as a
+   linear array RGB pixel entries: one byte for each of red, green,
+   and blue component. Thus row[i] will begin at rgb_image +
+   i*(i_width*3) and the blue pixel at image[i][0] would be rgb_image
+   + i*(i_width*3) + 1.
+
+   text_ptr contains comments that can be written to the image. It can
+   be null. i_text_count is the number of entries in text_ptr.
+   
+ */
+void write_png(const char *file_name, png_uint_32 i_height, 
+              png_uint_32 i_width, void *rgb_image, 
+              /*in*/ png_text *text_ptr, int i_text_count );
+