Merge branch 'ct' of git.pipapo.org:cinelerra-ct into ct
[cinelerra_cv/ct.git] / cinelerra / filepng.C
blob6646d3e5f532ae6d4964a138c4b1f21e11df0d4d
1 #include "asset.h"
2 #include "bcwidgetgrid.h"
3 #include "edit.h"
4 #include "file.h"
5 #include "filepng.h"
6 #include "interlacemodes.h"
7 #include "language.h"
8 #include "mwindow.inc"
9 #include "quicktime.h"
10 #include "vframe.h"
11 #include "videodevice.inc"
12 #include "mainerror.h"
14 #include <png.h>
16 FilePNG::FilePNG(Asset_GC asset, File *file)
17  : FileList(asset, file, "PNGLIST", ".png", FILE_PNG, FILE_PNG_LIST)
21 FilePNG::~FilePNG()
27 int FilePNG::check_sig(Asset_GC asset)
29         FILE *stream = fopen(asset->path, "rb");
31         if(stream)
32         {
34 //printf("FilePNG::check_sig 1\n");
35                 char test[16];
36                 fread(test, 16, 1, stream);
37                 fclose(stream);
39                 if(png_check_sig((unsigned char*)test, 8))
40                 {
41 //printf("FilePNG::check_sig 1\n");
42                         return 1;
43                 }
44                 else
45                 if(test[0] == 'P' && test[1] == 'N' && test[2] == 'G' && 
46                         test[3] == 'L' && test[4] == 'I' && test[5] == 'S' && test[6] == 'T')
47                 {
48 //printf("FilePNG::check_sig 1\n");
49                         return 1;
50                 }
51         }
52         return 0;
57 void FilePNG::get_parameters(BC_WindowBase *parent_window, 
58         Asset_GC asset, 
59         BC_WindowBase* &format_window,
60         int audio_options,
61         int video_options)
63         if(video_options)
64         {
65                 PNGConfigVideo *window = new PNGConfigVideo(parent_window, asset);
66                 format_window = window;
67                 window->create_objects();
68                 window->run_window();
69                 delete window;
70         }
76 int FilePNG::can_copy_from(Edit *edit, int64_t position)
78         if(edit->asset->format == FILE_MOV)
79         {
80                 if(match4(edit->asset->vcodec, QUICKTIME_PNG)) return 1;
81         }
82         else
83         if(edit->asset->format == FILE_PNG || 
84                 edit->asset->format == FILE_PNG_LIST)
85                 return 1;
87         return 0;
91 int FilePNG::colormodel_supported(int colormodel)
93         if (((colormodel == BC_RGBA8888) && (native_cmodel == BC_RGBA16161616))
94             || ((colormodel == BC_RGB161616) && (native_cmodel == BC_RGBA16161616))
95             || (colormodel == BC_RGB888))
96         {
97             return colormodel;
98         }
99         else if ((colormodel == BC_RGB161616) && (native_cmodel == BC_RGBA8888))
100         {
101             return BC_RGB888;
102         }
103         else
104         {
105             return native_cmodel;
106         }
110 int FilePNG::get_best_colormodel(Asset_GC asset, int driver)
112         if(asset->png_use_alpha)
113                 return BC_RGBA8888;
114         else
115                 return BC_RGB888;
121 int FilePNG::read_frame_header(char *path)
123         int result = 0;
124         int color_type;
125         int color_depth;
126         int num_trans = 0;
127         
128         FILE *stream;
130         if(!(stream = fopen(path, "rb")))
131         {
132                 eprintf("Error while opening \"%s\" for reading. \n%m\n", asset->path);
133                 return 1;
134         }
136         png_structp png_ptr;
137         png_infop info_ptr;
138         png_infop end_info = 0; 
139         png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
140         info_ptr = png_create_info_struct(png_ptr);
141         png_init_io(png_ptr, stream);
144         png_read_info(png_ptr, info_ptr);
146         asset->width = png_get_image_width(png_ptr, info_ptr);
147         asset->height = png_get_image_height(png_ptr, info_ptr);
148         
149         asset->interlace_mode = BC_ILACE_MODE_NOTINTERLACED;
151         color_type = png_get_color_type(png_ptr, info_ptr);
152         color_depth = png_get_bit_depth(png_ptr,info_ptr);
153         
154         png_get_tRNS(png_ptr, info_ptr, NULL, &num_trans, NULL);
155         
156         if (color_depth == 16)
157         {
158             if (color_type & PNG_COLOR_MASK_ALPHA)
159             {
160                 native_cmodel = BC_RGBA16161616;
161             }
162             else
163             {
164                 native_cmodel = BC_RGB161616;
165             }
166         }
167         else 
168         if ((color_type & PNG_COLOR_MASK_ALPHA)
169             || (num_trans > 0))
170         {
171             native_cmodel = BC_RGBA8888;
172         }
173         else
174         {
175             native_cmodel = BC_RGB888;
176         }
179         png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
180         fclose(stream);
181         
182         
183         
184         return result;
190 static void read_function(png_structp png_ptr, 
191         png_bytep data, 
192         png_uint_32 length)
194         VFrame *input = (VFrame*)png_get_io_ptr(png_ptr);
196         memcpy(data, input->get_data() + input->get_compressed_size(), length);
197         input->set_compressed_size(input->get_compressed_size() + length);
200 static void write_function(png_structp png_ptr, png_bytep data, png_uint_32 length)
202         VFrame *output = (VFrame*)png_get_io_ptr(png_ptr);
204         if(output->get_compressed_allocated() < output->get_compressed_size() + length)
205                 output->allocate_compressed_data((output->get_compressed_allocated() + length) * 2);
206         memcpy(output->get_data() + output->get_compressed_size(), data, length);
207         output->set_compressed_size(output->get_compressed_size() + length);
210 static void flush_function(png_structp png_ptr)
212         ;
217 int FilePNG::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit)
219         PNGUnit *png_unit = (PNGUnit*)unit;
220         int result = 0;
221         png_structp png_ptr;
222         png_infop info_ptr;
223         png_infop end_info = 0; 
224         VFrame *output_frame;
225         data->set_compressed_size(0);
227 //printf("FilePNG::write_frame 1\n");
228         png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
229         info_ptr = png_create_info_struct(png_ptr);
230         png_set_write_fn(png_ptr,
231                data, 
232                            (png_rw_ptr)write_function,
233                (png_flush_ptr)flush_function);
234         png_set_compression_level(png_ptr, 9);
236         png_set_IHDR(png_ptr, 
237                 info_ptr, 
238                 asset->width, 
239                 asset->height,
240         8, 
241                 asset->png_use_alpha ? 
242                   PNG_COLOR_TYPE_RGB_ALPHA : 
243                   PNG_COLOR_TYPE_RGB, 
244                 PNG_INTERLACE_NONE, 
245                 PNG_COMPRESSION_TYPE_DEFAULT, 
246                 PNG_FILTER_TYPE_DEFAULT);
247         png_write_info(png_ptr, info_ptr);
249 //printf("FilePNG::write_frame 1\n");
250         native_cmodel = asset->png_use_alpha ? BC_RGBA8888 : BC_RGB888;
251         if(frame->get_color_model() != native_cmodel)
252         {
253                 if(!png_unit->temp_frame) png_unit->temp_frame = new VFrame(0, 
254                         asset->width, 
255                         asset->height, 
256                         native_cmodel);
258                 cmodel_transfer(png_unit->temp_frame->get_rows(), /* Leave NULL if non existent */
259                         frame->get_rows(),
260                         png_unit->temp_frame->get_y(), /* Leave NULL if non existent */
261                         png_unit->temp_frame->get_u(),
262                         png_unit->temp_frame->get_v(),
263                         frame->get_y(), /* Leave NULL if non existent */
264                         frame->get_u(),
265                         frame->get_v(),
266                         0,        /* Dimensions to capture from input frame */
267                         0, 
268                         asset->width, 
269                         asset->height,
270                         0,       /* Dimensions to project on output frame */
271                         0, 
272                         asset->width, 
273                         asset->height,
274                         frame->get_color_model(), 
275                         png_unit->temp_frame->get_color_model(),
276                         0,         /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
277                         asset->width,       /* For planar use the luma rowspan */
278                         asset->height);
279                 
280                 output_frame = png_unit->temp_frame;
281         }
282         else
283                 output_frame = frame;
286 //printf("FilePNG::write_frame 2\n");
287         png_write_image(png_ptr, output_frame->get_rows());
288         png_write_end(png_ptr, info_ptr);
289         png_destroy_write_struct(&png_ptr, &info_ptr);
290 //printf("FilePNG::write_frame 3 %d\n", data->get_compressed_size());
292         return result;
295 int FilePNG::read_frame(VFrame *output, VFrame *input)
297         png_structp png_ptr;
298         png_infop info_ptr;
299         png_infop end_info = 0; 
300         int result = 0;
301         int color_type;
302         int color_depth;
303         int colormodel;
304         int size = input->get_compressed_size();
305         input->set_compressed_size(0);
306         
307         
308         //printf("FilePNG::read_frame 1 %d %d\n", native_cmodel, output->get_color_model());
309         png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
310         info_ptr = png_create_info_struct(png_ptr);
311         png_set_read_fn(png_ptr, input, (png_rw_ptr)read_function);
312         png_read_info(png_ptr, info_ptr);
314         int png_color_type = png_get_color_type(png_ptr, info_ptr);
315         if (png_color_type == PNG_COLOR_TYPE_GRAY ||
316                 png_color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
317         {
318                 png_set_gray_to_rgb(png_ptr);
319         }
321         colormodel = output->get_color_model();
322         color_type = png_get_color_type(png_ptr, info_ptr);
323         color_depth = png_get_bit_depth(png_ptr,info_ptr);
324         
325         if (((native_cmodel == BC_RGBA16161616)||(native_cmodel == BC_RGB161616))
326             && ((colormodel == BC_RGBA8888)||(colormodel == BC_RGB888)))
327         {
328             png_set_strip_16(png_ptr);
329         }
331         /* If we're dropping the alpha channel, use the background color of the image
332            otherwise, use black */
333         if (((native_cmodel == BC_RGBA16161616)||(native_cmodel == BC_RGBA8888))
334             && ((colormodel == BC_RGB161616)||(colormodel == BC_RGB888)))
335         {
336             png_color_16 my_background;
337             png_color_16p image_background;
338             
339             memset(&my_background,0,sizeof(png_color_16));
340             
341             if (png_get_bKGD(png_ptr, info_ptr, &image_background))
342             {
343                 png_set_background(png_ptr, image_background, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
344             }
345             else
346             {
347                 png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
348             }
349         }
350         
351         /* Little endian */
352         if ((color_depth == 16)
353             &&((colormodel == BC_RGBA16161616)||(colormodel == BC_RGB161616)))
354         {
355             png_set_swap(png_ptr);
356         }
357         
358         if (!(color_type & PNG_COLOR_MASK_COLOR))
359         {
360             png_set_gray_to_rgb(png_ptr);
361         }
362         
363         if (color_type & PNG_COLOR_MASK_PALETTE)
364         {
365             png_set_palette_to_rgb(png_ptr);
366         }
367         
368         if (color_depth <= 8)
369         {
370             png_set_expand(png_ptr);
371         }
373 /* read the image */
374         png_read_image(png_ptr, output->get_rows());
375 //printf("FilePNG::read_frame 3\n");
376         png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
378         input->set_compressed_size(size);
380 //printf("FilePNG::read_frame 4\n");
381         return result;
384 FrameWriterUnit* FilePNG::new_writer_unit(FrameWriter *writer)
386         return new PNGUnit(this, writer);
400 PNGUnit::PNGUnit(FilePNG *file, FrameWriter *writer)
401  : FrameWriterUnit(writer)
403         this->file = file;
404         temp_frame = 0;
406 PNGUnit::~PNGUnit()
408         if(temp_frame) delete temp_frame;
419 PNGConfigVideo::PNGConfigVideo(BC_WindowBase *parent_window, Asset_GC asset)
420  : BC_Window(PROGRAM_NAME ": Video Compression",
421         parent_window->get_abs_cursor_x(1),
422         parent_window->get_abs_cursor_y(1),
423         200,
424         100,
425         200,
426         100,
427         0,
428         1)
430         this->parent_window = parent_window;
431         this->asset = asset;
434 PNGConfigVideo::~PNGConfigVideo()
438 int PNGConfigVideo::create_objects()
440         int x = 10, y = 10;
442         BC_WidgetGrid *wg;
443         BC_RelocatableWidget *rw;
445         wg = add_widgetgrid(new BC_WidgetGrid(10, 10, 10, 10, 3, 3));
447         rw =
448         add_subwindow(new PNGUseAlpha(this, x, y));
449         wg->add(rw, 0, 0);
451         rw =
452         add_subwindow(new BC_OKButton(this));
454         wg->move_widgets();
455         resize_window(wg->get_w_wm(), wg->get_h_wm() + rw->get_h());
456         return 0;
459 int PNGConfigVideo::close_event()
461         set_done(0);
462         return 1;
466 PNGUseAlpha::PNGUseAlpha(PNGConfigVideo *gui, int x, int y)
467  : BC_CheckBox(x, y, gui->asset->png_use_alpha, _("Use alpha"))
469         this->gui = gui;
472 int PNGUseAlpha::handle_event()
474         gui->asset->png_use_alpha = get_value();
475         return 1;
481 //      Local Variables:
482 //      mode: C++
483 //      c-file-style: "linux"
484 //      End: