4 * Copyright (C) 2011 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include "bcpbuffer.h"
32 #include "bcresources.h"
33 #include "bcsignals.h"
34 #include "bcsynchronous.h"
35 #include "bctexture.h"
36 #include "bcwindowbase.h"
38 #include "bccmodels.h"
44 static void png_read_function(png_structp png_ptr,
45 png_bytep data, png_size_t length)
47 VFrame *frame = (VFrame*)png_get_io_ptr(png_ptr);
48 if(frame->image_size - frame->image_offset < (long)length)
50 printf("PngReadFunction::png_read_function %d: overrun\n", __LINE__);
51 length = frame->image_size - frame->image_offset;
54 memcpy(data, &frame->image[frame->image_offset], length);
55 frame->image_offset += length;
65 VFrameScene::VFrameScene()
69 VFrameScene::~VFrameScene()
79 //static BCCounter counter;
82 VFramePng::VFramePng(unsigned char *png_data, double scale)
85 ((long)png_data[0] << 24) | ((long)png_data[1] << 16) |
86 ((long)png_data[2] << 8) | (long)png_data[3];
87 if( !scale ) scale = BC_WindowBase::get_resources()->icon_scale;
88 read_png(png_data+4, image_size, scale, scale);
91 VFramePng::VFramePng(unsigned char *png_data, long image_size, double xscale, double yscale)
93 if( !xscale ) xscale = BC_WindowBase::get_resources()->icon_scale;
94 if( !yscale ) yscale = BC_WindowBase::get_resources()->icon_scale;
95 read_png(png_data, image_size, xscale, yscale);
98 VFramePng::~VFramePng()
103 VFrame::VFrame(VFrame &frame)
106 params = new BC_Hash;
107 allocate_data(0, -1, 0, 0, 0, frame.w, frame.h,
108 frame.color_model, frame.bytes_per_line);
109 memcpy(data, frame.data, bytes_per_line * h);
113 VFrame::VFrame(int w, int h, int color_model, long bytes_per_line)
116 params = new BC_Hash;
117 allocate_data(data, -1, 0, 0, 0, w, h,
118 color_model, bytes_per_line);
121 VFrame::VFrame(unsigned char *data, int shmid, int w, int h,
122 int color_model, long bytes_per_line)
125 params = new BC_Hash;
126 allocate_data(data, shmid, 0, 0, 0, w, h,
127 color_model, bytes_per_line);
130 VFrame::VFrame(unsigned char *data, int shmid,
131 long y_offset, long u_offset, long v_offset,
132 int w, int h, int color_model, long bytes_per_line)
135 params = new BC_Hash;
136 allocate_data(data, shmid, y_offset, u_offset, v_offset, w, h,
137 color_model, bytes_per_line);
140 VFrame::VFrame(BC_Bitmap *bitmap, int w, int h,
141 int color_model, long bytes_per_line)
144 params = new BC_Hash;
146 unsigned char *data = 0;
147 if( bitmap->is_shared() )
148 shmid = bitmap->get_shmid();
150 data = bitmap->get_data();
151 allocate_data(data, shmid,
152 bitmap->get_y_offset(),
153 bitmap->get_u_offset(),
154 bitmap->get_v_offset(),
155 w, h, color_model, bytes_per_line);
161 params = new BC_Hash;
162 this->color_model = BC_COMPRESSED;
170 // Delete effect stack
171 prev_effects.remove_all_objects();
172 next_effects.remove_all_objects();
177 int VFrame::equivalent(VFrame *src, int test_stacks)
179 return (src->get_color_model() == get_color_model() &&
180 src->get_w() == get_w() &&
181 src->get_h() == get_h() &&
182 src->bytes_per_line == bytes_per_line &&
183 (!test_stacks || equal_stacks(src)));
186 int VFrame::data_matches(VFrame *frame)
188 if(data && frame->get_data() &&
189 frame->params_match(get_w(), get_h(), get_color_model()) &&
190 get_data_size() == frame->get_data_size())
192 int data_size = get_data_size();
193 unsigned char *ptr1 = get_data();
194 unsigned char *ptr2 = frame->get_data();
195 for(int i = 0; i < data_size; i++)
197 if(*ptr1++ != *ptr2++) return 0;
204 // long VFrame::set_shm_offset(long offset)
206 // shm_offset = offset;
210 // long VFrame::get_shm_offset()
212 // return shm_offset;
215 int VFrame::get_memory_type()
220 int VFrame::params_match(int w, int h, int color_model)
222 return (this->w == w &&
224 this->color_model == color_model);
228 int VFrame::reset_parameters(int do_opengl)
233 memory_type = VFrame::PRIVATE;
241 compressed_allocated = 0;
242 compressed_size = 0; // Size of current image
249 sequence_number = -1;
255 // By default, anything is going to be done in RAM
256 opengl_state = VFrame::RAM;
261 prev_effects.set_array_delete();
262 next_effects.set_array_delete();
266 int VFrame::clear_objects(int do_opengl)
281 case VFrame::PRIVATE:
283 // if(this->w * this->h > 1500 * 1100)
284 // printf("VFrame::clear_objects 2 this=%p data=%p\n", this, data);
287 //printf("VFrame::clear_objects %d this=%p shmid=%p data=%p\n", __LINE__, this, shmid, data);
307 // Delete row pointers
331 int VFrame::get_field2_offset()
333 return field2_offset;
336 int VFrame::set_field2_offset(int value)
338 this->field2_offset = value;
342 void VFrame::set_keyframe(int value)
344 this->is_keyframe = value;
347 int VFrame::get_keyframe()
353 VFrameScene* VFrame::get_scene()
358 int VFrame::calculate_bytes_per_pixel(int color_model)
360 return BC_CModels::calculate_pixelsize(color_model);
363 long VFrame::get_bytes_per_line()
365 return bytes_per_line;
368 long VFrame::get_data_size()
370 return calculate_data_size(w, h, bytes_per_line, color_model) - 4;
373 long VFrame::calculate_data_size(int w, int h, int bytes_per_line, int color_model)
375 return BC_CModels::calculate_datasize(w, h, bytes_per_line, color_model);
378 void VFrame::create_row_pointers()
381 switch(color_model) {
383 if( this->v_offset ) break;
386 this->v_offset = sz + w / 4 * h / 4;
392 if( this->v_offset ) break;
395 this->v_offset = sz + sz / 4;
399 if( this->v_offset ) break;
402 this->v_offset = sz + sz / 2;
405 if( this->v_offset ) break;
408 this->v_offset = sz + sz;
411 if( this->v_offset || a ) break;
412 a = this->data + 3 * sz * sizeof(float);
414 if( this->v_offset ) break;
416 this->u_offset = sz * sizeof(float);
417 this->v_offset = 2 * sz * sizeof(float);
421 rows = new unsigned char*[h];
422 for(int i = 0; i < h; i++)
423 rows[i] = &this->data[i * this->bytes_per_line];
426 y = this->data + this->y_offset;
427 u = this->data + this->u_offset;
428 v = this->data + this->v_offset;
431 int VFrame::allocate_data(unsigned char *data, int shmid,
432 long y_offset, long u_offset, long v_offset, int w, int h,
433 int color_model, long bytes_per_line)
437 this->color_model = color_model;
438 this->bytes_per_pixel = calculate_bytes_per_pixel(color_model);
439 this->y_offset = this->u_offset = this->v_offset = 0;
441 // printf("VFrame::allocate_data %d shmid == 0\n", __LINE__, shmid);
444 this->bytes_per_line = bytes_per_line >= 0 ?
445 bytes_per_line : this->bytes_per_pixel * w;
447 // Allocate data + padding for MMX
449 //printf("VFrame::allocate_data %d %p\n", __LINE__, this->data);
450 memory_type = VFrame::SHARED;
453 this->y_offset = y_offset;
454 this->u_offset = u_offset;
455 this->v_offset = v_offset;
457 else if(shmid >= 0) {
458 memory_type = VFrame::SHMGET;
459 this->data = (unsigned char*)shmat(shmid, NULL, 0);
460 //printf("VFrame::allocate_data %d shmid=%d data=%p\n", __LINE__, shmid, this->data);
462 this->y_offset = y_offset;
463 this->u_offset = u_offset;
464 this->v_offset = v_offset;
467 memory_type = VFrame::PRIVATE;
468 int size = calculate_data_size(this->w, this->h,
469 this->bytes_per_line, this->color_model);
470 if(BC_WindowBase::get_resources()->use_vframe_shm() && use_shm) {
471 this->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777);
472 if(this->shmid < 0) {
473 printf("VFrame::allocate_data %d could not allocate shared memory\n", __LINE__);
476 this->data = (unsigned char*)shmat(this->shmid, NULL, 0);
477 //printf("VFrame::allocate_data %d %d %d\n", __LINE__, size, this->shmid);
479 //printf("VFrame::allocate_data %d %p\n", __LINE__, this->data);
480 // This causes it to automatically delete when the program exits.
481 shmctl(this->shmid, IPC_RMID, 0);
484 // Have to use malloc for libpng
485 //printf("==vframe %d from %p\n", size, __builtin_return_address(0));
486 this->data = (unsigned char *)malloc(size);
490 // if(this->w * this->h > 1500 * 1100)
491 // printf("VFrame::allocate_data 2 this=%p w=%d h=%d this->data=%p\n",
492 // this, this->w, this->h, this->data);
495 printf("VFrame::allocate_data %dx%d: memory exhausted.\n", this->w, this->h);
497 //printf("VFrame::allocate_data %d %p data=%p %d %d\n", __LINE__, this, this->data, this->w, this->h);
498 //if(size > 1000000) printf("VFrame::allocate_data %d\n", size);
501 // Create row pointers
502 create_row_pointers();
506 void VFrame::set_memory(unsigned char *data,
516 memory_type = VFrame::SHARED;
519 this->y_offset = y_offset;
520 this->u_offset = u_offset;
521 this->v_offset = v_offset;
526 memory_type = VFrame::SHMGET;
527 this->data = (unsigned char*)shmat(shmid, NULL, 0);
531 y = this->data + this->y_offset;
532 u = this->data + this->u_offset;
533 v = this->data + this->v_offset;
535 create_row_pointers();
538 void VFrame::set_memory(BC_Bitmap *bitmap)
541 unsigned char *data = 0;
542 if( bitmap->is_shared() && !bitmap->is_zombie() )
543 shmid = bitmap->get_shmid();
545 data = bitmap->get_data();
546 set_memory(data, shmid,
547 bitmap->get_y_offset(),
548 bitmap->get_u_offset(),
549 bitmap->get_v_offset());
552 void VFrame::set_compressed_memory(unsigned char *data,
561 memory_type = VFrame::SHARED;
568 memory_type = VFrame::SHMGET;
569 this->data = (unsigned char*)shmat(shmid, NULL, 0);
573 this->compressed_allocated = data_allocated;
574 this->compressed_size = data_size;
578 // Reallocate uncompressed buffer with or without alpha
579 int VFrame::reallocate(
590 // if(shmid == 0) printf("VFrame::reallocate %d shmid=%d\n", __LINE__, shmid);
592 // reset_parameters(0);
605 int VFrame::allocate_compressed_data(long bytes)
607 if(bytes < 1) return 1;
609 // Want to preserve original contents
610 if(data && compressed_allocated < bytes)
613 unsigned char *new_data = 0;
614 if(BC_WindowBase::get_resources()->use_vframe_shm() && use_shm)
616 new_shmid = shmget(IPC_PRIVATE,
619 new_data = (unsigned char*)shmat(new_shmid, NULL, 0);
620 shmctl(new_shmid, IPC_RMID, 0);
624 // Have to use malloc for libpng
625 new_data = (unsigned char *)malloc(bytes);
628 bcopy(data, new_data, compressed_allocated);
631 if(memory_type == VFrame::PRIVATE)
641 if(memory_type == VFrame::SHMGET)
649 compressed_allocated = bytes;
654 if(BC_WindowBase::get_resources()->use_vframe_shm() && use_shm)
656 shmid = shmget(IPC_PRIVATE,
659 data = (unsigned char*)shmat(shmid, NULL, 0);
660 shmctl(shmid, IPC_RMID, 0);
664 // Have to use malloc for libpng
665 data = (unsigned char *)malloc(bytes);
668 compressed_allocated = bytes;
675 int VFramePng::read_png(const unsigned char *data, long sz, double xscale, double yscale)
677 // Test for RAW format
678 if(data[0] == 'R' && data[1] == 'A' && data[2] == 'W' && data[3] == ' ') {
679 int new_color_model = BC_RGBA8888;
680 w = data[4] | (data[5] << 8) | (data[6] << 16) | (data[7] << 24);
681 h = data[8] | (data[9] << 8) | (data[10] << 16) | (data[11] << 24);
682 int components = data[12];
683 new_color_model = components == 3 ? BC_RGB888 : BC_RGBA8888;
684 // This shares the data directly
685 // reallocate(data + 20, 0, 0, 0, w, h, new_color_model, -1);
687 // Can't use shared data for theme since button constructions overlay the
689 reallocate(NULL, -1, 0, 0, 0, w, h, new_color_model, -1);
690 memcpy(get_data(), data + 16, w * h * components);
693 else if(data[0] == 0x89 && data[1] == 'P' && data[2] == 'N' && data[3] == 'G') {
695 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
696 png_infop info_ptr = png_create_info_struct(png_ptr);
700 image = data; image_size = sz;
701 png_set_read_fn(png_ptr, this, PngReadFunction::png_read_function);
702 png_read_info(png_ptr, info_ptr);
704 w = png_get_image_width(png_ptr, info_ptr);
705 h = png_get_image_height(png_ptr, info_ptr);
707 int src_color_model = png_get_color_type(png_ptr, info_ptr);
709 /* tell libpng to strip 16 bit/color files down to 8 bits/color */
710 png_set_strip_16(png_ptr);
712 /* extract multiple pixels with bit depths of 1, 2, and 4 from a single
713 * byte into separate bytes (useful for paletted and grayscale images).
715 png_set_packing(png_ptr);
717 /* expand paletted colors into true RGB triplets */
718 if (src_color_model == PNG_COLOR_TYPE_PALETTE)
719 png_set_expand(png_ptr);
721 /* expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
722 if (src_color_model == PNG_COLOR_TYPE_GRAY && png_get_bit_depth(png_ptr, info_ptr) < 8)
723 png_set_expand(png_ptr);
725 if (src_color_model == PNG_COLOR_TYPE_GRAY ||
726 src_color_model == PNG_COLOR_TYPE_GRAY_ALPHA)
727 png_set_gray_to_rgb(png_ptr);
729 /* expand paletted or RGB images with transparency to full alpha channels
730 * so the data will be available as RGBA quartets */
731 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)){
733 png_set_expand(png_ptr);
736 switch(src_color_model)
738 case PNG_COLOR_TYPE_GRAY:
739 case PNG_COLOR_TYPE_RGB:
740 new_color_model = BC_RGB888;
743 case PNG_COLOR_TYPE_GRAY_ALPHA:
744 case PNG_COLOR_TYPE_RGB_ALPHA:
746 new_color_model = BC_RGBA8888;
749 case PNG_COLOR_TYPE_PALETTE:
751 new_color_model = BC_RGBA8888;
753 new_color_model = BC_RGB888;
756 reallocate(NULL, -1, 0, 0, 0, w, h, new_color_model, -1);
758 //printf("VFrame::read_png %d %d %d %p\n", __LINE__, w, h, get_rows());
759 png_read_image(png_ptr, get_rows());
760 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
763 printf("VFrame::read_png %d: unknown file format"
764 " 0x%02x 0x%02x 0x%02x 0x%02x\n",
765 __LINE__, data[4], data[5], data[6], data[7]);
768 int ww = w * xscale, hh = h * yscale;
769 if( ww != w || hh != h ) {
770 VFrame vframe(*this);
771 reallocate(NULL, -1, 0, 0, 0, ww, hh, color_model, -1);
772 transfer_from(&vframe);
777 int VFrame::write_png(const char *path)
779 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
780 png_infop info_ptr = png_create_info_struct(png_ptr);
781 FILE *out_fd = fopen(path, "w");
784 printf("VFrame::write_png %d %s %s\n", __LINE__, path, strerror(errno));
788 int png_cmodel = PNG_COLOR_TYPE_RGB;
789 switch(get_color_model())
793 png_cmodel = PNG_COLOR_TYPE_RGB;
798 png_cmodel = PNG_COLOR_TYPE_RGB_ALPHA;
802 png_cmodel = PNG_COLOR_TYPE_GRAY;
806 png_init_io(png_ptr, out_fd);
807 png_set_compression_level(png_ptr, 9);
808 png_set_IHDR(png_ptr,
815 PNG_COMPRESSION_TYPE_DEFAULT,
816 PNG_FILTER_TYPE_DEFAULT);
817 png_write_info(png_ptr, info_ptr);
818 png_write_image(png_ptr, get_rows());
819 png_write_end(png_ptr, info_ptr);
820 png_destroy_write_struct(&png_ptr, &info_ptr);
826 #define ZERO_YUV(components, type, max) \
828 for(int i = 0; i < h; i++) \
830 type *row = (type*)get_rows()[i]; \
831 for(int j = 0; j < w; j++) \
833 row[j * components] = 0; \
834 row[j * components + 1] = (max + 1) / 2; \
835 row[j * components + 2] = (max + 1) / 2; \
836 if(components == 4) row[j * components + 3] = 0; \
841 int VFrame::clear_frame()
844 //printf("VFrame::clear_frame %d\n", __LINE__);
845 switch(color_model) {
851 bzero(get_u(), w / 4 * h / 4);
852 bzero(get_v(), w / 4 * h / 4);
859 bzero(get_u(), sz / 4);
860 bzero(get_v(), sz / 4);
865 bzero(get_u(), sz / 2);
866 bzero(get_v(), sz / 2);
869 case BC_RGBA_FLOATP: if( a ) {
870 float *ap = (float *)a;
871 for( int i=sz; --i>=0; ++ap ) *ap = 1.f; }
872 case BC_RGB_FLOATP: {
873 float *rp = (float *)y;
874 for( int i=sz; --i>=0; ++rp ) *rp = 0.f;
875 float *gp = (float *)u;
876 for( int i=sz; --i>=0; ++gp ) *gp = 0.f;
877 float *bp = (float *)v;
878 for( int i=sz; --i>=0; ++bp ) *bp = 0.f;
887 ZERO_YUV(3, unsigned char, 0xff);
891 ZERO_YUV(4, unsigned char, 0xff);
895 ZERO_YUV(3, uint16_t, 0xffff);
898 case BC_YUVA16161616:
899 ZERO_YUV(4, uint16_t, 0xffff);
903 bzero(data, calculate_data_size(w, h, bytes_per_line, color_model));
909 void VFrame::rotate90()
911 // Allocate new frame
912 int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
913 unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
914 unsigned char **new_rows = new unsigned char*[new_h];
915 for(int i = 0; i < new_h; i++)
916 new_rows[i] = &new_data[new_bytes_per_line * i];
919 for(int in_y = 0, out_x = new_w - 1; in_y < h; in_y++, out_x--)
921 for(int in_x = 0, out_y = 0; in_x < w; in_x++, out_y++)
923 for(int k = 0; k < bytes_per_pixel; k++)
925 new_rows[out_y][out_x * bytes_per_pixel + k] =
926 rows[in_y][in_x * bytes_per_pixel + k];
935 bytes_per_line = new_bytes_per_line;
940 void VFrame::rotate270()
942 // Allocate new frame
943 int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
944 unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
945 unsigned char **new_rows = new unsigned char*[new_h];
946 for(int i = 0; i < new_h; i++)
947 new_rows[i] = &new_data[new_bytes_per_line * i];
950 for(int in_y = 0, out_x = 0; in_y < h; in_y++, out_x++)
952 for(int in_x = 0, out_y = new_h - 1; in_x < w; in_x++, out_y--)
954 for(int k = 0; k < bytes_per_pixel; k++)
956 new_rows[out_y][out_x * bytes_per_pixel + k] =
957 rows[in_y][in_x * bytes_per_pixel + k];
966 bytes_per_line = new_bytes_per_line;
971 void VFrame::flip_vert()
973 unsigned char *temp = new unsigned char[bytes_per_line];
974 for(int i = 0, j = h - 1; i < j; i++, j--)
976 memcpy(temp, rows[j], bytes_per_line);
977 memcpy(rows[j], rows[i], bytes_per_line);
978 memcpy(rows[i], temp, bytes_per_line);
983 void VFrame::flip_horiz()
985 unsigned char temp[32];
986 for(int i = 0; i < h; i++)
988 unsigned char *row = rows[i];
989 for(int j = 0; j < bytes_per_line / 2; j += bytes_per_pixel)
991 memcpy(temp, row + j, bytes_per_pixel);
992 memcpy(row + j, row + bytes_per_line - j - bytes_per_pixel, bytes_per_pixel);
993 memcpy(row + bytes_per_line - j - bytes_per_pixel, temp, bytes_per_pixel);
1000 int VFrame::copy_from(VFrame *frame)
1002 int w = MIN(this->w, frame->get_w());
1003 int h = MIN(this->h, frame->get_h());
1004 timestamp = frame->timestamp;
1006 switch(frame->color_model)
1009 allocate_compressed_data(frame->compressed_size);
1010 memcpy(data, frame->data, frame->compressed_size);
1011 this->compressed_size = frame->compressed_size;
1015 memcpy(get_y(), frame->get_y(), w * h);
1016 memcpy(get_u(), frame->get_u(), w / 4 * h / 4);
1017 memcpy(get_v(), frame->get_v(), w / 4 * h / 4);
1023 //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());
1024 memcpy(get_y(), frame->get_y(), w * h);
1025 memcpy(get_u(), frame->get_u(), w * h / 4);
1026 memcpy(get_v(), frame->get_v(), w * h / 4);
1030 //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());
1031 memcpy(get_y(), frame->get_y(), w * h);
1032 memcpy(get_u(), frame->get_u(), w * h / 2);
1033 memcpy(get_v(), frame->get_v(), w * h / 2);
1037 //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());
1038 memcpy(get_y(), frame->get_y(), w * h);
1039 memcpy(get_u(), frame->get_u(), w * h);
1040 memcpy(get_v(), frame->get_v(), w * h);
1043 // printf("VFrame::copy_from %d\n", calculate_data_size(w,
1046 // frame->color_model));
1047 // Copy without extra 4 bytes in case the source is a hardware device
1048 memmove(data, frame->data, get_data_size());
1055 int VFrame::transfer_from(VFrame *that, int bg_color, int in_x, int in_y, int in_w, int in_h)
1057 if( this->get_color_model() == that->get_color_model() &&
1058 this->get_w() == that->get_w() && this->get_h() == that->get_h() &&
1059 this->get_bytes_per_line() == that->get_bytes_per_line() )
1060 return this->copy_from(that);
1062 timestamp = that->timestamp;
1064 BC_CModels::transfer(
1065 this->get_rows(), that->get_rows(), // Packed data out/in
1066 this->get_y(), this->get_u(), this->get_v(), // Planar data out/in
1067 that->get_y(), that->get_u(), that->get_v(),
1068 0, 0, that->get_w(), that->get_h(), // Dimensions in/out
1069 0, 0, this->get_w(), this->get_h(),
1070 that->get_color_model(), this->get_color_model(), // Color models in/out
1071 bg_color, // alpha blend bg_color
1072 that->get_bytes_per_line(),
1073 this->get_bytes_per_line()); // rowspans (of luma for YUV)
1075 unsigned char *in_ptrs[4], *out_ptrs[4];
1076 unsigned char **inp, **outp;
1077 if( BC_CModels::is_planar(that->get_color_model()) ) {
1078 in_ptrs[0] = that->get_y();
1079 in_ptrs[1] = that->get_u();
1080 in_ptrs[2] = that->get_v();
1081 in_ptrs[3] = that->get_a();
1085 inp = that->get_rows();
1086 if( BC_CModels::is_planar(this->get_color_model()) ) {
1087 out_ptrs[0] = this->get_y();
1088 out_ptrs[1] = this->get_u();
1089 out_ptrs[2] = this->get_v();
1090 out_ptrs[3] = this->get_a();
1094 outp = this->get_rows();
1095 BC_CModels::transfer(outp, this->get_color_model(),
1096 0, 0, this->get_w(), this->get_h(),
1097 this->get_bytes_per_line(),
1098 inp, that->get_color_model(),
1099 in_x, in_y, in_w, in_h,
1100 that->get_bytes_per_line(),
1111 #define OVERLAY(type, max, components) \
1113 type **in_rows = (type**)src->get_rows(); \
1114 type **out_rows = (type**)get_rows(); \
1115 int in_w = src->get_w(); \
1116 int in_h = src->get_h(); \
1118 for(int i = 0; i < in_h; i++) \
1120 if(i + out_y1 >= 0 && i + out_y1 < h) \
1122 type *src_row = in_rows[i]; \
1123 type *dst_row = out_rows[i + out_y1] + out_x1 * components; \
1125 for(int j = 0; j < in_w; j++) \
1127 if(j + out_x1 >= 0 && j + out_x1 < w) \
1129 int opacity = src_row[3]; \
1130 int transparency = dst_row[3] * (max - src_row[3]) / max; \
1131 dst_row[0] = (transparency * dst_row[0] + opacity * src_row[0]) / max; \
1132 dst_row[1] = (transparency * dst_row[1] + opacity * src_row[1]) / max; \
1133 dst_row[2] = (transparency * dst_row[2] + opacity * src_row[2]) / max; \
1134 dst_row[3] = MAX(dst_row[3], src_row[3]); \
1137 dst_row += components; \
1138 src_row += components; \
1145 void VFrame::overlay(VFrame *src,
1149 switch(get_color_model())
1152 OVERLAY(unsigned char, 0xff, 4);
1159 int VFrame::get_scale_tables(int *column_table, int *row_table,
1160 int in_x1, int in_y1, int in_x2, int in_y2,
1161 int out_x1, int out_y1, int out_x2, int out_y2)
1164 float w_in = in_x2 - in_x1;
1165 float h_in = in_y2 - in_y1;
1166 int w_out = out_x2 - out_x1;
1167 int h_out = out_y2 - out_y1;
1169 float hscale = w_in / w_out;
1170 float vscale = h_in / h_out;
1172 for(i = 0; i < w_out; i++)
1174 column_table[i] = (int)(hscale * i);
1177 for(i = 0; i < h_out; i++)
1179 row_table[i] = (int)(vscale * i) + in_y1;
1184 void VFrame::push_prev_effect(const char *name)
1187 prev_effects.append(ptr = new char[strlen(name) + 1]);
1189 if(prev_effects.total > MAX_STACK_ELEMENTS) prev_effects.remove_object(0);
1192 void VFrame::pop_prev_effect()
1194 if(prev_effects.total)
1195 prev_effects.remove_object(prev_effects.last());
1198 void VFrame::push_next_effect(const char *name)
1201 next_effects.append(ptr = new char[strlen(name) + 1]);
1203 if(next_effects.total > MAX_STACK_ELEMENTS) next_effects.remove_object(0);
1206 void VFrame::pop_next_effect()
1208 if(next_effects.total)
1209 next_effects.remove_object(next_effects.last());
1212 const char* VFrame::get_next_effect(int number)
1214 if(!next_effects.total) return "";
1216 if(number > next_effects.total - 1) number = next_effects.total - 1;
1218 return next_effects.values[next_effects.total - number - 1];
1221 const char* VFrame::get_prev_effect(int number)
1223 if(!prev_effects.total) return "";
1225 if(number > prev_effects.total - 1) number = prev_effects.total - 1;
1227 return prev_effects.values[prev_effects.total - number - 1];
1230 BC_Hash* VFrame::get_params()
1235 void VFrame::clear_stacks()
1237 next_effects.remove_all_objects();
1238 prev_effects.remove_all_objects();
1243 void VFrame::copy_params(VFrame *src)
1245 status = src->status;
1246 params->copy_from(src->params);
1249 void VFrame::copy_stacks(VFrame *src)
1253 for(int i = 0; i < src->next_effects.total; i++)
1256 next_effects.append(ptr = new char[strlen(src->next_effects.values[i]) + 1]);
1257 strcpy(ptr, src->next_effects.values[i]);
1259 for(int i = 0; i < src->prev_effects.total; i++)
1262 prev_effects.append(ptr = new char[strlen(src->prev_effects.values[i]) + 1]);
1263 strcpy(ptr, src->prev_effects.values[i]);
1269 int VFrame::equal_stacks(VFrame *src)
1271 for(int i = 0; i < src->next_effects.total && i < next_effects.total; i++)
1273 if(strcmp(src->next_effects.values[i], next_effects.values[i])) return 0;
1276 for(int i = 0; i < src->prev_effects.total && i < prev_effects.total; i++)
1278 if(strcmp(src->prev_effects.values[i], prev_effects.values[i])) return 0;
1281 if(!params->equivalent(src->params)) return 0;
1285 void VFrame::dump_stacks()
1287 printf("VFrame::dump_stacks\n");
1288 printf(" next_effects:\n");
1289 for(int i = next_effects.total - 1; i >= 0; i--)
1290 printf(" %s\n", next_effects.values[i]);
1291 printf(" prev_effects:\n");
1292 for(int i = prev_effects.total - 1; i >= 0; i--)
1293 printf(" %s\n", prev_effects.values[i]);
1296 void VFrame::dump_params()
1303 printf("VFrame::dump %d this=%p\n", __LINE__, this);
1304 printf(" w=%d h=%d colormodel=%d rows=%p use_shm=%d shmid=%d\n",
1305 w, h, color_model, rows, use_shm, shmid);
1309 int VFrame::get_memory_usage()
1311 if(get_compressed_allocated()) return get_compressed_allocated();
1312 return get_h() * get_bytes_per_line();
1315 void VFrame::draw_pixel(int x, int y)
1317 if(!(x >= 0 && y >= 0 && x < get_w() && y < get_h())) return;
1319 #define DRAW_PIXEL(x, y, components, do_yuv, max, type) \
1321 type **rows = (type**)get_rows(); \
1322 rows[y][x * components] = max - rows[y][x * components]; \
1325 rows[y][x * components + 1] = max - rows[y][x * components + 1]; \
1326 rows[y][x * components + 2] = max - rows[y][x * components + 2]; \
1330 rows[y][x * components + 1] = (max / 2 + 1) - rows[y][x * components + 1]; \
1331 rows[y][x * components + 2] = (max / 2 + 1) - rows[y][x * components + 2]; \
1333 if(components == 4) \
1334 rows[y][x * components + 3] = max; \
1338 switch(get_color_model())
1341 DRAW_PIXEL(x, y, 3, 0, 0xff, unsigned char);
1344 DRAW_PIXEL(x, y, 4, 0, 0xff, unsigned char);
1347 DRAW_PIXEL(x, y, 3, 0, 1.0, float);
1350 DRAW_PIXEL(x, y, 4, 0, 1.0, float);
1353 DRAW_PIXEL(x, y, 3, 1, 0xff, unsigned char);
1356 DRAW_PIXEL(x, y, 4, 1, 0xff, unsigned char);
1359 DRAW_PIXEL(x, y, 3, 0, 0xffff, uint16_t);
1362 DRAW_PIXEL(x, y, 3, 1, 0xffff, uint16_t);
1364 case BC_RGBA16161616:
1365 DRAW_PIXEL(x, y, 4, 0, 0xffff, uint16_t);
1367 case BC_YUVA16161616:
1368 DRAW_PIXEL(x, y, 4, 1, 0xffff, uint16_t);
1374 void VFrame::draw_line(int x1, int y1, int x2, int y2)
1376 int w = labs(x2 - x1);
1377 int h = labs(y2 - y1);
1378 //printf("FindObjectMain::draw_line 1 %d %d %d %d\n", x1, y1, x2, y2);
1387 // Flip coordinates so x1 < x2
1397 int numerator = y2 - y1;
1398 int denominator = x2 - x1;
1399 for(int i = x1; i <= x2; i++)
1401 int y = y1 + (int64_t)(i - x1) * (int64_t)numerator / (int64_t)denominator;
1407 // Flip coordinates so y1 < y2
1417 int numerator = x2 - x1;
1418 int denominator = y2 - y1;
1419 for(int i = y1; i <= y2; i++)
1421 int x = x1 + (int64_t)(i - y1) * (int64_t)numerator / (int64_t)denominator;
1425 //printf("FindObjectMain::draw_line 2\n");
1428 void VFrame::draw_rect(int x1, int y1, int x2, int y2)
1430 draw_line(x1, y1, x2, y1);
1431 draw_line(x2, y1 + 1, x2, y2);
1432 draw_line(x2 - 1, y2, x1, y2);
1433 draw_line(x1, y2 - 1, x1, y1 + 1);
1436 #define ARROW_SIZE 10
1437 void VFrame::draw_arrow(int x1, int y1, int x2, int y2)
1439 double angle = atan((float)(y2 - y1) / (float)(x2 - x1));
1440 double angle1 = angle + (float)145 / 360 * 2 * 3.14159265;
1441 double angle2 = angle - (float)145 / 360 * 2 * 3.14159265;
1448 x3 = x2 - (int)(ARROW_SIZE * cos(angle1));
1449 y3 = y2 - (int)(ARROW_SIZE * sin(angle1));
1450 x4 = x2 - (int)(ARROW_SIZE * cos(angle2));
1451 y4 = y2 - (int)(ARROW_SIZE * sin(angle2));
1455 x3 = x2 + (int)(ARROW_SIZE * cos(angle1));
1456 y3 = y2 + (int)(ARROW_SIZE * sin(angle1));
1457 x4 = x2 + (int)(ARROW_SIZE * cos(angle2));
1458 y4 = y2 + (int)(ARROW_SIZE * sin(angle2));
1462 draw_line(x1, y1, x2, y2);
1463 // draw_line(x1, y1 + 1, x2, y2 + 1);
1466 if(abs(y2 - y1) || abs(x2 - x1)) draw_line(x2, y2, x3, y3);
1468 if(abs(y2 - y1) || abs(x2 - x1)) draw_line(x2, y2, x4, y4);