]> 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 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)
 
 
 AC_INIT(vlc,0.7.0)
 
@@ -869,8 +869,7 @@ dnl
 dnl  default modules
 dnl
 AX_ADD_PLUGINS([dummy rc logger gestures memcpy hotkeys])
 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])
 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])
 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
 
 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/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
   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. 
 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
 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
 
 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];
 
            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 
         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 
 
 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
 
        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.
        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
  * 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:
  *
  * Authors: Rocky Bernstein
  *   based on code from:
@@ -182,11 +182,11 @@ Packetize( decoder_t *p_dec, block_t **pp_block )
 /*****************************************************************************
  Reassemble:
 
 /*****************************************************************************
  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.
 
  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;
 
     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, 
 
     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
  * 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: 
  *
  * 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.
   
   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
  
   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.
   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 )
 */
 
 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. */
 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] ) {
       
     
     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];
       
       
       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;
       
                 "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;
       
       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;
       
       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, 
        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,
       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,
                 "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,
       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,
                 "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:
       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, 
       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:
       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, 
       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_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;
     
     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*/
 
     }
 #endif /*HAVE_LIBPNG*/
 
-
     VCDInlinePalette( p_dest, p_sys, i_height, i_width );
 
     /* The video is automatically scaled. However subtitle bitmaps
     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 );
+