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