]> git.sesse.net Git - vlc/blob - modules/codec/ogt/write_png.c
* ffmpeg.c: disabled mpeg4 audio, too buggy. (This way users can see that
[vlc] / modules / codec / ogt / write_png.c
1 /*****************************************************************************
2  * Dump an Image to a Portable Network Graphics (PNG) file
3  ****************************************************************************
4   Copyright (C) 2004 VideoLAN
5   Author: Rocky Bernstein
6  
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 2 of the License, or
10   (at your option) any later version.
11  
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16  
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
20  *****************************************************************************/
21
22 #include "config.h"
23 #ifdef HAVE_LIBPNG
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include "write_png.h"
28 #include <setjmp.h>
29
30 typedef void (*snapshot_messenger_t)(char *message);
31
32 #define _(x) x
33
34 /*
35  *   Error functions for use as callbacks by the png libraries
36  */
37
38 void error_msg(char *message) 
39 {
40   printf("error: %s\n", message);
41 }
42
43 void warning_msg(char *message) 
44 {
45   printf("warning: %s\n", message);
46 }
47
48 static snapshot_messenger_t error_msg_cb = error_msg;
49 static snapshot_messenger_t warning_msg_cb  = warning_msg;
50
51 static void 
52 user_error_fn(png_structp png_ptr, png_const_charp error_msg)
53 {
54
55   if(error_msg_cb) {
56     char uerror[4096]; 
57
58     memset(&uerror, 0, sizeof(uerror));
59     sprintf(uerror, _("Error: %s\n"), error_msg);
60     error_msg_cb(uerror);
61   }
62 }
63
64 static void 
65 user_warning_fn(png_structp png_ptr, png_const_charp warning_msg)
66 {
67   if(error_msg_cb) {
68     char uerror[4096];
69     
70     memset(&uerror, 0, sizeof(uerror));
71     sprintf(uerror, _("Error: %s\n"), warning_msg);
72     warning_msg_cb(uerror);
73   }
74 }
75
76 /* 
77    Dump an image to a Portable Network Graphics (PNG) file. File_name
78    is where the file goes, i_height and i_width are the height and
79    width in pixels of the image. The data for the image is stored as a
80    linear array of one byte for each of red, green, and blue
81    components of an RGB pixel. Thus row[i] will begin at rgb_image +
82    i*(i_width*3) and the blue pixel at image[i][0] would be rgb_image +
83    i*(i_width*3) + 1.
84    
85  */
86 void 
87 write_png(const char *file_name, png_uint_32 i_height, png_uint_32 i_width,
88           void *rgb_image, /*in*/ png_text *text_ptr, int i_text_count )
89 {
90   FILE *fp;
91   png_structp png_ptr;
92   png_infop info_ptr;
93   png_color_8 sig_bit;
94   png_bytep *row_pointers;
95
96   unsigned int i,j;
97
98   /* open the file */
99   fp = fopen(file_name, "wb");
100   if (fp == NULL)
101     return;
102   
103   /* Create and initialize the png_struct with the desired error handler
104    * functions.  If you want to use the default stderr and longjump method,
105    * you can supply NULL for the last three parameters.  We also check that
106    * the library version is compatible with the one used at compile time,
107    * in case we are using dynamically linked libraries.  REQUIRED.
108    */
109   png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL,
110                                     user_error_fn, user_warning_fn);
111   
112   if (png_ptr == NULL)
113     {
114       fclose(fp);
115       return;
116     }
117   
118   /* Allocate/initialize the image information data.  REQUIRED */
119   info_ptr = png_create_info_struct(png_ptr);
120   if (info_ptr == NULL)
121     {
122       fclose(fp);
123       png_destroy_write_struct(&png_ptr,  (png_infopp)NULL);
124       return;
125     }
126   
127   /* Set error handling.  REQUIRED if you aren't supplying your own
128    * error handling functions in the png_create_write_struct() call.
129    */
130   if (setjmp(png_ptr->jmpbuf))
131     {
132       /* If we get here, we had a problem writing the file */
133       fclose(fp);
134       png_destroy_write_struct(&png_ptr,  (png_infopp) &info_ptr);
135       return;
136    }
137
138    /* Set up the output control using standard C streams. This
139       is required. */
140    png_init_io(png_ptr, fp);
141
142    /* Set the image information here.  i_width and i_height are up to 2^31,
143     * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
144     * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
145     * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
146     * or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
147     * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
148     * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
149     */
150    png_set_IHDR(png_ptr, info_ptr, i_width, i_height, 8, PNG_COLOR_TYPE_RGB,
151                 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, 
152                 PNG_FILTER_TYPE_BASE);
153
154    /* For color images: */
155    sig_bit.red   = 8;
156    sig_bit.green = 8;
157    sig_bit.blue  = 8;
158
159    if (text_ptr)
160      png_set_text(png_ptr, info_ptr, text_ptr, i_text_count);
161
162    /* Write the file header information.  REQUIRED */
163    png_write_info(png_ptr, info_ptr);
164
165    /* Once we write out the header, the compression type on the text
166     * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or
167     * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again
168     * at the end.
169     */
170
171    /* Shift the pixels up to a legal bit depth and fill in
172     * as appropriate to correctly scale the image.
173     */
174    png_set_shift(png_ptr, &sig_bit);
175
176    /* pack pixels into bytes */
177    png_set_packing(png_ptr);
178
179    row_pointers = png_malloc(png_ptr, i_height*sizeof(png_bytep *));
180    for (i=0, j=0; i<i_height; i++, j+=i_width*3) {
181      row_pointers[i] = rgb_image + j; 
182    }
183    
184    png_set_rows   (png_ptr, info_ptr, row_pointers);
185    png_write_image(png_ptr, row_pointers);
186
187    /* You can write optional chunks like tEXt, zTXt, and tIME at the end
188     * as well.
189     */
190
191    /* It is REQUIRED to call this to finish writing the rest of the file */
192    png_write_end(png_ptr, info_ptr);
193
194    /* if you allocated any text comments, free them here */
195    /* free image data if allocated. */
196
197    /* clean up after the write, and free any memory allocated */
198    png_destroy_info_struct(png_ptr, &info_ptr);
199
200    /* clean up after the write, and free any memory allocated */
201    png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
202
203    fclose(fp);
204
205    return;
206 }
207
208 #ifdef STANDALONE
209 int
210 main(int argc, char **argv) 
211 {
212   char image_data[3*16 * 3*16 * 3];
213   int i,j,k,l,m;
214   char r,g,b,t, or,og,ob;
215
216   or=0x00; og=0xFF; ob=0x0;
217   m=0;
218   for (i=0; i<3; i++) {
219     t=or; or=og; og=ob; ob=t;
220     for (j=0; j<16; j++) {
221       r=or; g=og; b=ob;
222       for (k=0; k<3; k++) {
223         for (l=0; l<16; l++) {
224           image_data[m++]=r;
225           image_data[m++]=g;
226           image_data[m++]=b;
227         }
228         t=r; r=g; g=b; b=t;
229       }
230     }
231   }
232   
233   write_png("/tmp/pngtest.png", 3*16, 3*16, (void *) image_data) ;
234   return 0;
235 }
236 #endif /*STANDALONE*/
237
238 #endif /*HAVE_LIBPNG*/