home *** CD-ROM | disk | FTP | other *** search
/ Geek 6 / Geek-006.iso / linux / video / xmovie-1.5.3.tar.gz / xmovie-1.5.3.tar / xmovie-1.5.3 / guicast / vframe.C < prev    next >
C/C++ Source or Header  |  2000-11-29  |  13KB  |  734 lines

  1. #include <png.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4.  
  5. #include "clip.h"
  6. #include "colormodels.h"
  7. #include "vframe.h"
  8.  
  9. class PngReadFunction
  10. {
  11. public:
  12.     static void png_read_function(png_structp png_ptr,
  13.                    png_bytep data, 
  14.                    png_size_t length)
  15.     {
  16.         VFrame *frame = (VFrame*)png_get_io_ptr(png_ptr);
  17.         if(frame->image_size - frame->image_offset < length) 
  18.             length = frame->image_size - frame->image_offset;
  19.  
  20.         memcpy(data, &frame->image[frame->image_offset], length);
  21.         frame->image_offset += length;
  22.     };
  23. };
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34. VFrame::VFrame(VFrame &frame)
  35. {
  36.     reset_parameters();
  37.     allocate_data(0, 0, 0, 0, frame.w, frame.h, frame.color_model, frame.bytes_per_line);
  38.     memcpy(data, frame.data, bytes_per_line * h);
  39. }
  40.  
  41. VFrame::VFrame(unsigned char *png_data)
  42. {
  43.     reset_parameters();
  44.     read_png(png_data);
  45. }
  46.  
  47. VFrame::VFrame(unsigned char *data, 
  48.     int w, 
  49.     int h, 
  50.     int color_model, 
  51.     long bytes_per_line)
  52. {
  53.     reset_parameters();
  54.     allocate_data(data, 0, 0, 0, w, h, color_model, bytes_per_line);
  55. }
  56.  
  57. VFrame::VFrame(unsigned char *data, 
  58.         long y_offset,
  59.         long u_offset,
  60.         long v_offset, 
  61.         int w, 
  62.         int h, 
  63.         int color_model = BC_RGBA8888, 
  64.         long bytes_per_line = -1)
  65. {
  66.     reset_parameters();
  67.     allocate_data(data, 
  68.         y_offset, 
  69.         u_offset, 
  70.         v_offset, 
  71.         w, 
  72.         h, 
  73.         color_model, 
  74.         bytes_per_line);
  75. }
  76.  
  77. VFrame::VFrame()
  78. {
  79.     reset_parameters();
  80.     this->color_model = BC_COMPRESSED;
  81. }
  82.  
  83.  
  84.  
  85.  
  86.  
  87.  
  88.  
  89.  
  90.  
  91.  
  92.  
  93. VFrame::~VFrame()
  94. {
  95.     clear_objects();
  96. }
  97.  
  98. long VFrame::set_shm_offset(long offset)
  99. {
  100.     shm_offset = offset;
  101.     return 0;
  102. }
  103.  
  104. long VFrame::get_shm_offset()
  105. {
  106.     return shm_offset;
  107. }
  108.  
  109. int VFrame::params_match(int w, int h, int color_model)
  110. {
  111.     return (this->w == w &&
  112.         this->h == h &&
  113.         this->color_model == color_model);
  114. }
  115.  
  116.  
  117. int VFrame::reset_parameters()
  118. {
  119.     field2_offset = 0;
  120.     shared = 0;
  121.     bytes_per_line = 0;
  122.     data = 0;
  123.     rows = 0;
  124.     color_model = 0;
  125.     compressed_allocated = 0;
  126.     compressed_size = 0;   // Size of current image
  127.     w = 0;
  128.     h = 0;
  129.     y = u = v = 0;
  130.     return 0;
  131. }
  132.  
  133. int VFrame::clear_objects()
  134. {
  135. // Delete data
  136.     if(!shared)
  137.     {
  138.         if(data) delete [] data;
  139.         data = 0;
  140.     }
  141.  
  142. // Delete row pointers
  143.     switch(color_model)
  144.     {
  145.         case BC_COMPRESSED:
  146.         case BC_YUV420P:
  147.             break;
  148.  
  149.         default:
  150.             delete [] rows;
  151.             break;
  152.     }
  153.  
  154.     return 0;
  155. }
  156.  
  157. int VFrame::get_field2_offset()
  158. {
  159.     return field2_offset;
  160. }
  161.  
  162. int VFrame::set_field2_offset(int value)
  163. {
  164.     this->field2_offset = value;
  165.     return 0;
  166. }
  167.  
  168. int VFrame::calculate_bytes_per_pixel(int color_model)
  169. {
  170.     return cmodel_calculate_pixelsize(color_model);
  171. }
  172.  
  173. long VFrame::get_bytes_per_line()
  174. {
  175.     return bytes_per_line;
  176. }
  177.  
  178. long VFrame::get_data_size()
  179. {
  180.     return h * bytes_per_line;
  181. }
  182.  
  183. long VFrame::calculate_data_size(int w, int h, int bytes_per_line, int color_model)
  184. {
  185.     if(bytes_per_line < 0) bytes_per_line = w * calculate_bytes_per_pixel(color_model);
  186.     switch(color_model)
  187.     {
  188.         case BC_YUV420P:
  189.         case BC_YUV411P:
  190.             return w * h + w * h / 2 + 4;
  191.             break;
  192.  
  193.         case BC_YUV422P:
  194.             return w * h * 2 + 4;
  195.             break;
  196.  
  197.         default:
  198.             return h * bytes_per_line + 4;
  199.             break;
  200.     }
  201.     return 0;
  202. }
  203.  
  204. int VFrame::allocate_data(unsigned char *data, 
  205.     long y_offset,
  206.     long u_offset,
  207.     long v_offset,
  208.     int w, 
  209.     int h, 
  210.     int color_model, 
  211.     long bytes_per_line)
  212. {
  213.     this->w = w;
  214.     this->h = h;
  215.     this->color_model = color_model;
  216.     this->bytes_per_pixel = calculate_bytes_per_pixel(color_model);
  217.     this->y_offset = this->u_offset = this->v_offset = 0;
  218.  
  219.     if(bytes_per_line >= 0)
  220.     {
  221.         this->bytes_per_line = bytes_per_line;
  222.     }
  223.     else
  224.         this->bytes_per_line = this->bytes_per_pixel * w;
  225.  
  226. // Allocate data + padding for MMX
  227.     if(data)
  228.     {
  229.         shared = 1;
  230.         this->data = data;
  231.         this->y_offset = y_offset;
  232.         this->u_offset = u_offset;
  233.         this->v_offset = v_offset;
  234.     }
  235.     else
  236.     {
  237.         shared = 0;
  238.         this->data = new unsigned char[calculate_data_size(this->w, this->h, this->bytes_per_line, this->color_model)];
  239.     }
  240.  
  241. // Create row pointers
  242.     switch(color_model)
  243.     {
  244.         case BC_YUV420P:
  245.         case BC_YUV411P:
  246.             if(!this->v_offset)
  247.             {
  248.                 this->y_offset = 0;
  249.                 this->u_offset = w * h;
  250.                 this->v_offset = w * h + w * h / 4;
  251.             }
  252.             y = this->data + this->y_offset;
  253.             u = this->data + this->u_offset;
  254.             v = this->data + this->v_offset;
  255.             break;
  256.  
  257.         case BC_YUV422P:
  258.             if(!this->v_offset)
  259.             {
  260.                 this->y_offset = 0;
  261.                 this->u_offset = w * h;
  262.                 this->v_offset = w * h + w * h / 2;
  263.             }
  264.             y = this->data + this->y_offset;
  265.             u = this->data + this->u_offset;
  266.             v = this->data + this->v_offset;
  267.             break;
  268.  
  269.         default:
  270.             rows = new unsigned char*[h];
  271.             for(int i = 0; i < h; i++)
  272.             {
  273.                 rows[i] = &this->data[i * this->bytes_per_line];
  274.             }
  275.             break;
  276.     }
  277.     return 0;
  278. }
  279.  
  280. void VFrame::set_memory(unsigned char *data, 
  281.         long y_offset,
  282.         long u_offset,
  283.         long v_offset)
  284. {
  285.     shared = 1;
  286.     this->data = data;
  287.     this->y_offset = y_offset;
  288.     this->u_offset = u_offset;
  289.     this->v_offset = v_offset;
  290.     y = this->data + this->y_offset;
  291.     u = this->data + this->u_offset;
  292.     v = this->data + this->v_offset;
  293. }
  294.  
  295. // Reallocate uncompressed buffer with or without alpha
  296. int VFrame::reallocate(unsigned char *data, 
  297.         long y_offset,
  298.         long u_offset,
  299.         long v_offset,
  300.         int w, 
  301.         int h, 
  302.         int color_model, 
  303.         long bytes_per_line)
  304. {
  305.     clear_objects();
  306.     reset_parameters();
  307.     allocate_data(data, y_offset, u_offset, v_offset, w, h, color_model, bytes_per_line);
  308.     return 0;
  309. }
  310.  
  311. int VFrame::allocate_compressed_data(long bytes)
  312. {
  313.     if(bytes < 1) return 1;
  314.  
  315.     if(data && compressed_allocated < bytes)
  316.     {
  317.         delete [] data;
  318.         data = 0;
  319.     }
  320.  
  321.     if(!data)
  322.     {
  323.         data = new unsigned char[bytes];
  324.         compressed_allocated = bytes;
  325.         compressed_size = 0;
  326.     }
  327.  
  328.     return 0;
  329. }
  330.  
  331. int VFrame::read_png(unsigned char *data)
  332. {
  333.     png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
  334.     png_infop info_ptr = png_create_info_struct(png_ptr);
  335.     int new_color_model;
  336.  
  337.     image_offset = 0;
  338.     image = data + 4;
  339.     image_size = (((unsigned long)data[0]) << 24) | 
  340.         (((unsigned long)data[1]) << 16) | 
  341.         (((unsigned long)data[2]) << 8) | 
  342.         (unsigned char)data[3];
  343.     png_set_read_fn(png_ptr, this, PngReadFunction::png_read_function);
  344.     png_read_info(png_ptr, info_ptr);
  345.  
  346.     w = png_get_image_width(png_ptr, info_ptr);
  347.     h = png_get_image_height(png_ptr, info_ptr);
  348.  
  349.     switch(png_get_color_type(png_ptr, info_ptr))
  350.     {
  351.         case PNG_COLOR_TYPE_RGB:
  352.             new_color_model = BC_RGB888;
  353.             break;
  354.  
  355.         case PNG_COLOR_TYPE_RGB_ALPHA:
  356.         default:
  357.             new_color_model = BC_RGBA8888;
  358.             break;
  359.     }
  360.  
  361.     reallocate(NULL, 
  362.         0, 
  363.         0, 
  364.         0, 
  365.         w, 
  366.         h, 
  367.         new_color_model,
  368.         -1);
  369.  
  370.     png_read_image(png_ptr, get_rows());
  371.     png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
  372.     return 0;
  373. }
  374.  
  375. unsigned char* VFrame::get_data()
  376. {
  377.     return data;
  378. }
  379.  
  380. long VFrame::get_compressed_allocated()
  381. {
  382.     return compressed_allocated;
  383. }
  384.  
  385. long VFrame::get_compressed_size()
  386. {
  387.     return compressed_size;
  388. }
  389.  
  390. long VFrame::set_compressed_size(long size)
  391. {
  392.     compressed_size = size;
  393.     return 0;
  394. }
  395.  
  396. int VFrame::get_color_model()
  397. {
  398.     return color_model;
  399. }
  400.  
  401.  
  402. int VFrame::equals(VFrame *frame)
  403. {
  404.     if(frame->data == data) 
  405.         return 1;
  406.     else
  407.         return 0;
  408. }
  409.  
  410. int VFrame::clear_frame()
  411. {
  412.     switch(color_model)
  413.     {
  414.         case BC_COMPRESSED:
  415.             break;
  416.  
  417.         case BC_YUV420P:
  418.             memset(data, 0, h * w * 2);
  419.             break;
  420.  
  421.         default:
  422.             memset(data, 0, h * bytes_per_line);
  423.             break;
  424.     }
  425.     return 0;
  426. }
  427.  
  428. void VFrame::rotate90()
  429. {
  430. // Allocate new frame
  431.     int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
  432.     unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
  433.     unsigned char **new_rows = new unsigned char*[new_h];
  434.     for(int i = 0; i < new_h; i++)
  435.         new_rows[i] = &new_data[new_bytes_per_line * i];
  436.  
  437. // Copy data
  438.     for(int in_y = 0, out_x = new_w - 1; in_y < h; in_y++, out_x--)
  439.     {
  440.         for(int in_x = 0, out_y = 0; in_x < w; in_x++, out_y++)
  441.         {
  442.             for(int k = 0; k < bytes_per_pixel; k++)
  443.             {
  444.                 new_rows[out_y][out_x * bytes_per_pixel + k] = 
  445.                     rows[in_y][in_x * bytes_per_pixel + k];
  446.             }
  447.         }
  448.     }
  449.  
  450. // Swap frames
  451.     clear_objects();
  452.     data = new_data;
  453.     rows = new_rows;
  454.     bytes_per_line = new_bytes_per_line;
  455.     w = new_w;
  456.     h = new_h;
  457. }
  458.  
  459. void VFrame::rotate270()
  460. {
  461. // Allocate new frame
  462.     int new_w = h, new_h = w, new_bytes_per_line = bytes_per_pixel * new_w;
  463.     unsigned char *new_data = new unsigned char[calculate_data_size(new_w, new_h, new_bytes_per_line, color_model)];
  464.     unsigned char **new_rows = new unsigned char*[new_h];
  465.     for(int i = 0; i < new_h; i++)
  466.         new_rows[i] = &new_data[new_bytes_per_line * i];
  467.  
  468. // Copy data
  469.     for(int in_y = 0, out_x = 0; in_y < h; in_y++, out_x++)
  470.     {
  471.         for(int in_x = 0, out_y = new_h - 1; in_x < w; in_x++, out_y--)
  472.         {
  473.             for(int k = 0; k < bytes_per_pixel; k++)
  474.             {
  475.                 new_rows[out_y][out_x * bytes_per_pixel + k] = 
  476.                     rows[in_y][in_x * bytes_per_pixel + k];
  477.             }
  478.         }
  479.     }
  480.  
  481. // Swap frames
  482.     clear_objects();
  483.     data = new_data;
  484.     rows = new_rows;
  485.     bytes_per_line = new_bytes_per_line;
  486.     w = new_w;
  487.     h = new_h;
  488. }
  489.  
  490. void VFrame::flip_vert()
  491. {
  492.     for(int i = 0, j = h - 1; i < j; i++, j--)
  493.     {
  494.         for(int k = 0; k < bytes_per_line; k++)
  495.         {
  496.             unsigned char temp = rows[j][k];
  497.             rows[j][k] = rows[i][k];
  498.             rows[i][k] = temp;
  499.         }
  500.     }
  501. }
  502.  
  503. int VFrame::apply_fade(int alpha)
  504. {
  505.     register int i, j, k, channel;
  506.  
  507.     if(alpha != VMAX)
  508.     {
  509.         switch(color_model)
  510.         {
  511.             case BC_YUVA8888:
  512.             case BC_RGBA8888:
  513.                 for(i = 0; i < h; i++)
  514.                 {
  515.                     for(j = 0; j < w; j++)
  516.                     {
  517.                         channel = rows[i][j * 4 + 3];
  518.                         channel *= alpha;
  519.                         channel >>= 8;
  520.                         rows[i][j * 4 + 3] = channel;
  521.                     }
  522.                 }
  523.                 break;
  524.         }
  525.     }
  526.     return 0;
  527. }
  528.  
  529. int VFrame::replace_from(VFrame *frame, 
  530.         float alpha, 
  531.         int use_alpha, 
  532.         int use_float)
  533. {
  534.     register long i, j;
  535.  
  536.     if(alpha != 1)
  537.     {
  538.         int a_int = (int)CLIP(alpha * 255 + 0.5, 0, 255);
  539.  
  540.         switch(color_model)
  541.         {
  542.             case BC_RGBA8888:
  543.             case BC_YUVA8888:
  544.             {
  545.                 unsigned char **dst_rows = rows;
  546.                 unsigned char **src_rows = frame->get_rows();
  547.                 if(use_float)
  548.                 {
  549.                     for(i = 0; i < h; i++)
  550.                     {
  551.                         for(j = 0; j < w; j++)
  552.                         {
  553.                             dst_rows[i][j * 4 + 0] = src_rows[i][j * 4 + 0];
  554.                             dst_rows[i][j * 4 + 1] = src_rows[i][j * 4 + 1];
  555.                             dst_rows[i][j * 4 + 2] = src_rows[i][j * 4 + 2];
  556.                             dst_rows[i][j * 4 + 3] = (unsigned char)(src_rows[i][j * 4 + 3] * alpha + 0.5);
  557.                         }
  558.                     }
  559.                 }
  560.                 else
  561.                 {
  562.                     for(i = 0; i < h; i++)
  563.                     {
  564.                         for(j = 0; j < w; j++)
  565.                         {
  566.                             dst_rows[i][j * 4 + 0] = src_rows[i][j * 4 + 0];
  567.                             dst_rows[i][j * 4 + 1] = src_rows[i][j * 4 + 1];
  568.                             dst_rows[i][j * 4 + 2] = src_rows[i][j * 4 + 2];
  569.                             dst_rows[i][j * 4 + 3] = (unsigned char)(((int)src_rows[i][j * 4 + 3] * a_int) >> 8);
  570.                         }
  571.                     }
  572.                 }
  573.             }
  574.                 break;
  575.  
  576.             case BC_RGBA16161616:
  577.             case BC_YUVA16161616:
  578.             {
  579.                 unsigned short **dst_rows = (unsigned short**)rows;
  580.                 unsigned short **src_rows = (unsigned short**)frame->get_rows();
  581.                 if(use_float)
  582.                 {
  583.                     for(i = 0; i < h; i++)
  584.                     {
  585.                         for(j = 0; j < w; j++)
  586.                         {
  587.                             dst_rows[i][j * 4 + 0] = src_rows[i][j * 4 + 0];
  588.                             dst_rows[i][j * 4 + 1] = src_rows[i][j * 4 + 1];
  589.                             dst_rows[i][j * 4 + 2] = src_rows[i][j * 4 + 2];
  590.                             dst_rows[i][j * 4 + 3] = (unsigned short)(src_rows[i][j * 4 + 3] * alpha + 0.5);
  591.                         }
  592.                     }
  593.                 }
  594.                 else
  595.                 {
  596.                     for(i = 0; i < h; i++)
  597.                     {
  598.                         for(j = 0; j < w; j++)
  599.                         {
  600.                             dst_rows[i][j * 4 + 0] = src_rows[i][j * 4 + 0];
  601.                             dst_rows[i][j * 4 + 1] = src_rows[i][j * 4 + 1];
  602.                             dst_rows[i][j * 4 + 2] = src_rows[i][j * 4 + 2];
  603.                             dst_rows[i][j * 4 + 3] = (unsigned short)(((int)src_rows[i][j * 4 + 3] * a_int) >> 8);
  604.                         }
  605.                     }
  606.                 }
  607.             }
  608.                 break;
  609.  
  610.             default:
  611.                 memcpy(this->data, frame->data, h * bytes_per_line);
  612.                 break;
  613.         }
  614.     }
  615.     else        
  616.         memcpy(this->data, frame->data, h * bytes_per_line);
  617.  
  618.     return 0;
  619. }
  620.  
  621. int VFrame::copy_from(VFrame *frame)
  622. {
  623.     switch(frame->color_model)
  624.     {
  625.         case BC_COMPRESSED:
  626.             allocate_compressed_data(frame->compressed_size);
  627.             memcpy(data, frame->data, frame->compressed_size);
  628.             this->compressed_size = frame->compressed_size;
  629.             break;
  630.  
  631.         case BC_YUV420P:
  632. //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());
  633.             memcpy(get_y(), frame->get_y(), w * h);
  634.             memcpy(get_u(), frame->get_u(), w * h / 4);
  635.             memcpy(get_v(), frame->get_v(), w * h / 4);
  636.             break;
  637.  
  638.         default:
  639. // printf("VFrame::copy_from %d\n", calculate_data_size(w, 
  640. //                 h, 
  641. //                 -1, 
  642. //                 frame->color_model));
  643.             memcpy(data, frame->data, calculate_data_size(w, 
  644.                 h, 
  645.                 -1, 
  646.                 frame->color_model));
  647.             break;
  648.     }
  649.  
  650.     return 0;
  651. }
  652.  
  653.  
  654. int VFrame::get_scale_tables(int *column_table, int *row_table, 
  655.             int in_x1, int in_y1, int in_x2, int in_y2,
  656.             int out_x1, int out_y1, int out_x2, int out_y2)
  657. {
  658.     int y_out, i;
  659.     float w_in = in_x2 - in_x1;
  660.     float h_in = in_y2 - in_y1;
  661.     int w_out = out_x2 - out_x1;
  662.     int h_out = out_y2 - out_y1;
  663.  
  664.     float hscale = w_in / w_out;
  665.     float vscale = h_in / h_out;
  666.  
  667.     for(i = 0; i < w_out; i++)
  668.     {
  669.         column_table[i] = (int)(hscale * i);
  670.     }
  671.  
  672.     for(i = 0; i < h_out; i++)
  673.     {
  674.         row_table[i] = (int)(vscale * i) + in_y1;
  675.     }
  676.     return 0;
  677. }
  678.  
  679. int VFrame::get_bytes_per_pixel()
  680. {
  681.     return bytes_per_pixel;
  682. }
  683.  
  684. int VFrame::clear_pixel(VPixel &pixel)
  685. {
  686.     pixel.r = pixel.g = pixel.b = pixel.a = 0;
  687.     return 0;
  688. }
  689.  
  690. unsigned char** VFrame::get_rows()
  691. {
  692.     if(rows)
  693.     {
  694.         return rows;
  695.     }
  696.     return 0;
  697. }
  698.  
  699. int VFrame::get_w()
  700. {
  701.     return w;
  702. }
  703.  
  704. int VFrame::get_h()
  705. {
  706.     return h;
  707. }
  708.  
  709. int VFrame::get_w_fixed()
  710. {
  711.     return w - 1;
  712. }
  713.  
  714. int VFrame::get_h_fixed()
  715. {
  716.     return h - 1;
  717. }
  718.  
  719. unsigned char* VFrame::get_y()
  720. {
  721.     return y;
  722. }
  723.  
  724. unsigned char* VFrame::get_u()
  725. {
  726.     return u;
  727. }
  728.  
  729. unsigned char* VFrame::get_v()
  730. {
  731.     return v;
  732. }
  733.  
  734.