r370: Heroine Virutal's official release 1.2.1
[cinelerra_cv/mob.git] / hvirtual / cinelerra / filepng.C
blob6ca6e5db0dc697693a19b04e69e061cca5ad2656
1 #include "asset.h"
2 #include "edit.h"
3 #include "file.h"
4 #include "filepng.h"
5 #include "language.h"
6 #include "mwindow.inc"
7 #include "quicktime.h"
8 #include "vframe.h"
9 #include "videodevice.inc"
11 #include <png.h>
13 FilePNG::FilePNG(Asset *asset, File *file)
14  : FileList(asset, file, "PNGLIST", ".png", FILE_PNG, FILE_PNG_LIST)
18 FilePNG::~FilePNG()
24 int FilePNG::check_sig(Asset *asset)
26         FILE *stream = fopen(asset->path, "rb");
28         if(stream)
29         {
31 //printf("FilePNG::check_sig 1\n");
32                 char test[16];
33                 fread(test, 16, 1, stream);
34                 fclose(stream);
36                 if(png_check_sig((unsigned char*)test, 8))
37                 {
38 //printf("FilePNG::check_sig 1\n");
39                         return 1;
40                 }
41                 else
42                 if(test[0] == 'P' && test[1] == 'N' && test[2] == 'G' && 
43                         test[3] == 'L' && test[4] == 'I' && test[5] == 'S' && test[6] == 'T')
44                 {
45 //printf("FilePNG::check_sig 1\n");
46                         return 1;
47                 }
48         }
49         return 0;
54 void FilePNG::get_parameters(BC_WindowBase *parent_window, 
55         Asset *asset, 
56         BC_WindowBase* &format_window,
57         int audio_options,
58         int video_options)
60         if(video_options)
61         {
62                 PNGConfigVideo *window = new PNGConfigVideo(parent_window, asset);
63                 format_window = window;
64                 window->create_objects();
65                 window->run_window();
66                 delete window;
67         }
73 int FilePNG::can_copy_from(Edit *edit, int64_t position)
75         if(edit->asset->format == FILE_MOV)
76         {
77                 if(match4(edit->asset->vcodec, QUICKTIME_PNG)) return 1;
78         }
79         else
80         if(edit->asset->format == FILE_PNG || 
81                 edit->asset->format == FILE_PNG_LIST)
82                 return 1;
84         return 0;
88 int FilePNG::colormodel_supported(int colormodel)
90         return native_cmodel;
94 int FilePNG::get_best_colormodel(Asset *asset, int driver)
96         if(asset->png_use_alpha)
97                 return BC_RGBA8888;
98         else
99                 return BC_RGB888;
105 int FilePNG::read_frame_header(char *path)
107         int result = 0;
110 //printf("FilePNG::read_frame_header 1\n");
111         FILE *stream;
113         if(!(stream = fopen(path, "rb")))
114         {
115                 perror("FilePNG::read_frame_header");
116                 return 1;
117         }
119 //printf("FilePNG::read_frame_header 1\n");
120         png_structp png_ptr;
121         png_infop info_ptr;
122         png_infop end_info = 0; 
123         png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
124         info_ptr = png_create_info_struct(png_ptr);
125         png_init_io(png_ptr, stream);
127 //printf("FilePNG::read_frame_header 1\n");
129         png_read_info(png_ptr, info_ptr);
131 //printf("FilePNG::read_frame_header 1\n");
132         asset->width = png_get_image_width(png_ptr, info_ptr);
133         asset->height = png_get_image_height(png_ptr, info_ptr);
134         int png_color_type = png_get_color_type(png_ptr, info_ptr);
136 // gray to rgb conversion is done automatically in read_frame 
137         switch (png_color_type)
138         {
139                 case PNG_COLOR_TYPE_GRAY:
140                         png_color_type = PNG_COLOR_TYPE_RGB;
141                         break;
142                 case PNG_COLOR_TYPE_GRAY_ALPHA: 
143                         png_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
144                         break;
145         }
146         native_cmodel = 
147                 png_color_type == PNG_COLOR_TYPE_RGB_ALPHA ?
148                 BC_RGBA8888 :
149                 BC_RGB888;
151 //printf("FilePNG::read_frame_header 1\n");
152         png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
153 //printf("FilePNG::read_frame_header 1\n");
154         fclose(stream);
155         
156 //printf("FilePNG::read_frame_header 2\n");
157         
158         
159         return result;
165 static void read_function(png_structp png_ptr, 
166         png_bytep data, 
167         png_uint_32 length)
169         VFrame *input = (VFrame*)png_get_io_ptr(png_ptr);
171         memcpy(data, input->get_data() + input->get_compressed_size(), length);
172         input->set_compressed_size(input->get_compressed_size() + length);
175 static void write_function(png_structp png_ptr, png_bytep data, png_uint_32 length)
177         VFrame *output = (VFrame*)png_get_io_ptr(png_ptr);
179         if(output->get_compressed_allocated() < output->get_compressed_size() + length)
180                 output->allocate_compressed_data((output->get_compressed_allocated() + length) * 2);
181         memcpy(output->get_data() + output->get_compressed_size(), data, length);
182         output->set_compressed_size(output->get_compressed_size() + length);
185 static void flush_function(png_structp png_ptr)
187         ;
192 int FilePNG::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit)
194         PNGUnit *png_unit = (PNGUnit*)unit;
195         int result = 0;
196         png_structp png_ptr;
197         png_infop info_ptr;
198         png_infop end_info = 0; 
199         VFrame *output_frame;
200         data->set_compressed_size(0);
202 //printf("FilePNG::write_frame 1\n");
203         png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
204         info_ptr = png_create_info_struct(png_ptr);
205         png_set_write_fn(png_ptr,
206                data, 
207                            (png_rw_ptr)write_function,
208                (png_flush_ptr)flush_function);
209         png_set_compression_level(png_ptr, 9);
211         png_set_IHDR(png_ptr, 
212                 info_ptr, 
213                 asset->width, 
214                 asset->height,
215         8, 
216                 asset->png_use_alpha ? 
217                   PNG_COLOR_TYPE_RGB_ALPHA : 
218                   PNG_COLOR_TYPE_RGB, 
219                 PNG_INTERLACE_NONE, 
220                 PNG_COMPRESSION_TYPE_DEFAULT, 
221                 PNG_FILTER_TYPE_DEFAULT);
222         png_write_info(png_ptr, info_ptr);
224 //printf("FilePNG::write_frame 1\n");
225         native_cmodel = asset->png_use_alpha ? BC_RGBA8888 : BC_RGB888;
226         if(frame->get_color_model() != native_cmodel)
227         {
228                 if(!png_unit->temp_frame) png_unit->temp_frame = new VFrame(0, 
229                         asset->width, 
230                         asset->height, 
231                         native_cmodel);
233                 cmodel_transfer(png_unit->temp_frame->get_rows(), /* Leave NULL if non existent */
234                         frame->get_rows(),
235                         png_unit->temp_frame->get_y(), /* Leave NULL if non existent */
236                         png_unit->temp_frame->get_u(),
237                         png_unit->temp_frame->get_v(),
238                         frame->get_y(), /* Leave NULL if non existent */
239                         frame->get_u(),
240                         frame->get_v(),
241                         0,        /* Dimensions to capture from input frame */
242                         0, 
243                         asset->width, 
244                         asset->height,
245                         0,       /* Dimensions to project on output frame */
246                         0, 
247                         asset->width, 
248                         asset->height,
249                         frame->get_color_model(), 
250                         png_unit->temp_frame->get_color_model(),
251                         0,         /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
252                         asset->width,       /* For planar use the luma rowspan */
253                         asset->height);
254                 
255                 output_frame = png_unit->temp_frame;
256         }
257         else
258                 output_frame = frame;
261 //printf("FilePNG::write_frame 2\n");
262         png_write_image(png_ptr, output_frame->get_rows());
263         png_write_end(png_ptr, info_ptr);
264         png_destroy_write_struct(&png_ptr, &info_ptr);
265 //printf("FilePNG::write_frame 3 %d\n", data->get_compressed_size());
267         return result;
270 int FilePNG::read_frame(VFrame *output, VFrame *input)
272         png_structp png_ptr;
273         png_infop info_ptr;
274         png_infop end_info = 0; 
275         int result = 0;
276         int size = input->get_compressed_size();
277         input->set_compressed_size(0);
278         
282 //printf("FilePNG::read_frame 1 %d %d\n", native_cmodel, output->get_color_model());
283         png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
284         info_ptr = png_create_info_struct(png_ptr);
285         png_set_read_fn(png_ptr, input, (png_rw_ptr)read_function);
286         png_read_info(png_ptr, info_ptr);
288         int png_color_type = png_get_color_type(png_ptr, info_ptr);
289         if (png_color_type == PNG_COLOR_TYPE_GRAY ||
290                 png_color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
291         {
292                 png_set_gray_to_rgb(png_ptr);
293         }
295 /* read the image */
296         png_read_image(png_ptr, output->get_rows());
297 //printf("FilePNG::read_frame 3\n");
298         png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
300         input->set_compressed_size(size);
302 //printf("FilePNG::read_frame 4\n");
303         return result;
306 FrameWriterUnit* FilePNG::new_writer_unit(FrameWriter *writer)
308         return new PNGUnit(this, writer);
322 PNGUnit::PNGUnit(FilePNG *file, FrameWriter *writer)
323  : FrameWriterUnit(writer)
325         this->file = file;
326         temp_frame = 0;
328 PNGUnit::~PNGUnit()
330         if(temp_frame) delete temp_frame;
341 PNGConfigVideo::PNGConfigVideo(BC_WindowBase *parent_window, Asset *asset)
342  : BC_Window(PROGRAM_NAME ": Video Compression",
343         parent_window->get_abs_cursor_x(1),
344         parent_window->get_abs_cursor_y(1),
345         200,
346         100)
348         this->parent_window = parent_window;
349         this->asset = asset;
352 PNGConfigVideo::~PNGConfigVideo()
356 int PNGConfigVideo::create_objects()
358         int x = 10, y = 10;
359         add_subwindow(new PNGUseAlpha(this, x, y));
360         add_subwindow(new BC_OKButton(this));
361         return 0;
364 int PNGConfigVideo::close_event()
366         set_done(0);
367         return 1;
371 PNGUseAlpha::PNGUseAlpha(PNGConfigVideo *gui, int x, int y)
372  : BC_CheckBox(x, y, gui->asset->png_use_alpha, _("Use alpha"))
374         this->gui = gui;
377 int PNGUseAlpha::handle_event()
379         gui->asset->png_use_alpha = get_value();
380         return 1;