4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
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.
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.
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
27 #include "mwindow.inc"
28 #include "quicktime.h"
30 #include "videodevice.inc"
34 FilePNG::FilePNG(Asset *asset, File *file)
35 : FileList(asset, file, "PNGLIST", ".png", FILE_PNG, FILE_PNG_LIST)
45 int FilePNG::check_sig(Asset *asset)
47 FILE *stream = fopen(asset->path, "rb");
52 //printf("FilePNG::check_sig 1\n");
54 int temp = fread(test, 16, 1, stream);
57 if(png_check_sig((unsigned char*)test, 8))
59 //printf("FilePNG::check_sig 1\n");
63 if(test[0] == 'P' && test[1] == 'N' && test[2] == 'G' &&
64 test[3] == 'L' && test[4] == 'I' && test[5] == 'S' && test[6] == 'T')
66 //printf("FilePNG::check_sig 1\n");
75 void FilePNG::get_parameters(BC_WindowBase *parent_window,
77 BC_WindowBase* &format_window,
83 PNGConfigVideo *window = new PNGConfigVideo(parent_window, asset);
84 format_window = window;
85 window->create_objects();
94 int FilePNG::can_copy_from(Asset *asset, int64_t position)
96 if(asset->format == FILE_MOV)
98 if(match4(asset->vcodec, QUICKTIME_PNG)) return 1;
101 if(asset->format == FILE_PNG ||
102 asset->format == FILE_PNG_LIST)
109 int FilePNG::colormodel_supported(int colormodel)
111 if (((colormodel == BC_RGBA8888) && (native_cmodel == BC_RGBA16161616))
112 || ((colormodel == BC_RGB161616) && (native_cmodel == BC_RGBA16161616))
113 || (colormodel == BC_RGB888))
117 else if ((colormodel == BC_RGB161616) && (native_cmodel == BC_RGBA8888))
123 return native_cmodel;
128 int FilePNG::get_best_colormodel(Asset *asset, int driver)
130 if(asset->png_use_alpha)
139 int FilePNG::read_frame_header(char *path)
148 if(!(stream = fopen(path, "rb")))
150 perror("FilePNG::read_frame_header");
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);
162 png_read_info(png_ptr, info_ptr);
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);
169 png_get_tRNS(png_ptr, info_ptr, NULL, &num_trans, NULL);
171 if (color_depth == 16)
173 if (color_type & PNG_COLOR_MASK_ALPHA)
175 native_cmodel = BC_RGBA16161616;
179 native_cmodel = BC_RGB161616;
183 if ((color_type & PNG_COLOR_MASK_ALPHA)
186 native_cmodel = BC_RGBA8888;
190 native_cmodel = BC_RGB888;
194 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
205 static void read_function(png_structp png_ptr,
209 VFrame *input = (VFrame*)png_get_io_ptr(png_ptr);
211 memcpy(data, input->get_data() + input->get_compressed_size(), length);
212 input->set_compressed_size(input->get_compressed_size() + length);
215 static void write_function(png_structp png_ptr, png_bytep data, png_uint_32 length)
217 VFrame *output = (VFrame*)png_get_io_ptr(png_ptr);
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);
225 static void flush_function(png_structp png_ptr)
232 int FilePNG::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit)
234 PNGUnit *png_unit = (PNGUnit*)unit;
238 png_infop end_info = 0;
239 VFrame *output_frame;
240 data->set_compressed_size(0);
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,
247 (png_rw_ptr)write_function,
248 (png_flush_ptr)flush_function);
249 png_set_compression_level(png_ptr, 9);
251 png_set_IHDR(png_ptr,
256 asset->png_use_alpha ?
257 PNG_COLOR_TYPE_RGB_ALPHA :
260 PNG_COMPRESSION_TYPE_DEFAULT,
261 PNG_FILTER_TYPE_DEFAULT);
262 png_write_info(png_ptr, info_ptr);
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)
268 if(!png_unit->temp_frame) png_unit->temp_frame = new VFrame(0,
275 BC_CModels::transfer(png_unit->temp_frame->get_rows(), /* Leave NULL if non existent */
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 */
283 0, /* Dimensions to capture from input frame */
287 0, /* Dimensions to project on output frame */
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 */
297 output_frame = png_unit->temp_frame;
300 output_frame = frame;
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());
312 int FilePNG::read_frame(VFrame *output, VFrame *input)
316 png_infop end_info = 0;
321 int size = input->get_compressed_size();
322 input->set_compressed_size(0);
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);
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)
335 png_set_gray_to_rgb(png_ptr);
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);
342 if (((native_cmodel == BC_RGBA16161616)||(native_cmodel == BC_RGB161616))
343 && ((colormodel == BC_RGBA8888)||(colormodel == BC_RGB888)))
345 png_set_strip_16(png_ptr);
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)))
353 png_color_16 my_background;
354 png_color_16p image_background;
356 memset(&my_background,0,sizeof(png_color_16));
358 if (png_get_bKGD(png_ptr, info_ptr, &image_background))
360 png_set_background(png_ptr, image_background, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
364 png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
369 if ((color_depth == 16)
370 &&((colormodel == BC_RGBA16161616)||(colormodel == BC_RGB161616)))
372 png_set_swap(png_ptr);
375 if (!(color_type & PNG_COLOR_MASK_COLOR))
377 png_set_gray_to_rgb(png_ptr);
380 if (color_type & PNG_COLOR_MASK_PALETTE)
382 png_set_palette_to_rgb(png_ptr);
385 if (color_depth <= 8)
387 png_set_expand(png_ptr);
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);
395 input->set_compressed_size(size);
397 //printf("FilePNG::read_frame 4\n");
401 FrameWriterUnit* FilePNG::new_writer_unit(FrameWriter *writer)
403 return new PNGUnit(this, writer);
417 PNGUnit::PNGUnit(FilePNG *file, FrameWriter *writer)
418 : FrameWriterUnit(writer)
425 if(temp_frame) delete temp_frame;
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),
443 this->parent_window = parent_window;
447 PNGConfigVideo::~PNGConfigVideo()
451 void PNGConfigVideo::create_objects()
454 lock_window("PNGConfigVideo::create_objects");
455 add_subwindow(new PNGUseAlpha(this, x, y));
456 add_subwindow(new BC_OKButton(this));
461 int PNGConfigVideo::close_event()
468 PNGUseAlpha::PNGUseAlpha(PNGConfigVideo *gui, int x, int y)
469 : BC_CheckBox(x, y, gui->asset->png_use_alpha, _("Use alpha"))
474 int PNGUseAlpha::handle_event()
476 gui->asset->png_use_alpha = get_value();