r717: Made the highlighted text color of the menus WHITE
[cinelerra_cv/mob.git] / guicast / vframe.C
blobe179299bda51c8075bb5a97f84f09386b9316cc1
1 #include <png.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdint.h>
6 //#include "bccounter.h"
7 #include "bcsignals.h"
8 #include "clip.h"
9 #include "colormodels.h"
10 #include "vframe.h"
12 class PngReadFunction
14 public:
15         static void png_read_function(png_structp png_ptr,
16                    png_bytep data, 
17                                    png_size_t length)
18         {
19                 VFrame *frame = (VFrame*)png_get_io_ptr(png_ptr);
20                 if(frame->image_size - frame->image_offset < length) 
21                         length = frame->image_size - frame->image_offset;
23                 memcpy(data, &frame->image[frame->image_offset], length);
24                 frame->image_offset += length;
25         };
34 //static BCCounter counter;
37 VFrame::VFrame(unsigned char *png_data)
39 //printf("VFrame::VFrame 1\n");
40         reset_parameters();
41 //printf("VFrame::VFrame 1\n");
42         read_png(png_data);
43 //printf("VFrame::VFrame 2\n");
46 VFrame::VFrame(const PngData& png_data)
48 //printf("VFrame::VFrame 1\n");
49         reset_parameters();
50 //printf("VFrame::VFrame 1\n");
51         read_png(png_data);
52 //printf("VFrame::VFrame 2\n");
55 VFrame::VFrame(VFrame &frame)
57         reset_parameters();
58         allocate_data(0, 0, 0, 0, frame.w, frame.h, frame.color_model, frame.bytes_per_line);
59         memcpy(data, frame.data, bytes_per_line * h);
60 //      counter.up();
63 VFrame::VFrame(unsigned char *data, 
64         int w, 
65         int h, 
66         int color_model, 
67         long bytes_per_line)
69         reset_parameters();
70         allocate_data(data, 0, 0, 0, w, h, color_model, bytes_per_line);
71 //      counter.up();
74 VFrame::VFrame(unsigned char *data, 
75                 long y_offset,
76                 long u_offset,
77                 long v_offset, 
78                 int w, 
79                 int h, 
80                 int color_model, 
81                 long bytes_per_line)
83         reset_parameters();
84         allocate_data(data, 
85                 y_offset, 
86                 u_offset, 
87                 v_offset, 
88                 w, 
89                 h, 
90                 color_model, 
91                 bytes_per_line);
92 //      counter.up();
95 VFrame::VFrame()
97         reset_parameters();
98         this->color_model = BC_COMPRESSED;
99 //      counter.up();
112 VFrame::~VFrame()
114         clear_objects();
115 //      counter.down();
118 int VFrame::equivalent(VFrame *src)
120         return (src->get_color_model() == get_color_model() &&
121                 src->get_w() == get_w() &&
122                 src->get_h() == get_h() &&
123                 src->bytes_per_line == bytes_per_line);
126 long VFrame::set_shm_offset(long offset)
128         shm_offset = offset;
129         return 0;
132 long VFrame::get_shm_offset()
134         return shm_offset;
137 int VFrame::params_match(int w, int h, int color_model)
139         return (this->w == w &&
140                 this->h == h &&
141                 this->color_model == color_model);
145 int VFrame::reset_parameters()
147         field2_offset = -1;
148         shared = 0;
149         shm_offset = 0;
150         bytes_per_line = 0;
151         data = 0;
152         rows = 0;
153         color_model = 0;
154         compressed_allocated = 0;
155         compressed_size = 0;   // Size of current image
156         w = 0;
157         h = 0;
158         y = u = v = 0;
159         y_offset = 0;
160         u_offset = 0;
161         v_offset = 0;
162         sequence_number = -1;
163         is_keyframe = 0;
164         return 0;
167 int VFrame::clear_objects()
169 // Delete data
170 //printf("VFrame::clear_objects 1 %p %d\n", this, shared);
171         if(!shared)
172         {
173 int size = calculate_data_size(this->w, this->h, this->bytes_per_line, this->color_model);
174 if(size > 2560 * 1920)
175 UNBUFFER(data);
176                 if(data) delete [] data;
177                 data = 0;
178         }
180 // Delete row pointers
181         switch(color_model)
182         {
183                 case BC_COMPRESSED:
184                 case BC_YUV420P:
185                         break;
187                 default:
188                         delete [] rows;
189                         break;
190         }
192         return 0;
195 int VFrame::get_field2_offset()
197         return field2_offset;
200 int VFrame::set_field2_offset(int value)
202         this->field2_offset = value;
203         return 0;
206 void VFrame::set_keyframe(int value)
208         this->is_keyframe = value;
211 int VFrame::get_keyframe()
213         return is_keyframe;
217 int VFrame::calculate_bytes_per_pixel(int color_model)
219         return cmodel_calculate_pixelsize(color_model);
222 long VFrame::get_bytes_per_line()
224         return bytes_per_line;
227 long VFrame::get_data_size()
229         return calculate_data_size(w, h, bytes_per_line, color_model) - 4;
230 //      return h * bytes_per_line;
233 long VFrame::calculate_data_size(int w, int h, int bytes_per_line, int color_model)
235         return cmodel_calculate_datasize(w, h, bytes_per_line, color_model);
236         return 0;
239 void VFrame::create_row_pointers()
241         switch(color_model)
242         {
243                 case BC_YUV420P:
244                 case BC_YUV411P:
245                         if(!this->v_offset)
246                         {
247                                 this->y_offset = 0;
248                                 this->u_offset = w * h;
249                                 this->v_offset = w * h + w * h / 4;
250                         }
251                         y = this->data + this->y_offset;
252                         u = this->data + this->u_offset;
253                         v = this->data + this->v_offset;
254                         break;
256                 case BC_YUV422P:
257                         if(!this->v_offset)
258                         {
259                                 this->y_offset = 0;
260                                 this->u_offset = w * h;
261                                 this->v_offset = w * h + w * h / 2;
262                         }
263                         y = this->data + this->y_offset;
264                         u = this->data + this->u_offset;
265                         v = this->data + this->v_offset;
266                         break;
268                 default:
269                         rows = new unsigned char*[h];
270                         for(int i = 0; i < h; i++)
271                         {
272                                 rows[i] = &this->data[i * this->bytes_per_line];
273                         }
274                         break;
275         }
278 int VFrame::allocate_data(unsigned char *data, 
279         long y_offset,
280         long u_offset,
281         long v_offset,
282         int w, 
283         int h, 
284         int color_model, 
285         long bytes_per_line)
287         this->w = w;
288         this->h = h;
289         this->color_model = color_model;
290         this->bytes_per_pixel = calculate_bytes_per_pixel(color_model);
291         this->y_offset = this->u_offset = this->v_offset = 0;
293         if(bytes_per_line >= 0)
294         {
295                 this->bytes_per_line = bytes_per_line;
296         }
297         else
298                 this->bytes_per_line = this->bytes_per_pixel * w;
300 // Allocate data + padding for MMX
301         if(data)
302         {
303                 shared = 1;
304                 this->data = data;
305                 this->y_offset = y_offset;
306                 this->u_offset = u_offset;
307                 this->v_offset = v_offset;
308         }
309         else
310         {
311                 shared = 0;
312                 int size = calculate_data_size(this->w, 
313                         this->h, 
314                         this->bytes_per_line, 
315                         this->color_model);
316                 this->data = new unsigned char[size];
318 if(size > 2560 * 1920)
319 BUFFER(size, this->data, "VFrame::allocate_data");
321 if(!this->data)
322 printf("VFrame::allocate_data %dx%d: memory exhausted.\n", this->w, this->h);
324 //printf("VFrame::allocate_data %p %d %d\n", this, this->w, this->h);
325 //if(size > 1000000) printf("VFrame::allocate_data %d\n", size);
326         }
328 // Create row pointers
329         create_row_pointers();
330         return 0;
333 void VFrame::set_memory(unsigned char *data, 
334                 long y_offset,
335                 long u_offset,
336                 long v_offset)
338         shared = 1;
339         this->data = data;
340         this->y_offset = y_offset;
341         this->u_offset = u_offset;
342         this->v_offset = v_offset;
343         y = this->data + this->y_offset;
344         u = this->data + this->u_offset;
345         v = this->data + this->v_offset;
346         create_row_pointers();
349 void VFrame::set_compressed_memory(unsigned char *data,
350         int data_size,
351         int data_allocated)
353         clear_objects();
354         shared = 1;
355         this->data = data;
356         this->compressed_allocated = data_allocated;
357         this->compressed_size = data_size;
361 // Reallocate uncompressed buffer with or without alpha
362 int VFrame::reallocate(unsigned char *data, 
363                 long y_offset,
364                 long u_offset,
365                 long v_offset,
366                 int w, 
367                 int h, 
368                 int color_model, 
369                 long bytes_per_line)
371         clear_objects();
372         reset_parameters();
373         allocate_data(data, 
374                 y_offset, 
375                 u_offset, 
376                 v_offset, 
377                 w, 
378                 h, 
379                 color_model, 
380                 bytes_per_line);
381         return 0;
384 int VFrame::allocate_compressed_data(long bytes)
386         if(bytes < 1) return 1;
388 // Want to preserve original contents
389         if(data && compressed_allocated < bytes)
390         {
391                 unsigned char *new_data = new unsigned char[bytes];
392                 bcopy(data, new_data, compressed_allocated);
393                 delete [] data;
394                 data = new_data;
395                 compressed_allocated = bytes;
396         }
397         else
398         if(!data)
399         {
400                 data = new unsigned char[bytes];
401                 compressed_allocated = bytes;
402                 compressed_size = 0;
403         }
405         return 0;
408 int VFrame::read_png(unsigned char *data)
410         PngData d;
411         d.size = (((unsigned long)data[0]) << 24) | 
412                 (((unsigned long)data[1]) << 16) | 
413                 (((unsigned long)data[2]) << 8) | 
414                 (unsigned char)data[3];
415         d.data = data + 4;
416         read_png(d);
419 int VFrame::read_png(const PngData& data)
421         png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
422         png_infop info_ptr = png_create_info_struct(png_ptr);
423         int new_color_model;
425         image_offset = 0;
426         image = data.data;
427         image_size = data.size;
428         png_set_read_fn(png_ptr, this, PngReadFunction::png_read_function);
429         png_read_info(png_ptr, info_ptr);
431         w = png_get_image_width(png_ptr, info_ptr);
432         h = png_get_image_height(png_ptr, info_ptr);
434         int src_color_model = png_get_color_type(png_ptr, info_ptr);
435         switch(src_color_model)
436         {
437                 case PNG_COLOR_TYPE_RGB:
438                         new_color_model = BC_RGB888;
439                         break;
442                 case PNG_COLOR_TYPE_GRAY_ALPHA:
443                 case PNG_COLOR_TYPE_RGB_ALPHA:
444                 default:
445                         new_color_model = BC_RGBA8888;
446                         break;
447         }
449         reallocate(NULL, 
450                 0, 
451                 0, 
452                 0, 
453                 w, 
454                 h, 
455                 new_color_model,
456                 -1);
458         png_read_image(png_ptr, get_rows());
462         if(src_color_model == PNG_COLOR_TYPE_GRAY_ALPHA)
463         {
464                 for(int i = 0; i < get_h(); i++)
465                 {
466                         unsigned char *row = get_rows()[i];
467                         unsigned char *out_ptr = row + get_w() * 4 - 4;
468                         unsigned char *in_ptr = row + get_w() * 2 - 2;
470                         for(int j = get_w() - 1; j >= 0; j--)
471                         {
472                                 out_ptr[0] = in_ptr[0];
473                                 out_ptr[1] = in_ptr[0];
474                                 out_ptr[2] = in_ptr[0];
475                                 out_ptr[3] = in_ptr[1];
476                                 out_ptr -= 4;
477                                 in_ptr -= 2;
478                         }
479                 }
480         }
482         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
483         return 0;
486 unsigned char* VFrame::get_data()
488         return data;
491 long VFrame::get_compressed_allocated()
493         return compressed_allocated;
496 long VFrame::get_compressed_size()
498         return compressed_size;
501 long VFrame::set_compressed_size(long size)
503         compressed_size = size;
504         return 0;
507 int VFrame::get_color_model()
509         return color_model;
513 int VFrame::equals(VFrame *frame)
515         if(frame->data == data) 
516                 return 1;
517         else
518                 return 0;
521 #define ZERO_YUV(components, type, max) \
522 { \
523         for(int i = 0; i < h; i++) \
524         { \
525                 type *row = (type*)get_rows()[i]; \
526                 for(int j = 0; j < w; j++) \
527                 { \
528                         row[j * components] = 0; \
529                         row[j * components + 1] = (max + 1) / 2; \
530                         row[j * components + 2] = (max + 1) / 2; \
531                         if(components == 4) row[j * components + 3] = 0; \
532                 } \
533         } \
536 int VFrame::clear_frame()
538         switch(color_model)
539         {
540                 case BC_COMPRESSED:
541                         break;
543                 case BC_YUV420P:
544                         bzero(data, h * w * 2);
545                         break;
547                 case BC_YUV888:
548                         ZERO_YUV(3, unsigned char, 0xff);
549                         break;
550                 
551                 case BC_YUVA8888:
552                         ZERO_YUV(4, unsigned char, 0xff);
553                         break;
555                 case BC_YUV161616:
556                         ZERO_YUV(3, uint16_t, 0xffff);
557                         break;
558                 
559                 case BC_YUVA16161616:
560                         ZERO_YUV(4, uint16_t, 0xffff);
561                         break;
562                 
563                 default:
564                         bzero(data, h * bytes_per_line);
565                         break;
566         }
567         return 0;
570 void VFrame::rotate90()
572 // Allocate new frame
573         int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
574         unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
575         unsigned char **new_rows = new unsigned char*[new_h];
576         for(int i = 0; i < new_h; i++)
577                 new_rows[i] = &new_data[new_bytes_per_line * i];
579 // Copy data
580         for(int in_y = 0, out_x = new_w - 1; in_y < h; in_y++, out_x--)
581         {
582                 for(int in_x = 0, out_y = 0; in_x < w; in_x++, out_y++)
583                 {
584                         for(int k = 0; k < bytes_per_pixel; k++)
585                         {
586                                 new_rows[out_y][out_x * bytes_per_pixel + k] = 
587                                         rows[in_y][in_x * bytes_per_pixel + k];
588                         }
589                 }
590         }
592 // Swap frames
593         clear_objects();
594         data = new_data;
595         rows = new_rows;
596         bytes_per_line = new_bytes_per_line;
597         w = new_w;
598         h = new_h;
601 void VFrame::rotate270()
603 // Allocate new frame
604         int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
605         unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
606         unsigned char **new_rows = new unsigned char*[new_h];
607         for(int i = 0; i < new_h; i++)
608                 new_rows[i] = &new_data[new_bytes_per_line * i];
610 // Copy data
611         for(int in_y = 0, out_x = 0; in_y < h; in_y++, out_x++)
612         {
613                 for(int in_x = 0, out_y = new_h - 1; in_x < w; in_x++, out_y--)
614                 {
615                         for(int k = 0; k < bytes_per_pixel; k++)
616                         {
617                                 new_rows[out_y][out_x * bytes_per_pixel + k] = 
618                                         rows[in_y][in_x * bytes_per_pixel + k];
619                         }
620                 }
621         }
623 // Swap frames
624         clear_objects();
625         data = new_data;
626         rows = new_rows;
627         bytes_per_line = new_bytes_per_line;
628         w = new_w;
629         h = new_h;
632 void VFrame::flip_vert()
634         for(int i = 0, j = h - 1; i < j; i++, j--)
635         {
636                 for(int k = 0; k < bytes_per_line; k++)
637                 {
638                         unsigned char temp = rows[j][k];
639                         rows[j][k] = rows[i][k];
640                         rows[i][k] = temp;
641                 }
642         }
647 int VFrame::copy_from(VFrame *frame)
649         int w = MIN(this->w, frame->get_w());
650         int h = MIN(this->h, frame->get_h());
651         
653         switch(frame->color_model)
654         {
655                 case BC_COMPRESSED:
656                         allocate_compressed_data(frame->compressed_size);
657                         memcpy(data, frame->data, frame->compressed_size);
658                         this->compressed_size = frame->compressed_size;
659                         break;
661                 case BC_YUV420P:
662 //printf("%d %d %p %p %p %p %p %p\n", w, h, get_y(), get_u(), get_v(), frame->get_y(), frame->get_u(), frame->get_v());
663                         memcpy(get_y(), frame->get_y(), w * h);
664                         memcpy(get_u(), frame->get_u(), w * h / 4);
665                         memcpy(get_v(), frame->get_v(), w * h / 4);
666                         break;
668                 case BC_YUV422P:
669 //printf("%d %d %p %p %p %p %p %p\n", w, h, get_y(), get_u(), get_v(), frame->get_y(), frame->get_u(), frame->get_v());
670                         memcpy(get_y(), frame->get_y(), w * h);
671                         memcpy(get_u(), frame->get_u(), w * h / 2);
672                         memcpy(get_v(), frame->get_v(), w * h / 2);
673                         break;
675                 default:
676 // printf("VFrame::copy_from %d\n", calculate_data_size(w, 
677 //                              h, 
678 //                              -1, 
679 //                              frame->color_model));
680                         memcpy(data, frame->data, calculate_data_size(w, 
681                                 h, 
682                                 -1, 
683                                 frame->color_model));
684                         break;
685         }
687         return 0;
691 #define OVERLAY(type, max, components) \
692 { \
693         type **in_rows = (type**)src->get_rows(); \
694         type **out_rows = (type**)get_rows(); \
695         int in_w = src->get_w(); \
696         int in_h = src->get_h(); \
698         for(int i = 0; i < in_h; i++) \
699         { \
700                 if(i + out_y1 >= 0 && i + out_y1 < h) \
701                 { \
702                         type *src_row = in_rows[i]; \
703                         type *dst_row = out_rows[i + out_y1] + out_x1 * components; \
705                         for(int j = 0; j < in_w; j++) \
706                         { \
707                                 if(j + out_x1 >= 0 && j + out_x1 < w) \
708                                 { \
709                                         int opacity = src_row[3]; \
710                                         int transparency = max - src_row[3]; \
711                                         dst_row[0] = (transparency * dst_row[0] + opacity * src_row[0]) / max; \
712                                         dst_row[1] = (transparency * dst_row[1] + opacity * src_row[1]) / max; \
713                                         dst_row[2] = (transparency * dst_row[2] + opacity * src_row[2]) / max; \
714                                         dst_row[3] = MAX(dst_row[3], src_row[3]); \
715                                 } \
717                                 dst_row += components; \
718                                 src_row += components; \
719                         } \
720                 } \
721         } \
725 void VFrame::overlay(VFrame *src, 
726                 int out_x1, 
727                 int out_y1)
729         switch(get_color_model())
730         {
731                 case BC_RGBA8888:
732                         OVERLAY(unsigned char, 0xff, 4);
733                         break;
734         }
739 int VFrame::get_scale_tables(int *column_table, int *row_table, 
740                         int in_x1, int in_y1, int in_x2, int in_y2,
741                         int out_x1, int out_y1, int out_x2, int out_y2)
743         int y_out, i;
744         float w_in = in_x2 - in_x1;
745         float h_in = in_y2 - in_y1;
746         int w_out = out_x2 - out_x1;
747         int h_out = out_y2 - out_y1;
749         float hscale = w_in / w_out;
750         float vscale = h_in / h_out;
752         for(i = 0; i < w_out; i++)
753         {
754                 column_table[i] = (int)(hscale * i);
755         }
757         for(i = 0; i < h_out; i++)
758         {
759                 row_table[i] = (int)(vscale * i) + in_y1;
760         }
761         return 0;
764 int VFrame::get_bytes_per_pixel()
766         return bytes_per_pixel;
769 unsigned char** VFrame::get_rows()
771         if(rows)
772         {
773                 return rows;
774         }
775         return 0;
778 int VFrame::get_w()
780         return w;
783 int VFrame::get_h()
785         return h;
788 int VFrame::get_w_fixed()
790         return w - 1;
793 int VFrame::get_h_fixed()
795         return h - 1;
798 unsigned char* VFrame::get_y()
800         return y;
803 unsigned char* VFrame::get_u()
805         return u;
808 unsigned char* VFrame::get_v()
810         return v;
813 void VFrame::set_number(long number)
815         sequence_number = number;
818 long VFrame::get_number()
820         return sequence_number;