00001 #include "asset.h"
00002 #include "edit.h"
00003 #include "file.h"
00004 #include "filepng.h"
00005 #include "interlacemodes.h"
00006 #include "language.h"
00007 #include "mwindow.inc"
00008 #include "quicktime.h"
00009 #include "vframe.h"
00010 #include "videodevice.inc"
00011
00012 #include <png.h>
00013
00014 FilePNG::FilePNG(Asset *asset, File *file)
00015 : FileList(asset, file, "PNGLIST", ".png", FILE_PNG, FILE_PNG_LIST)
00016 {
00017 }
00018
00019 FilePNG::~FilePNG()
00020 {
00021 }
00022
00023
00024
00025 int FilePNG::check_sig(Asset *asset)
00026 {
00027 FILE *stream = fopen(asset->path, "rb");
00028
00029 if(stream)
00030 {
00031
00032
00033 char test[16];
00034 fread(test, 16, 1, stream);
00035 fclose(stream);
00036
00037 if(png_check_sig((unsigned char*)test, 8))
00038 {
00039
00040 return 1;
00041 }
00042 else
00043 if(test[0] == 'P' && test[1] == 'N' && test[2] == 'G' &&
00044 test[3] == 'L' && test[4] == 'I' && test[5] == 'S' && test[6] == 'T')
00045 {
00046
00047 return 1;
00048 }
00049 }
00050 return 0;
00051 }
00052
00053
00054
00055 void FilePNG::get_parameters(BC_WindowBase *parent_window,
00056 Asset *asset,
00057 BC_WindowBase* &format_window,
00058 int audio_options,
00059 int video_options)
00060 {
00061 if(video_options)
00062 {
00063 PNGConfigVideo *window = new PNGConfigVideo(parent_window, asset);
00064 format_window = window;
00065 window->create_objects();
00066 window->run_window();
00067 delete window;
00068 }
00069 }
00070
00071
00072
00073
00074 int FilePNG::can_copy_from(Edit *edit, int64_t position)
00075 {
00076 if(edit->asset->format == FILE_MOV)
00077 {
00078 if(match4(edit->asset->vcodec, QUICKTIME_PNG)) return 1;
00079 }
00080 else
00081 if(edit->asset->format == FILE_PNG ||
00082 edit->asset->format == FILE_PNG_LIST)
00083 return 1;
00084
00085 return 0;
00086 }
00087
00088
00089 int FilePNG::colormodel_supported(int colormodel)
00090 {
00091 if (((colormodel == BC_RGBA8888) && (native_cmodel == BC_RGBA16161616))
00092 || ((colormodel == BC_RGB161616) && (native_cmodel == BC_RGBA16161616))
00093 || (colormodel == BC_RGB888))
00094 {
00095 return colormodel;
00096 }
00097 else if ((colormodel == BC_RGB161616) && (native_cmodel == BC_RGBA8888))
00098 {
00099 return BC_RGB888;
00100 }
00101 else
00102 {
00103 return native_cmodel;
00104 }
00105 }
00106
00107
00108 int FilePNG::get_best_colormodel(Asset *asset, int driver)
00109 {
00110 if(asset->png_use_alpha)
00111 return BC_RGBA8888;
00112 else
00113 return BC_RGB888;
00114 }
00115
00116
00117
00118
00119 int FilePNG::read_frame_header(char *path)
00120 {
00121 int result = 0;
00122 int color_type;
00123 int color_depth;
00124 int num_trans = 0;
00125
00126 FILE *stream;
00127
00128 if(!(stream = fopen(path, "rb")))
00129 {
00130 perror("FilePNG::read_frame_header");
00131 return 1;
00132 }
00133
00134 png_structp png_ptr;
00135 png_infop info_ptr;
00136 png_infop end_info = 0;
00137 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
00138 info_ptr = png_create_info_struct(png_ptr);
00139 png_init_io(png_ptr, stream);
00140
00141
00142 png_read_info(png_ptr, info_ptr);
00143
00144 asset->width = png_get_image_width(png_ptr, info_ptr);
00145 asset->height = png_get_image_height(png_ptr, info_ptr);
00146
00147 asset->interlace_mode = BC_ILACE_MODE_NOTINTERLACED;
00148
00149 color_type = png_get_color_type(png_ptr, info_ptr);
00150 color_depth = png_get_bit_depth(png_ptr,info_ptr);
00151
00152 png_get_tRNS(png_ptr, info_ptr, NULL, &num_trans, NULL);
00153
00154 if (color_depth == 16)
00155 {
00156 if (color_type & PNG_COLOR_MASK_ALPHA)
00157 {
00158 native_cmodel = BC_RGBA16161616;
00159 }
00160 else
00161 {
00162 native_cmodel = BC_RGB161616;
00163 }
00164 }
00165 else
00166 if ((color_type & PNG_COLOR_MASK_ALPHA)
00167 || (num_trans > 0))
00168 {
00169 native_cmodel = BC_RGBA8888;
00170 }
00171 else
00172 {
00173 native_cmodel = BC_RGB888;
00174 }
00175
00176
00177 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
00178 fclose(stream);
00179
00180
00181
00182 return result;
00183 }
00184
00185
00186
00187
00188 static void read_function(png_structp png_ptr,
00189 png_bytep data,
00190 png_uint_32 length)
00191 {
00192 VFrame *input = (VFrame*)png_get_io_ptr(png_ptr);
00193
00194 memcpy(data, input->get_data() + input->get_compressed_size(), length);
00195 input->set_compressed_size(input->get_compressed_size() + length);
00196 }
00197
00198 static void write_function(png_structp png_ptr, png_bytep data, png_uint_32 length)
00199 {
00200 VFrame *output = (VFrame*)png_get_io_ptr(png_ptr);
00201
00202 if(output->get_compressed_allocated() < output->get_compressed_size() + length)
00203 output->allocate_compressed_data((output->get_compressed_allocated() + length) * 2);
00204 memcpy(output->get_data() + output->get_compressed_size(), data, length);
00205 output->set_compressed_size(output->get_compressed_size() + length);
00206 }
00207
00208 static void flush_function(png_structp png_ptr)
00209 {
00210 ;
00211 }
00212
00213
00214
00215 int FilePNG::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit)
00216 {
00217 PNGUnit *png_unit = (PNGUnit*)unit;
00218 int result = 0;
00219 png_structp png_ptr;
00220 png_infop info_ptr;
00221 png_infop end_info = 0;
00222 VFrame *output_frame;
00223 data->set_compressed_size(0);
00224
00225
00226 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
00227 info_ptr = png_create_info_struct(png_ptr);
00228 png_set_write_fn(png_ptr,
00229 data,
00230 (png_rw_ptr)write_function,
00231 (png_flush_ptr)flush_function);
00232 png_set_compression_level(png_ptr, 9);
00233
00234 png_set_IHDR(png_ptr,
00235 info_ptr,
00236 asset->width,
00237 asset->height,
00238 8,
00239 asset->png_use_alpha ?
00240 PNG_COLOR_TYPE_RGB_ALPHA :
00241 PNG_COLOR_TYPE_RGB,
00242 PNG_INTERLACE_NONE,
00243 PNG_COMPRESSION_TYPE_DEFAULT,
00244 PNG_FILTER_TYPE_DEFAULT);
00245 png_write_info(png_ptr, info_ptr);
00246
00247
00248 native_cmodel = asset->png_use_alpha ? BC_RGBA8888 : BC_RGB888;
00249 if(frame->get_color_model() != native_cmodel)
00250 {
00251 if(!png_unit->temp_frame) png_unit->temp_frame = new VFrame(0,
00252 asset->width,
00253 asset->height,
00254 native_cmodel);
00255
00256 cmodel_transfer(png_unit->temp_frame->get_rows(),
00257 frame->get_rows(),
00258 png_unit->temp_frame->get_y(),
00259 png_unit->temp_frame->get_u(),
00260 png_unit->temp_frame->get_v(),
00261 frame->get_y(),
00262 frame->get_u(),
00263 frame->get_v(),
00264 0,
00265 0,
00266 asset->width,
00267 asset->height,
00268 0,
00269 0,
00270 asset->width,
00271 asset->height,
00272 frame->get_color_model(),
00273 png_unit->temp_frame->get_color_model(),
00274 0,
00275 asset->width,
00276 asset->height);
00277
00278 output_frame = png_unit->temp_frame;
00279 }
00280 else
00281 output_frame = frame;
00282
00283
00284
00285 png_write_image(png_ptr, output_frame->get_rows());
00286 png_write_end(png_ptr, info_ptr);
00287 png_destroy_write_struct(&png_ptr, &info_ptr);
00288
00289
00290 return result;
00291 }
00292
00293 int FilePNG::read_frame(VFrame *output, VFrame *input)
00294 {
00295 png_structp png_ptr;
00296 png_infop info_ptr;
00297 png_infop end_info = 0;
00298 int result = 0;
00299 int color_type;
00300 int color_depth;
00301 int colormodel;
00302 int size = input->get_compressed_size();
00303 input->set_compressed_size(0);
00304
00305
00306
00307 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
00308 info_ptr = png_create_info_struct(png_ptr);
00309 png_set_read_fn(png_ptr, input, (png_rw_ptr)read_function);
00310 png_read_info(png_ptr, info_ptr);
00311
00312 int png_color_type = png_get_color_type(png_ptr, info_ptr);
00313 if (png_color_type == PNG_COLOR_TYPE_GRAY ||
00314 png_color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
00315 {
00316 png_set_gray_to_rgb(png_ptr);
00317 }
00318
00319 colormodel = output->get_color_model();
00320 color_type = png_get_color_type(png_ptr, info_ptr);
00321 color_depth = png_get_bit_depth(png_ptr,info_ptr);
00322
00323 if (((native_cmodel == BC_RGBA16161616)||(native_cmodel == BC_RGB161616))
00324 && ((colormodel == BC_RGBA8888)||(colormodel == BC_RGB888)))
00325 {
00326 png_set_strip_16(png_ptr);
00327 }
00328
00329
00330
00331 if (((native_cmodel == BC_RGBA16161616)||(native_cmodel == BC_RGBA8888))
00332 && ((colormodel == BC_RGB161616)||(colormodel == BC_RGB888)))
00333 {
00334 png_color_16 my_background;
00335 png_color_16p image_background;
00336
00337 memset(&my_background,0,sizeof(png_color_16));
00338
00339 if (png_get_bKGD(png_ptr, info_ptr, &image_background))
00340 {
00341 png_set_background(png_ptr, image_background, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
00342 }
00343 else
00344 {
00345 png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
00346 }
00347 }
00348
00349
00350 if ((color_depth == 16)
00351 &&((colormodel == BC_RGBA16161616)||(colormodel == BC_RGB161616)))
00352 {
00353 png_set_swap(png_ptr);
00354 }
00355
00356 if (!(color_type & PNG_COLOR_MASK_COLOR))
00357 {
00358 png_set_gray_to_rgb(png_ptr);
00359 }
00360
00361 if (color_type & PNG_COLOR_MASK_PALETTE)
00362 {
00363 png_set_palette_to_rgb(png_ptr);
00364 }
00365
00366 if (color_depth <= 8)
00367 {
00368 png_set_expand(png_ptr);
00369 }
00370
00371
00372 png_read_image(png_ptr, output->get_rows());
00373
00374 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
00375
00376 input->set_compressed_size(size);
00377
00378
00379 return result;
00380 }
00381
00382 FrameWriterUnit* FilePNG::new_writer_unit(FrameWriter *writer)
00383 {
00384 return new PNGUnit(this, writer);
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398 PNGUnit::PNGUnit(FilePNG *file, FrameWriter *writer)
00399 : FrameWriterUnit(writer)
00400 {
00401 this->file = file;
00402 temp_frame = 0;
00403 }
00404 PNGUnit::~PNGUnit()
00405 {
00406 if(temp_frame) delete temp_frame;
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 PNGConfigVideo::PNGConfigVideo(BC_WindowBase *parent_window, Asset *asset)
00418 : BC_Window(PROGRAM_NAME ": Video Compression",
00419 parent_window->get_abs_cursor_x(1),
00420 parent_window->get_abs_cursor_y(1),
00421 200,
00422 100)
00423 {
00424 this->parent_window = parent_window;
00425 this->asset = asset;
00426 }
00427
00428 PNGConfigVideo::~PNGConfigVideo()
00429 {
00430 }
00431
00432 int PNGConfigVideo::create_objects()
00433 {
00434 int x = 10, y = 10;
00435 add_subwindow(new PNGUseAlpha(this, x, y));
00436 add_subwindow(new BC_OKButton(this));
00437 return 0;
00438 }
00439
00440 int PNGConfigVideo::close_event()
00441 {
00442 set_done(0);
00443 return 1;
00444 }
00445
00446
00447 PNGUseAlpha::PNGUseAlpha(PNGConfigVideo *gui, int x, int y)
00448 : BC_CheckBox(x, y, gui->asset->png_use_alpha, _("Use alpha"))
00449 {
00450 this->gui = gui;
00451 }
00452
00453 int PNGUseAlpha::handle_event()
00454 {
00455 gui->asset->png_use_alpha = get_value();
00456 return 1;
00457 }
00458
00459
00460