initial commit
[goodguy/history.git] / cinelerra-5.0 / cinelerra / filepng.C.orig
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  * 
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  * 
20  */
21
22 #include "asset.h"
23 #include "edit.h"
24 #include "file.h"
25 #include "filepng.h"
26 #include "language.h"
27 #include "mwindow.inc"
28 #include "quicktime.h"
29 #include "vframe.h"
30 #include "videodevice.inc"
31
32 #include <png.h>
33
34 FilePNG::FilePNG(Asset *asset, File *file)
35  : FileList(asset, file, "PNGLIST", ".png", FILE_PNG, FILE_PNG_LIST)
36 {
37 }
38
39 FilePNG::~FilePNG()
40 {
41 }
42
43
44
45 int FilePNG::check_sig(Asset *asset)
46 {
47         FILE *stream = fopen(asset->path, "rb");
48
49         if(stream)
50         {
51
52 //printf("FilePNG::check_sig 1\n");
53                 char test[16];
54                 int temp = fread(test, 16, 1, stream);
55                 fclose(stream);
56
57                 if(png_check_sig((unsigned char*)test, 8))
58                 {
59 //printf("FilePNG::check_sig 1\n");
60                         return 1;
61                 }
62                 else
63                 if(test[0] == 'P' && test[1] == 'N' && test[2] == 'G' && 
64                         test[3] == 'L' && test[4] == 'I' && test[5] == 'S' && test[6] == 'T')
65                 {
66 //printf("FilePNG::check_sig 1\n");
67                         return 1;
68                 }
69         }
70         return 0;
71 }
72
73
74
75 void FilePNG::get_parameters(BC_WindowBase *parent_window, 
76         Asset *asset, 
77         BC_WindowBase* &format_window,
78         int audio_options,
79         int video_options)
80 {
81         if(video_options)
82         {
83                 PNGConfigVideo *window = new PNGConfigVideo(parent_window, asset);
84                 format_window = window;
85                 window->create_objects();
86                 window->run_window();
87                 delete window;
88         }
89 }
90
91
92
93
94 int FilePNG::can_copy_from(Asset *asset, int64_t position)
95 {
96         if(asset->format == FILE_MOV)
97         {
98                 if(match4(asset->vcodec, QUICKTIME_PNG)) return 1;
99         }
100         else
101         if(asset->format == FILE_PNG || 
102                 asset->format == FILE_PNG_LIST)
103                 return 1;
104
105         return 0;
106 }
107
108
109 int FilePNG::colormodel_supported(int colormodel)
110 {
111         if (((colormodel == BC_RGBA8888) && (native_cmodel == BC_RGBA16161616))
112             || ((colormodel == BC_RGB161616) && (native_cmodel == BC_RGBA16161616))
113             || (colormodel == BC_RGB888))
114         {
115             return colormodel;
116         }
117         else if ((colormodel == BC_RGB161616) && (native_cmodel == BC_RGBA8888))
118         {
119             return BC_RGB888;
120         }
121         else
122         {
123             return native_cmodel;
124         }
125 }
126
127
128 int FilePNG::get_best_colormodel(Asset *asset, int driver)
129 {
130         if(asset->png_use_alpha)
131                 return BC_RGBA8888;
132         else
133                 return BC_RGB888;
134 }
135
136
137
138
139 int FilePNG::read_frame_header(char *path)
140 {
141         int result = 0;
142         int color_type;
143         int color_depth;
144         int num_trans = 0;
145         
146         FILE *stream;
147
148         if(!(stream = fopen(path, "rb")))
149         {
150                 perror("FilePNG::read_frame_header");
151                 return 1;
152         }
153
154         png_structp png_ptr;
155         png_infop info_ptr;
156         png_infop end_info = 0; 
157         png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
158         info_ptr = png_create_info_struct(png_ptr);
159         png_init_io(png_ptr, stream);
160
161
162         png_read_info(png_ptr, info_ptr);
163
164         asset->width = png_get_image_width(png_ptr, info_ptr);
165         asset->height = png_get_image_height(png_ptr, info_ptr);
166         color_type = png_get_color_type(png_ptr, info_ptr);
167         color_depth = png_get_bit_depth(png_ptr,info_ptr);
168         
169         png_get_tRNS(png_ptr, info_ptr, NULL, &num_trans, NULL);
170         
171         if (color_depth == 16)
172         {
173             if (color_type & PNG_COLOR_MASK_ALPHA)
174             {
175                 native_cmodel = BC_RGBA16161616;
176             }
177             else
178             {
179                 native_cmodel = BC_RGB161616;
180             }
181         }
182         else 
183         if ((color_type & PNG_COLOR_MASK_ALPHA)
184             || (num_trans > 0))
185         {
186             native_cmodel = BC_RGBA8888;
187         }
188         else
189         {
190             native_cmodel = BC_RGB888;
191         }
192
193
194         png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
195         fclose(stream);
196         
197         
198         
199         return result;
200 }
201
202
203
204
205 static void read_function(png_structp png_ptr, 
206         png_bytep data, 
207         png_uint_32 length)
208 {
209         VFrame *input = (VFrame*)png_get_io_ptr(png_ptr);
210
211         memcpy(data, input->get_data() + input->get_compressed_size(), length);
212         input->set_compressed_size(input->get_compressed_size() + length);
213 }
214
215 static void write_function(png_structp png_ptr, png_bytep data, png_uint_32 length)
216 {
217         VFrame *output = (VFrame*)png_get_io_ptr(png_ptr);
218
219         if(output->get_compressed_allocated() < output->get_compressed_size() + length)
220                 output->allocate_compressed_data((output->get_compressed_allocated() + length) * 2);
221         memcpy(output->get_data() + output->get_compressed_size(), data, length);
222         output->set_compressed_size(output->get_compressed_size() + length);
223 }
224
225 static void flush_function(png_structp png_ptr)
226 {
227         ;
228 }
229
230
231
232 int FilePNG::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit)
233 {
234         PNGUnit *png_unit = (PNGUnit*)unit;
235         int result = 0;
236         png_structp png_ptr;
237         png_infop info_ptr;
238         png_infop end_info = 0; 
239         VFrame *output_frame;
240         data->set_compressed_size(0);
241
242 //printf("FilePNG::write_frame 1\n");
243         png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
244         info_ptr = png_create_info_struct(png_ptr);
245         png_set_write_fn(png_ptr,
246                data, 
247                            (png_rw_ptr)write_function,
248                (png_flush_ptr)flush_function);
249         png_set_compression_level(png_ptr, 9);
250
251         png_set_IHDR(png_ptr, 
252                 info_ptr, 
253                 asset->width, 
254                 asset->height,
255         8, 
256                 asset->png_use_alpha ? 
257                   PNG_COLOR_TYPE_RGB_ALPHA : 
258                   PNG_COLOR_TYPE_RGB, 
259                 PNG_INTERLACE_NONE, 
260                 PNG_COMPRESSION_TYPE_DEFAULT, 
261                 PNG_FILTER_TYPE_DEFAULT);
262         png_write_info(png_ptr, info_ptr);
263
264 //printf("FilePNG::write_frame 1\n");
265         native_cmodel = asset->png_use_alpha ? BC_RGBA8888 : BC_RGB888;
266         if(frame->get_color_model() != native_cmodel)
267         {
268                 if(!png_unit->temp_frame) png_unit->temp_frame = new VFrame(0, 
269                         -1,
270                         asset->width, 
271                         asset->height, 
272                         native_cmodel,
273                         -1);
274
275                 BC_CModels::transfer(png_unit->temp_frame->get_rows(), /* Leave NULL if non existent */
276                         frame->get_rows(),
277                         png_unit->temp_frame->get_y(), /* Leave NULL if non existent */
278                         png_unit->temp_frame->get_u(),
279                         png_unit->temp_frame->get_v(),
280                         frame->get_y(), /* Leave NULL if non existent */
281                         frame->get_u(),
282                         frame->get_v(),
283                         0,        /* Dimensions to capture from input frame */
284                         0, 
285                         asset->width, 
286                         asset->height,
287                         0,       /* Dimensions to project on output frame */
288                         0, 
289                         asset->width, 
290                         asset->height,
291                         frame->get_color_model(), 
292                         png_unit->temp_frame->get_color_model(),
293                         0,         /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
294                         asset->width,       /* For planar use the luma rowspan */
295                         asset->height);
296                 
297                 output_frame = png_unit->temp_frame;
298         }
299         else
300                 output_frame = frame;
301
302
303 //printf("FilePNG::write_frame 2\n");
304         png_write_image(png_ptr, output_frame->get_rows());
305         png_write_end(png_ptr, info_ptr);
306         png_destroy_write_struct(&png_ptr, &info_ptr);
307 //printf("FilePNG::write_frame 3 %d\n", data->get_compressed_size());
308
309         return result;
310 }
311
312 int FilePNG::read_frame(VFrame *output, VFrame *input)
313 {
314         png_structp png_ptr;
315         png_infop info_ptr;
316         png_infop end_info = 0; 
317         int result = 0;
318         int color_type;
319         int color_depth;
320         int colormodel;
321         int size = input->get_compressed_size();
322         input->set_compressed_size(0);
323         
324         
325         //printf("FilePNG::read_frame 1 %d %d\n", native_cmodel, output->get_color_model());
326         png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
327         info_ptr = png_create_info_struct(png_ptr);
328         png_set_read_fn(png_ptr, input, (png_rw_ptr)read_function);
329         png_read_info(png_ptr, info_ptr);
330
331         int png_color_type = png_get_color_type(png_ptr, info_ptr);
332         if (png_color_type == PNG_COLOR_TYPE_GRAY ||
333                 png_color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
334         {
335                 png_set_gray_to_rgb(png_ptr);
336         }
337
338         colormodel = output->get_color_model();
339         color_type = png_get_color_type(png_ptr, info_ptr);
340         color_depth = png_get_bit_depth(png_ptr,info_ptr);
341         
342         if (((native_cmodel == BC_RGBA16161616)||(native_cmodel == BC_RGB161616))
343             && ((colormodel == BC_RGBA8888)||(colormodel == BC_RGB888)))
344         {
345             png_set_strip_16(png_ptr);
346         }
347
348         /* If we're dropping the alpha channel, use the background color of the image
349            otherwise, use black */
350         if (((native_cmodel == BC_RGBA16161616)||(native_cmodel == BC_RGBA8888))
351             && ((colormodel == BC_RGB161616)||(colormodel == BC_RGB888)))
352         {
353             png_color_16 my_background;
354             png_color_16p image_background;
355             
356             memset(&my_background,0,sizeof(png_color_16));
357             
358             if (png_get_bKGD(png_ptr, info_ptr, &image_background))
359             {
360                 png_set_background(png_ptr, image_background, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
361             }
362             else
363             {
364                 png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
365             }
366         }
367         
368         /* Little endian */
369         if ((color_depth == 16)
370             &&((colormodel == BC_RGBA16161616)||(colormodel == BC_RGB161616)))
371         {
372             png_set_swap(png_ptr);
373         }
374         
375         if (!(color_type & PNG_COLOR_MASK_COLOR))
376         {
377             png_set_gray_to_rgb(png_ptr);
378         }
379         
380         if (color_type & PNG_COLOR_MASK_PALETTE)
381         {
382             png_set_palette_to_rgb(png_ptr);
383         }
384         
385         if (color_depth <= 8)
386         {
387             png_set_expand(png_ptr);
388         }
389
390 /* read the image */
391         png_read_image(png_ptr, output->get_rows());
392 //printf("FilePNG::read_frame 3\n");
393         png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
394
395         input->set_compressed_size(size);
396
397 //printf("FilePNG::read_frame 4\n");
398         return result;
399 }
400
401 FrameWriterUnit* FilePNG::new_writer_unit(FrameWriter *writer)
402 {
403         return new PNGUnit(this, writer);
404 }
405
406
407
408
409
410
411
412
413
414
415
416
417 PNGUnit::PNGUnit(FilePNG *file, FrameWriter *writer)
418  : FrameWriterUnit(writer)
419 {
420         this->file = file;
421         temp_frame = 0;
422 }
423 PNGUnit::~PNGUnit()
424 {
425         if(temp_frame) delete temp_frame;
426 }
427
428
429
430
431
432
433
434
435
436 PNGConfigVideo::PNGConfigVideo(BC_WindowBase *parent_window, Asset *asset)
437  : BC_Window(PROGRAM_NAME ": Video Compression",
438         parent_window->get_abs_cursor_x(1),
439         parent_window->get_abs_cursor_y(1),
440         200,
441         100)
442 {
443         this->parent_window = parent_window;
444         this->asset = asset;
445 }
446
447 PNGConfigVideo::~PNGConfigVideo()
448 {
449 }
450
451 void PNGConfigVideo::create_objects()
452 {
453         int x = 10, y = 10;
454         lock_window("PNGConfigVideo::create_objects");
455         add_subwindow(new PNGUseAlpha(this, x, y));
456         add_subwindow(new BC_OKButton(this));
457         show_window(1);
458         unlock_window();
459 }
460
461 int PNGConfigVideo::close_event()
462 {
463         set_done(0);
464         return 1;
465 }
466
467
468 PNGUseAlpha::PNGUseAlpha(PNGConfigVideo *gui, int x, int y)
469  : BC_CheckBox(x, y, gui->asset->png_use_alpha, _("Use alpha"))
470 {
471         this->gui = gui;
472 }
473
474 int PNGUseAlpha::handle_event()
475 {
476         gui->asset->png_use_alpha = get_value();
477         return 1;
478 }
479
480
481