6 //#include "bccounter.h"
8 #include "colormodels.h"
14 static void png_read_function(png_structp png_ptr,
18 VFrame *frame = (VFrame*)png_get_io_ptr(png_ptr);
19 if(frame->image_size - frame->image_offset < length)
20 length = frame->image_size - frame->image_offset;
22 memcpy(data, &frame->image[frame->image_offset], length);
23 frame->image_offset += length;
33 //static BCCounter counter;
36 VFrame::VFrame(unsigned char *png_data)
38 //printf("VFrame::VFrame 1\n");
40 //printf("VFrame::VFrame 1\n");
42 //printf("VFrame::VFrame 2\n");
45 VFrame::VFrame(VFrame &frame)
48 allocate_data(0, 0, 0, 0, frame.w, frame.h, frame.color_model, frame.bytes_per_line);
49 memcpy(data, frame.data, bytes_per_line * h);
53 VFrame::VFrame(unsigned char *data,
60 allocate_data(data, 0, 0, 0, w, h, color_model, bytes_per_line);
64 VFrame::VFrame(unsigned char *data,
88 this->color_model = BC_COMPRESSED;
108 long VFrame::set_shm_offset(long offset)
114 long VFrame::get_shm_offset()
119 int VFrame::params_match(int w, int h, int color_model)
121 return (this->w == w &&
123 this->color_model == color_model);
127 int VFrame::reset_parameters()
136 compressed_allocated = 0;
137 compressed_size = 0; // Size of current image
144 sequence_number = -1;
148 int VFrame::clear_objects()
151 //printf("VFrame::clear_objects 1 %p %d\n", this, shared);
154 int size = calculate_data_size(this->w, this->h, this->bytes_per_line, this->color_model);
155 //printf("VFrame::clear_objects %p %d %d\n", this, this->w, this->h);
156 //if(size > 1000000) printf("VFrame::clear_objects %d\n", size);
157 if(data) delete [] data;
161 // Delete row pointers
176 int VFrame::get_field2_offset()
178 return field2_offset;
181 int VFrame::set_field2_offset(int value)
183 this->field2_offset = value;
187 int VFrame::calculate_bytes_per_pixel(int color_model)
189 return cmodel_calculate_pixelsize(color_model);
192 long VFrame::get_bytes_per_line()
194 return bytes_per_line;
197 long VFrame::get_data_size()
199 return calculate_data_size(w, h, bytes_per_line, color_model) - 4;
200 // return h * bytes_per_line;
203 long VFrame::calculate_data_size(int w, int h, int bytes_per_line, int color_model)
205 return cmodel_calculate_datasize(w, h, bytes_per_line, color_model);
209 void VFrame::create_row_pointers()
218 this->u_offset = w * h;
219 this->v_offset = w * h + w * h / 4;
221 y = this->data + this->y_offset;
222 u = this->data + this->u_offset;
223 v = this->data + this->v_offset;
230 this->u_offset = w * h;
231 this->v_offset = w * h + w * h / 2;
233 y = this->data + this->y_offset;
234 u = this->data + this->u_offset;
235 v = this->data + this->v_offset;
239 rows = new unsigned char*[h];
240 for(int i = 0; i < h; i++)
242 rows[i] = &this->data[i * this->bytes_per_line];
248 int VFrame::allocate_data(unsigned char *data,
259 this->color_model = color_model;
260 this->bytes_per_pixel = calculate_bytes_per_pixel(color_model);
261 this->y_offset = this->u_offset = this->v_offset = 0;
263 if(bytes_per_line >= 0)
265 this->bytes_per_line = bytes_per_line;
268 this->bytes_per_line = this->bytes_per_pixel * w;
270 // Allocate data + padding for MMX
275 this->y_offset = y_offset;
276 this->u_offset = u_offset;
277 this->v_offset = v_offset;
282 int size = calculate_data_size(this->w, this->h, this->bytes_per_line, this->color_model);
283 this->data = new unsigned char[size];
285 printf("VFrame::allocate_data %dx%d: memory exhausted.\n", this->w, this->h);
287 //printf("VFrame::allocate_data %p %d %d\n", this, this->w, this->h);
288 //if(size > 1000000) printf("VFrame::allocate_data %d\n", size);
291 // Create row pointers
292 create_row_pointers();
296 void VFrame::set_memory(unsigned char *data,
303 this->y_offset = y_offset;
304 this->u_offset = u_offset;
305 this->v_offset = v_offset;
306 y = this->data + this->y_offset;
307 u = this->data + this->u_offset;
308 v = this->data + this->v_offset;
309 create_row_pointers();
312 // Reallocate uncompressed buffer with or without alpha
313 int VFrame::reallocate(unsigned char *data,
324 allocate_data(data, y_offset, u_offset, v_offset, w, h, color_model, bytes_per_line);
328 int VFrame::allocate_compressed_data(long bytes)
330 if(bytes < 1) return 1;
332 // Want to preserve original contents
333 if(data && compressed_allocated < bytes)
335 //printf("VFrame::allocate_compressed_data 1 %d\n", bytes);
336 unsigned char *new_data = new unsigned char[bytes];
337 //printf("VFrame::allocate_compressed_data 1\n");
338 bcopy(data, new_data, compressed_allocated);
339 //printf("VFrame::allocate_compressed_data 1\n");
341 //printf("VFrame::allocate_compressed_data 1\n");
343 compressed_allocated = bytes;
344 //printf("VFrame::allocate_compressed_data 2\n");
349 data = new unsigned char[bytes];
350 compressed_allocated = bytes;
357 int VFrame::read_png(unsigned char *data)
359 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
360 png_infop info_ptr = png_create_info_struct(png_ptr);
365 image_size = (((unsigned long)data[0]) << 24) |
366 (((unsigned long)data[1]) << 16) |
367 (((unsigned long)data[2]) << 8) |
368 (unsigned char)data[3];
369 png_set_read_fn(png_ptr, this, PngReadFunction::png_read_function);
370 png_read_info(png_ptr, info_ptr);
372 w = png_get_image_width(png_ptr, info_ptr);
373 h = png_get_image_height(png_ptr, info_ptr);
375 switch(png_get_color_type(png_ptr, info_ptr))
377 case PNG_COLOR_TYPE_RGB:
378 new_color_model = BC_RGB888;
381 case PNG_COLOR_TYPE_RGB_ALPHA:
383 new_color_model = BC_RGBA8888;
396 png_read_image(png_ptr, get_rows());
397 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
401 unsigned char* VFrame::get_data()
406 long VFrame::get_compressed_allocated()
408 return compressed_allocated;
411 long VFrame::get_compressed_size()
413 return compressed_size;
416 long VFrame::set_compressed_size(long size)
418 compressed_size = size;
422 int VFrame::get_color_model()
428 int VFrame::equals(VFrame *frame)
430 if(frame->data == data)
436 #define ZERO_YUV(components, type, max) \
438 for(int i = 0; i < h; i++) \
440 type *row = (type*)get_rows()[i]; \
441 for(int j = 0; j < w; j++) \
443 row[j * components] = 0; \
444 row[j * components + 1] = (max + 1) / 2; \
445 row[j * components + 2] = (max + 1) / 2; \
446 if(components == 4) row[j * components + 3] = 0; \
451 int VFrame::clear_frame()
459 bzero(data, h * w * 2);
463 ZERO_YUV(3, unsigned char, 0xff);
467 ZERO_YUV(4, unsigned char, 0xff);
471 ZERO_YUV(3, uint16_t, 0xffff);
474 case BC_YUVA16161616:
475 ZERO_YUV(4, uint16_t, 0xffff);
479 bzero(data, h * bytes_per_line);
485 void VFrame::rotate90()
487 // Allocate new frame
488 int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
489 unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
490 unsigned char **new_rows = new unsigned char*[new_h];
491 for(int i = 0; i < new_h; i++)
492 new_rows[i] = &new_data[new_bytes_per_line * i];
495 for(int in_y = 0, out_x = new_w - 1; in_y < h; in_y++, out_x--)
497 for(int in_x = 0, out_y = 0; in_x < w; in_x++, out_y++)
499 for(int k = 0; k < bytes_per_pixel; k++)
501 new_rows[out_y][out_x * bytes_per_pixel + k] =
502 rows[in_y][in_x * bytes_per_pixel + k];
511 bytes_per_line = new_bytes_per_line;
516 void VFrame::rotate270()
518 // Allocate new frame
519 int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
520 unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
521 unsigned char **new_rows = new unsigned char*[new_h];
522 for(int i = 0; i < new_h; i++)
523 new_rows[i] = &new_data[new_bytes_per_line * i];
526 for(int in_y = 0, out_x = 0; in_y < h; in_y++, out_x++)
528 for(int in_x = 0, out_y = new_h - 1; in_x < w; in_x++, out_y--)
530 for(int k = 0; k < bytes_per_pixel; k++)
532 new_rows[out_y][out_x * bytes_per_pixel + k] =
533 rows[in_y][in_x * bytes_per_pixel + k];
542 bytes_per_line = new_bytes_per_line;
547 void VFrame::flip_vert()
549 for(int i = 0, j = h - 1; i < j; i++, j--)
551 for(int k = 0; k < bytes_per_line; k++)
553 unsigned char temp = rows[j][k];
554 rows[j][k] = rows[i][k];
561 #define APPLY_FADE(equivalent, input_rows, output_rows, max, type, chroma_zero, components) \
563 int64_t opacity = (int64_t)(alpha * max); \
564 int64_t transparency = (int64_t)(max - opacity); \
566 for(int i = 0; i < h; i++) \
568 type *in_row = (type*)input_rows[i]; \
569 type *out_row = (type*)output_rows[i]; \
571 for(int j = 0; j < w; j++) \
573 if(components == 3) \
575 out_row[j * components] = \
576 (type)((int64_t)in_row[j * components] * opacity / max); \
577 out_row[j * components + 1] = \
578 (type)(((int64_t)in_row[j * components + 1] * opacity + \
579 (int64_t)chroma_zero * transparency) / max); \
580 out_row[j * components + 2] = \
581 (type)(((int64_t)in_row[j * components + 2] * opacity + \
582 (int64_t)chroma_zero * transparency) / max); \
588 out_row[j * components] = in_row[j * components]; \
589 out_row[j * components + 1] = in_row[j * components + 1]; \
590 out_row[j * components + 2] = in_row[j * components + 2]; \
593 out_row[j * components + 3] = \
594 (type)((int64_t)in_row[j * components + 3] * opacity / max); \
601 // Fade the frame but don't move data around
602 int VFrame::apply_fade(float alpha)
604 printf("VFrame::apply_fade: Never call this. Use FadeEngine instead.\n");
610 APPLY_FADE(1, rows, rows, 0xff, unsigned char, 0x0, 3);
613 APPLY_FADE(1, rows, rows, 0xff, unsigned char, 0x0, 4);
616 APPLY_FADE(1, rows, rows, 0xffff, uint16_t, 0x0, 3);
618 case BC_RGBA16161616:
619 APPLY_FADE(1, rows, rows, 0xffff, uint16_t, 0x0, 4);
622 APPLY_FADE(1, rows, rows, 0xff, unsigned char, 0x80, 3);
625 APPLY_FADE(1, rows, rows, 0xff, unsigned char, 0x80, 4);
628 APPLY_FADE(1, rows, rows, 0xffff, uint16_t, 0x8000, 3);
630 case BC_YUVA16161616:
631 APPLY_FADE(1, rows, rows, 0xffff, uint16_t, 0x8000, 4);
638 // Fade the frame while moving data around
639 int VFrame::replace_from(VFrame *frame, float alpha)
641 printf("VFrame::replace_from: Never call this. Use FadeEngine instead.\n");
647 APPLY_FADE(0, rows, frame->get_rows(), 0xff, unsigned char, 0x0, 3);
650 APPLY_FADE(0, rows, frame->get_rows(), 0xff, unsigned char, 0x0, 4);
653 APPLY_FADE(0, rows, frame->get_rows(), 0xffff, uint16_t, 0x0, 3);
655 case BC_RGBA16161616:
656 APPLY_FADE(0, rows, frame->get_rows(), 0xffff, uint16_t, 0x0, 4);
659 APPLY_FADE(0, rows, frame->get_rows(), 0xff, unsigned char, 0x80, 3);
662 APPLY_FADE(0, rows, frame->get_rows(), 0xff, unsigned char, 0x80, 4);
665 APPLY_FADE(0, rows, frame->get_rows(), 0xffff, uint16_t, 0x8000, 3);
667 case BC_YUVA16161616:
668 APPLY_FADE(0, rows, frame->get_rows(), 0xffff, uint16_t, 0x8000, 4);
678 int VFrame::copy_from(VFrame *frame)
680 switch(frame->color_model)
683 allocate_compressed_data(frame->compressed_size);
684 memcpy(data, frame->data, frame->compressed_size);
685 this->compressed_size = frame->compressed_size;
689 //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());
690 memcpy(get_y(), frame->get_y(), w * h);
691 memcpy(get_u(), frame->get_u(), w * h / 4);
692 memcpy(get_v(), frame->get_v(), w * h / 4);
696 //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());
697 memcpy(get_y(), frame->get_y(), w * h);
698 memcpy(get_u(), frame->get_u(), w * h / 2);
699 memcpy(get_v(), frame->get_v(), w * h / 2);
703 // printf("VFrame::copy_from %d\n", calculate_data_size(w,
706 // frame->color_model));
707 memcpy(data, frame->data, calculate_data_size(w,
710 frame->color_model));
718 #define OVERLAY(type, max, components) \
720 type **in_rows = (type**)src->get_rows(); \
721 type **out_rows = (type**)get_rows(); \
722 int in_w = src->get_w(); \
723 int in_h = src->get_h(); \
725 for(int i = 0; i < in_h; i++) \
727 if(i + out_y1 >= 0 && i + out_y1 < h) \
729 type *src_row = in_rows[i]; \
730 type *dst_row = out_rows[i + out_y1] + out_x1 * components; \
732 for(int j = 0; j < in_w; j++) \
734 if(j + out_x1 >= 0 && j + out_x1 < w) \
736 int opacity = src_row[3]; \
737 int transparency = max - src_row[3]; \
738 dst_row[0] = (transparency * dst_row[0] + opacity * src_row[0]) / max; \
739 dst_row[1] = (transparency * dst_row[1] + opacity * src_row[1]) / max; \
740 dst_row[2] = (transparency * dst_row[2] + opacity * src_row[2]) / max; \
741 dst_row[3] = MAX(dst_row[3], src_row[3]); \
744 dst_row += components; \
745 src_row += components; \
752 void VFrame::overlay(VFrame *src,
756 switch(get_color_model())
759 OVERLAY(unsigned char, 0xff, 4);
766 int VFrame::get_scale_tables(int *column_table, int *row_table,
767 int in_x1, int in_y1, int in_x2, int in_y2,
768 int out_x1, int out_y1, int out_x2, int out_y2)
771 float w_in = in_x2 - in_x1;
772 float h_in = in_y2 - in_y1;
773 int w_out = out_x2 - out_x1;
774 int h_out = out_y2 - out_y1;
776 float hscale = w_in / w_out;
777 float vscale = h_in / h_out;
779 for(i = 0; i < w_out; i++)
781 column_table[i] = (int)(hscale * i);
784 for(i = 0; i < h_out; i++)
786 row_table[i] = (int)(vscale * i) + in_y1;
791 int VFrame::get_bytes_per_pixel()
793 return bytes_per_pixel;
796 unsigned char** VFrame::get_rows()
815 int VFrame::get_w_fixed()
820 int VFrame::get_h_fixed()
825 unsigned char* VFrame::get_y()
830 unsigned char* VFrame::get_u()
835 unsigned char* VFrame::get_v()
840 void VFrame::set_number(long number)
842 sequence_number = number;
845 long VFrame::get_number()
847 return sequence_number;