r665: Merged the official release 2.0.
[cinelerra_cv.git] / quicktime / qtpng.c
blobfa4fba2479ebfbd97f2fe6ba6df96a5eeb9aa6b8
1 #include "colormodels.h"
2 #include "funcprotos.h"
3 #include <png.h>
4 #include "quicktime.h"
5 #include "qtpng.h"
7 typedef struct
9 int compression_level;
10 unsigned char *buffer;
11 // Read position
12 long buffer_position;
13 // Frame size
14 long buffer_size;
15 // Buffer allocation
16 long buffer_allocated;
17 int quality;
18 unsigned char *temp_frame;
19 } quicktime_png_codec_t;
21 static int delete_codec(quicktime_video_map_t *vtrack)
23 quicktime_png_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
24 if(codec->buffer) free(codec->buffer);
25 if(codec->temp_frame) free(codec->temp_frame);
26 free(codec);
27 return 0;
30 static int source_cmodel(quicktime_t *file, int track)
32 int depth = quicktime_video_depth(file, track);
33 if(depth == 24)
34 return BC_RGB888;
35 else
36 return BC_RGBA8888;
39 void quicktime_set_png(quicktime_t *file, int compression_level)
41 int i;
42 char *compressor;
44 for(i = 0; i < file->total_vtracks; i++)
46 if(quicktime_match_32(quicktime_video_compressor(file, i), QUICKTIME_PNG))
48 quicktime_png_codec_t *codec = ((quicktime_codec_t*)file->vtracks[i].codec)->priv;
49 codec->compression_level = compression_level;
54 static void read_function(png_structp png_ptr, png_bytep data, png_uint_32 length)
56 quicktime_png_codec_t *codec = png_get_io_ptr(png_ptr);
58 if(length + codec->buffer_position <= codec->buffer_size)
60 memcpy(data, codec->buffer + codec->buffer_position, length);
61 codec->buffer_position += length;
65 static void write_function(png_structp png_ptr, png_bytep data, png_uint_32 length)
67 quicktime_png_codec_t *codec = png_get_io_ptr(png_ptr);
69 if(length + codec->buffer_size > codec->buffer_allocated)
71 codec->buffer_allocated += length;
72 codec->buffer = realloc(codec->buffer, codec->buffer_allocated);
74 memcpy(codec->buffer + codec->buffer_size, data, length);
75 codec->buffer_size += length;
78 static void flush_function(png_structp png_ptr)
83 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
85 int result = 0;
86 int64_t i;
87 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
88 quicktime_trak_t *trak = vtrack->track;
89 png_structp png_ptr;
90 png_infop info_ptr;
91 png_infop end_info = 0;
92 int height = trak->tkhd.track_height;
93 int width = trak->tkhd.track_width;
94 quicktime_png_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
95 int cmodel = source_cmodel(file, track);
96 int use_temp = (cmodel != file->color_model ||
97 file->in_x != 0 ||
98 file->in_y != 0 ||
99 file->in_w != width ||
100 file->in_h != height ||
101 file->out_w != width ||
102 file->out_h != height);
103 unsigned char **temp_rows = malloc(sizeof(unsigned char*) * height);
105 if(use_temp)
107 if(!codec->temp_frame)
109 codec->temp_frame = malloc(cmodel_calculate_datasize(width,
110 height,
111 -1,
112 cmodel));
114 for(i = 0; i < height; i++)
115 temp_rows[i] = codec->temp_frame +
116 cmodel_calculate_pixelsize(cmodel) * width * i;
118 else
120 for(i = 0; i < height; i++)
121 temp_rows[i] = row_pointers[i];
124 quicktime_set_video_position(file, vtrack->current_position, track);
125 codec->buffer_size = quicktime_frame_size(file, vtrack->current_position, track);
126 codec->buffer_position = 0;
127 if(codec->buffer_size > codec->buffer_allocated)
129 codec->buffer_allocated = codec->buffer_size;
130 codec->buffer = realloc(codec->buffer, codec->buffer_allocated);
133 result = !quicktime_read_data(file, codec->buffer, codec->buffer_size);
135 if(!result)
137 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
138 info_ptr = png_create_info_struct(png_ptr);
139 png_set_read_fn(png_ptr, codec, (png_rw_ptr)read_function);
140 png_read_info(png_ptr, info_ptr);
142 /* read the image */
143 png_read_image(png_ptr, temp_rows);
144 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
147 if(use_temp)
149 cmodel_transfer(row_pointers,
150 temp_rows,
151 row_pointers[0],
152 row_pointers[1],
153 row_pointers[2],
157 file->in_x,
158 file->in_y,
159 file->in_w,
160 file->in_h,
163 file->out_w,
164 file->out_h,
165 cmodel,
166 file->color_model,
168 width,
169 file->out_w);
173 free(temp_rows);
175 return result;
181 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
183 int64_t offset = quicktime_position(file);
184 int result = 0;
185 int i;
186 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
187 quicktime_trak_t *trak = vtrack->track;
188 quicktime_png_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
189 int height = trak->tkhd.track_height;
190 int width = trak->tkhd.track_width;
191 png_structp png_ptr;
192 png_infop info_ptr;
193 int cmodel = source_cmodel(file, track);
194 quicktime_atom_t chunk_atom;
196 codec->buffer_size = 0;
197 codec->buffer_position = 0;
199 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
200 info_ptr = png_create_info_struct(png_ptr);
201 png_set_write_fn(png_ptr,
202 codec,
203 (png_rw_ptr)write_function,
204 (png_flush_ptr)flush_function);
205 png_set_compression_level(png_ptr, codec->compression_level);
206 png_set_IHDR(png_ptr,
207 info_ptr,
208 width, height,
210 cmodel == BC_RGB888 ?
211 PNG_COLOR_TYPE_RGB :
212 PNG_COLOR_TYPE_RGB_ALPHA,
213 PNG_INTERLACE_NONE,
214 PNG_COMPRESSION_TYPE_DEFAULT,
215 PNG_FILTER_TYPE_DEFAULT);
216 png_write_info(png_ptr, info_ptr);
217 png_write_image(png_ptr, row_pointers);
218 png_write_end(png_ptr, info_ptr);
219 png_destroy_write_struct(&png_ptr, &info_ptr);
221 quicktime_write_chunk_header(file, trak, &chunk_atom);
222 result = !quicktime_write_data(file,
223 codec->buffer,
224 codec->buffer_size);
225 quicktime_write_chunk_footer(file,
226 trak,
227 vtrack->current_chunk,
228 &chunk_atom,
231 vtrack->current_chunk++;
232 return result;
235 static int set_parameter(quicktime_t *file,
236 int track,
237 char *key,
238 void *value)
240 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
241 quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
242 quicktime_png_codec_t *codec = codec_base->priv;
244 if(!strcasecmp(key, "compression_level"))
245 codec->compression_level = *(int*)value;
248 static int reads_colormodel(quicktime_t *file,
249 int colormodel,
250 int track)
252 return (colormodel == BC_RGB888 ||
253 colormodel == BC_BGR8888);
256 void quicktime_init_codec_png(quicktime_video_map_t *vtrack)
258 quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
259 quicktime_png_codec_t *codec;
261 /* Init public items */
262 codec_base->priv = calloc(1, sizeof(quicktime_png_codec_t));
263 codec_base->delete_vcodec = delete_codec;
264 codec_base->decode_video = decode;
265 codec_base->encode_video = encode;
266 codec_base->decode_audio = 0;
267 codec_base->encode_audio = 0;
268 codec_base->reads_colormodel = reads_colormodel;
269 codec_base->set_parameter = set_parameter;
270 codec_base->fourcc = QUICKTIME_PNG;
271 codec_base->title = "PNG";
272 codec_base->desc = "Lossless RGB compression";
274 /* Init private items */
275 codec = codec_base->priv;
276 codec->compression_level = 9;