X-Git-Url: http://git.cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Ffilepng.C;fp=cinelerra-5.1%2Fcinelerra%2Ffilepng.C;h=f1ee1c06fd283cce8f10dd4dc515197157511ca6;hb=30bdb85eb33a8ee7ba675038a86c6be59c43d7bd;hp=0000000000000000000000000000000000000000;hpb=52fcc46226f9df46f9ce9d0566dc568455a7db0b;p=goodguy%2Fhistory.git diff --git a/cinelerra-5.1/cinelerra/filepng.C b/cinelerra-5.1/cinelerra/filepng.C new file mode 100644 index 00000000..f1ee1c06 --- /dev/null +++ b/cinelerra-5.1/cinelerra/filepng.C @@ -0,0 +1,450 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "asset.h" +#include "edit.h" +#include "file.h" +#include "filepng.h" +#include "interlacemodes.h" +#include "language.h" +#include "mwindow.inc" +#include "vframe.h" +#include "videodevice.inc" +#include "mainerror.h" + +#include +#include + +FilePNG::FilePNG(Asset *asset, File *file) + : FileList(asset, file, "PNGLIST", ".png", FILE_PNG, FILE_PNG_LIST) +{ +} + +FilePNG::~FilePNG() +{ +} + + + +int FilePNG::check_sig(Asset *asset) +{ + FILE *stream = fopen(asset->path, "rb"); + + if(stream) + { + +//printf("FilePNG::check_sig 1\n"); + char test[16]; + (void)fread(test, 16, 1, stream); + fclose(stream); + +// if(png_sig_cmp((unsigned char*)test, 0, 8)) + if(png_check_sig((unsigned char*)test, 8)) + { +//printf("FilePNG::check_sig 1\n"); + return 1; + } + else + if(test[0] == 'P' && test[1] == 'N' && test[2] == 'G' && + test[3] == 'L' && test[4] == 'I' && test[5] == 'S' && test[6] == 'T') + { +//printf("FilePNG::check_sig 1\n"); + return 1; + } + } + return 0; +} + + + +void FilePNG::get_parameters(BC_WindowBase *parent_window, + Asset *asset, + BC_WindowBase* &format_window, + int audio_options, + int video_options) +{ + if(video_options) + { + PNGConfigVideo *window = new PNGConfigVideo(parent_window, asset); + format_window = window; + window->create_objects(); + window->run_window(); + delete window; + } +} + + + + +int FilePNG::can_copy_from(Asset *asset, int64_t position) +{ + if(asset->format == FILE_PNG || + asset->format == FILE_PNG_LIST) + return 1; + + return 0; +} + + +int FilePNG::colormodel_supported(int colormodel) +{ + if (((colormodel == BC_RGBA8888) && (native_cmodel == BC_RGBA16161616)) + || ((colormodel == BC_RGB161616) && (native_cmodel == BC_RGBA16161616)) + || (colormodel == BC_RGB888)) + { + return colormodel; + } + else if ((colormodel == BC_RGB161616) && (native_cmodel == BC_RGBA8888)) + { + return BC_RGB888; + } + else + { + return native_cmodel; + } +} + + +int FilePNG::get_best_colormodel(Asset *asset, int driver) +{ + if(asset->png_use_alpha) + return BC_RGBA8888; + else + return BC_RGB888; +} + + + + +int FilePNG::read_frame_header(char *path) +{ + int result = 0; + int color_type; + int color_depth; + int num_trans = 0; + + FILE *stream; + + if(!(stream = fopen(path, "rb"))) + { + eprintf("Error while opening \"%s\" for reading. \n%m\n", asset->path); + return 1; + } + + png_structp png_ptr; + png_infop info_ptr; + png_infop end_info = 0; + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); + info_ptr = png_create_info_struct(png_ptr); + png_init_io(png_ptr, stream); + + + png_read_info(png_ptr, info_ptr); + + asset->width = png_get_image_width(png_ptr, info_ptr); + asset->height = png_get_image_height(png_ptr, info_ptr); + + asset->interlace_mode = BC_ILACE_MODE_NOTINTERLACED; + + color_type = png_get_color_type(png_ptr, info_ptr); + color_depth = png_get_bit_depth(png_ptr,info_ptr); + + png_get_tRNS(png_ptr, info_ptr, NULL, &num_trans, NULL); + + if (color_depth == 16) + { + if (color_type & PNG_COLOR_MASK_ALPHA) + { + native_cmodel = BC_RGBA16161616; + } + else + { + native_cmodel = BC_RGB161616; + } + } + else + if ((color_type & PNG_COLOR_MASK_ALPHA) + || (num_trans > 0)) + { + native_cmodel = BC_RGBA8888; + } + else + { + native_cmodel = BC_RGB888; + } + + + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + fclose(stream); + + + + return result; +} + + + + +static void read_function(png_structp png_ptr, + png_bytep data, + png_uint_32 length) +{ + VFrame *input = (VFrame*)png_get_io_ptr(png_ptr); + + memcpy(data, input->get_data() + input->get_compressed_size(), length); + input->set_compressed_size(input->get_compressed_size() + length); +} + +static void write_function(png_structp png_ptr, png_bytep data, png_uint_32 length) +{ + VFrame *output = (VFrame*)png_get_io_ptr(png_ptr); + long total_length = output->get_compressed_size() + length; + if(output->get_compressed_allocated() < total_length) { + long new_length = 2 * (output->get_compressed_allocated() + length); + output->allocate_compressed_data(new_length); + } + memcpy(output->get_data() + output->get_compressed_size(), data, length); + output->set_compressed_size(total_length); +} + +static void flush_function(png_structp png_ptr) +{ +} + + +int FilePNG::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit) +{ + PNGUnit *png_unit = (PNGUnit*)unit; + png_structp png_ptr = 0; + png_infop info_ptr = 0; + VFrame *output_frame; + int result = 1; + data->set_compressed_size(0); +//printf("FilePNG::write_frame 1\n"); + native_cmodel = asset->png_use_alpha ? BC_RGBA8888 : BC_RGB888; + if(frame->get_color_model() != native_cmodel) + { + if(!png_unit->temp_frame) png_unit->temp_frame = new VFrame(0, + -1, asset->width, asset->height, native_cmodel, -1); + + png_unit->temp_frame->transfer_from(frame); + output_frame = png_unit->temp_frame; + } + else + output_frame = frame; + +//printf("FilePNG::write_frame 1\n"); + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); + if( png_ptr && !setjmp(png_jmpbuf(png_ptr)) ) { + info_ptr = png_create_info_struct(png_ptr); + png_set_write_fn(png_ptr, data, + (png_rw_ptr)write_function, (png_flush_ptr)flush_function); + png_set_compression_level(png_ptr, 5); + + png_set_IHDR(png_ptr, info_ptr, asset->width, asset->height, 8, + asset->png_use_alpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + png_write_info(png_ptr, info_ptr); + png_write_image(png_ptr, output_frame->get_rows()); + png_write_end(png_ptr, info_ptr); + png_destroy_write_struct(&png_ptr, &info_ptr); + result = 0; + } + else { + char error[256]; png_error(png_ptr, error); + fprintf(stderr, "FilePNG::write_frame failed: %s\n", error); + } + + png_destroy_write_struct(&png_ptr, &info_ptr); +//printf("FilePNG::write_frame 3 %d\n", data->get_compressed_size()); + return result; +} + +int FilePNG::read_frame(VFrame *output, VFrame *input) +{ + png_structp png_ptr; + png_infop info_ptr; + png_infop end_info = 0; + int result = 0; + int color_type; + int color_depth; + int colormodel; + int size = input->get_compressed_size(); + input->set_compressed_size(0); + + + //printf("FilePNG::read_frame 1 %d %d\n", native_cmodel, output->get_color_model()); + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); + info_ptr = png_create_info_struct(png_ptr); + png_set_read_fn(png_ptr, input, (png_rw_ptr)read_function); + png_read_info(png_ptr, info_ptr); + + int png_color_type = png_get_color_type(png_ptr, info_ptr); + if (png_color_type == PNG_COLOR_TYPE_GRAY || + png_color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + png_set_gray_to_rgb(png_ptr); + } + + colormodel = output->get_color_model(); + color_type = png_get_color_type(png_ptr, info_ptr); + color_depth = png_get_bit_depth(png_ptr,info_ptr); + + if (((native_cmodel == BC_RGBA16161616)||(native_cmodel == BC_RGB161616)) + && ((colormodel == BC_RGBA8888)||(colormodel == BC_RGB888))) + { + png_set_strip_16(png_ptr); + } + + /* If we're dropping the alpha channel, use the background color of the image + otherwise, use black */ + if (((native_cmodel == BC_RGBA16161616)||(native_cmodel == BC_RGBA8888)) + && ((colormodel == BC_RGB161616)||(colormodel == BC_RGB888))) + { + png_color_16 my_background; + png_color_16p image_background; + + memset(&my_background,0,sizeof(png_color_16)); + + if (png_get_bKGD(png_ptr, info_ptr, &image_background)) + { + png_set_background(png_ptr, image_background, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + } + else + { + png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + } + } + + /* Little endian */ + if ((color_depth == 16) + &&((colormodel == BC_RGBA16161616)||(colormodel == BC_RGB161616))) + { + png_set_swap(png_ptr); + } + + if (!(color_type & PNG_COLOR_MASK_COLOR)) + { + png_set_gray_to_rgb(png_ptr); + } + + if (color_type & PNG_COLOR_MASK_PALETTE) + { + png_set_palette_to_rgb(png_ptr); + } + + if (color_depth <= 8) + { + png_set_expand(png_ptr); + } + +/* read the image */ + png_read_image(png_ptr, output->get_rows()); +//printf("FilePNG::read_frame 3\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + + input->set_compressed_size(size); + +//printf("FilePNG::read_frame 4\n"); + return result; +} + +FrameWriterUnit* FilePNG::new_writer_unit(FrameWriter *writer) +{ + return new PNGUnit(this, writer); +} + + + + + + + + + + + + +PNGUnit::PNGUnit(FilePNG *file, FrameWriter *writer) + : FrameWriterUnit(writer) +{ + this->file = file; + temp_frame = 0; +} +PNGUnit::~PNGUnit() +{ + if(temp_frame) delete temp_frame; +} + + + + + + + + + +PNGConfigVideo::PNGConfigVideo(BC_WindowBase *parent_window, Asset *asset) + : BC_Window(PROGRAM_NAME ": Video Compression", + parent_window->get_abs_cursor_x(1), + parent_window->get_abs_cursor_y(1), + 200, + 100) +{ + this->parent_window = parent_window; + this->asset = asset; +} + +PNGConfigVideo::~PNGConfigVideo() +{ +} + +void PNGConfigVideo::create_objects() +{ + lock_window("PNGConfigVideo::create_objects()"); + int x = 10, y = 10; + add_subwindow(new PNGUseAlpha(this, x, y)); + add_subwindow(new BC_OKButton(this)); + show_window(1); + unlock_window(); +} + +int PNGConfigVideo::close_event() +{ + set_done(0); + return 1; +} + + +PNGUseAlpha::PNGUseAlpha(PNGConfigVideo *gui, int x, int y) + : BC_CheckBox(x, y, gui->asset->png_use_alpha, _("Use alpha")) +{ + this->gui = gui; +} + +int PNGUseAlpha::handle_event() +{ + gui->asset->png_use_alpha = get_value(); + return 1; +} + + +