home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / gbmsrc.zip / gbmvid.c < prev    next >
C/C++ Source or Header  |  1996-12-04  |  12KB  |  523 lines

  1. /*
  2.  
  3. gbmvid.c - YUV12C M-Motion Video Frame Buffer format
  4.  
  5. Reads and writes 24 bit RGB.
  6.  
  7. */
  8.  
  9. /*...sincludes:0:*/
  10. #include <stdio.h>
  11. #include <ctype.h>
  12. #include <stddef.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <memory.h>
  16. #include <malloc.h>
  17. #include "gbm.h"
  18. #include "gbmhelp.h"
  19.  
  20. /*...vgbm\46\h:0:*/
  21. /*...vgbmhelp\46\h:0:*/
  22. /*...e*/
  23.  
  24. /*...suseful:0:*/
  25. #define    low_byte(w)    ((byte)  (          (w)&0x00ff)    )
  26. #define    high_byte(w)    ((byte) (((unsigned)(w)&0xff00)>>8))
  27. #define    make_word(a,b)    (((word)a) + (((word)b) << 8))
  28. /*...e*/
  29.  
  30. static GBMFT vid_gbmft =
  31.     {
  32.     "YUV12C",
  33.     "YUV12C M-Motion Video Frame Buffer",
  34.     "VID",
  35.     GBM_FT_R24|GBM_FT_W24,
  36.     };
  37.  
  38. #define    GBM_ERR_VID_BAD_W    ((GBM_ERR) 1000)
  39.  
  40. /*...svid_qft:0:*/
  41. GBM_ERR vid_qft(GBMFT *gbmft)
  42.     {
  43.     *gbmft = vid_gbmft;
  44.     return GBM_ERR_OK;
  45.     }
  46. /*...e*/
  47. /*...svid_rhdr:0:*/
  48. GBM_ERR vid_rhdr(const char *fn, int fd, GBM *gbm, const char *opt)
  49.     {
  50.     int w, h;
  51.     byte buf[16];
  52.  
  53.     fn=fn; opt=opt; /* Suppress 'unref arg' compiler warnings */
  54.  
  55.     if ( gbm_file_read(fd, buf, 16) != 16 )
  56.         return GBM_ERR_READ;
  57.  
  58.     if ( memcmp(buf, "YUV12C", 6) )
  59.         return GBM_ERR_BAD_MAGIC;
  60.  
  61.     w = make_word(buf[12], buf[13]);
  62.     h = make_word(buf[14], buf[15]);
  63.  
  64.     if ( w & 3 )
  65.         return GBM_ERR_VID_BAD_W;
  66.  
  67.     if ( w <= 0 || h <= 0 )
  68.         return GBM_ERR_BAD_SIZE;
  69.  
  70.     gbm->w   = w;
  71.     gbm->h   = h;
  72.     gbm->bpp = 24;
  73.  
  74.     return GBM_ERR_OK;
  75.     }
  76. /*...e*/
  77. /*...svid_rpal:0:*/
  78. GBM_ERR vid_rpal(int fd, GBM *gbm, GBMRGB *gbmrgb)
  79.     {
  80.     fd=fd; gbm=gbm; gbmrgb=gbmrgb; /* Suppress 'unref arg' compiler warnings */
  81.  
  82.     return GBM_ERR_OK;
  83.     }
  84. /*...e*/
  85. /*...svid_rdata:0:*/
  86. /*...sdata tables:0:*/
  87. static short tab1[] =
  88.     {
  89.     0,2,5,8,11,14,17,20,
  90.     22,25,28,31,34,37,40,42,
  91.     45,48,51,54,57,60,62,65,
  92.     68,71,74,77,80,82,85,88,
  93.     91,94,97,100,102,105,108,111,
  94.     114,117,120,122,125,128,131,134,
  95.     137,140,142,145,148,151,154,157,
  96.     160,163,165,168,171,174,177,180,
  97.     -183,-180,-177,-174,-171,-168,-165,-163,
  98.     -160,-157,-154,-151,-148,-145,-142,-140,
  99.     -137,-134,-131,-128,-125,-122,-120,-117,
  100.     -114,-111,-108,-105,-102,-100,-97,-94,
  101.     -91,-88,-85,-82,-80,-77,-74,-71,
  102.     -68,-65,-62,-60,-57,-54,-51,-48,
  103.     -45,-42,-40,-37,-34,-31,-28,-25,
  104.     -22,-20,-17,-14,-11,-8,-5,-2,
  105.     };
  106.  
  107. static short tab2[] =
  108.     {
  109.     0,0,-1,-1,-2,-2,-3,-3,
  110.     -4,-4,-5,-5,-6,-7,-7,-8,
  111.     -8,-9,-9,-10,-10,-11,-11,-12,
  112.     -13,-13,-14,-14,-15,-15,-16,-16,
  113.     -17,-17,-18,-19,-19,-20,-20,-21,
  114.     -21,-22,-22,-23,-23,-24,-24,-25,
  115.     -26,-26,-27,-27,-28,-28,-29,-29,
  116.     -30,-30,-31,-32,-32,-33,-33,-34,
  117.     34,34,33,33,32,32,31,30,
  118.     30,29,29,28,28,27,27,26,
  119.     26,25,24,24,23,23,22,22,
  120.     21,21,20,20,19,19,18,17,
  121.     17,16,16,15,15,14,14,13,
  122.     13,12,11,11,10,10,9,9,
  123.     8,8,7,7,6,5,5,4,
  124.     4,3,3,2,2,1,1,0,
  125.     };
  126.  
  127. static short tab3[] =
  128.     {
  129.     0,-1,-2,-3,-4,-5,-6,-8,
  130.     -9,-10,-11,-12,-13,-14,-16,-17,
  131.     -18,-19,-20,-21,-23,-24,-25,-26,
  132.     -27,-28,-29,-31,-32,-33,-34,-35,
  133.     -36,-37,-39,-40,-41,-42,-43,-44,
  134.     -46,-47,-48,-49,-50,-51,-52,-54,
  135.     -55,-56,-57,-58,-59,-60,-62,-63,
  136.     -64,-65,-66,-67,-69,-70,-71,-72,
  137.     73,72,71,70,69,67,66,65,
  138.     64,63,62,60,59,58,57,56,
  139.     55,54,52,51,50,49,48,47,
  140.     46,44,43,42,41,40,39,37,
  141.     36,35,34,33,32,31,29,28,
  142.     27,26,25,24,23,21,20,19,
  143.     18,17,16,14,13,12,11,10,
  144.     9,8,6,5,4,3,2,1,
  145.     };
  146.  
  147. static short tab4[] =
  148.     {
  149.     0,2,4,6,9,11,13,15,
  150.     18,20,22,24,27,29,31,33,
  151.     36,38,40,42,45,47,49,51,
  152.     54,56,58,60,63,65,67,69,
  153.     72,74,76,78,81,83,85,87,
  154.     90,92,94,96,99,101,103,105,
  155.     108,110,112,115,117,119,121,124,
  156.     126,128,130,133,135,137,139,142,
  157.     -144,-142,-139,-137,-135,-133,-130,-128,
  158.     -126,-124,-121,-119,-117,-115,-112,-110,
  159.     -108,-105,-103,-101,-99,-96,-94,-92,
  160.     -90,-87,-85,-83,-81,-78,-76,-74,
  161.     -72,-69,-67,-65,-63,-60,-58,-56,
  162.     -54,-51,-49,-47,-45,-42,-40,-38,
  163.     -36,-33,-31,-29,-27,-24,-22,-20,
  164.     -18,-15,-13,-11,-9,-6,-4,-2,
  165.     };
  166.  
  167. #ifdef NEVER
  168. static void make_tables(void)
  169.     {
  170.     int    i;
  171.     signed char j;
  172.  
  173.     for ( i = 0, j = 0; i < 0x80; i++, j += 2 )
  174.         {
  175. #ifdef NEVER
  176.         /* Version 1 */
  177.         tab1[i] = (short) ( 1.7874 * j);
  178.         tab2[i] = (short) (-0.3396 * j);
  179.         tab3[i] = (short) (-0.7188 * j);
  180.         tab4[i] = (short) ( 1.4094 * j);
  181. #endif
  182.         /* Version 2, 80% Saturation */
  183.         tab1[i] = (short) ( 1.4299 * j);
  184.         tab2[i] = (short) (-0.2717 * j);
  185.         tab3[i] = (short) (-0.5751 * j);
  186.         tab4[i] = (short) ( 1.1275 * j);
  187.         }
  188.     }
  189. #endif
  190. /*...e*/
  191. /*...sdecode_sites:0:*/
  192. /*
  193.  
  194. Supplied wordwise:
  195.  
  196. Which pixel:        00000000     11111111    2222 2222    33333333
  197. What comp:    uuvvyyyyyyyguuvv yyyyyyyguuvvyyyy yyygu_v_yyyyyyyg
  198. Bit posn:    76767654321 5454 7654321 32327654 321 1 1 7654321
  199.  
  200. Supplied bytewise:
  201.  
  202. Which pixel:    0000         0000     2222 11111111 33333333 2222    
  203. What comp:    yyyguuvv uuvvyyyy uuvvyyyy yyyyyyyg yyyyyyyg yyygu_v_
  204. Bit posn:    321 5454 76767654 32327654 7654321  7654321  321 1 1 
  205.  
  206. Desired:
  207.  
  208. Which pixel:    00000000 11111111 22222222 33333333
  209. What comp:    yyyyyyy_ yyyyyyy_ yyyyyyy_ yyyyyyy_ uuuuuuu_ vvvvvvv_
  210.  
  211. */
  212.  
  213. void    decode_sites(byte *src, byte *dest, int n_sites)
  214.     {
  215.     for ( ; n_sites--; src += 6 )
  216.         {
  217.         *dest++ = (byte) ( ((byte) (src[0] & 0xe0)>>4) |
  218.                    ((byte) (src[1] & 0x0f)<<4) );
  219.         *dest++ = (byte)    (byte) (src[3] & 0xfe)      ;
  220.         *dest++ = (byte) ( ((byte) (src[2] & 0x0f)<<4) |
  221.                    ((byte) (src[5] & 0xe0)>>4) );
  222.         *dest++ = (byte)    (byte) (src[4] & 0xfe)      ;
  223.         *dest++ = (byte) ( ((byte) (src[0] & 0x0c)<<2) |
  224.                     (byte) (src[1] & 0xc0)     |
  225.                    ((byte) (src[2] & 0xc0)>>4) |
  226.                    ((byte) (src[5] & 0x08)>>2) );
  227.         *dest++ = (byte) ( ((byte) (src[0] & 0x03)<<4) |
  228.                    ((byte) (src[1] & 0x30)<<2) |
  229.                    ((byte) (src[2] & 0x30)>>2) |
  230.                     (byte) (src[5] & 0x02)     );
  231.         }
  232.     }
  233. /*...e*/
  234. /*...sconvert_sites:0:*/
  235. /*...sVersion1:0:*/
  236. /*
  237.  
  238. Site has Y1 Y2 Y3 Y4 U V.
  239.  
  240. Input is of the form Y1 Y2 Y3 Y4 U V
  241.  
  242. R = ( V * 179 / 127 ) + Y
  243.  
  244. B = ( U * 227 / 127 ) + Y
  245.  
  246.     170 * Y - 51 * R - 19 * B
  247. G = -------------------------
  248.               100
  249.  
  250. Rewrite to give better optimisation ...
  251.  
  252. R = Y + 1.4094 * V
  253.  
  254. B = Y + 1.7874 * U
  255.  
  256. G = Y - 0.7188 * V - 0.3396 * U
  257.  
  258. */
  259. /*...e*/
  260. /*...sVersion2\44\ 80\37\ saturation \40\as recommended\41\:0:*/
  261. /*
  262.  
  263. Site has Y1 Y2 Y3 Y4 U V.
  264.  
  265. Input is of the form Y1 Y2 Y3 Y4 U V
  266.  
  267. R = 0.8 * ( V * 179 / 127 ) + Y
  268.  
  269. B = 0.8 * ( U * 227 / 127 ) + Y
  270.  
  271.     170 * Y - 51 * R - 19 * B
  272. G = -------------------------
  273.               100
  274.  
  275. Rewrite to give better optimisation ...
  276.  
  277. R = Y + 1.1275 * V
  278.  
  279. B = Y + 1.4299 * U
  280.  
  281. G = Y - 0.5751 * V - 0.2717 * U
  282.  
  283. */
  284. /*...e*/
  285.  
  286. void convert_sites(byte *src, byte *dest, int n_sites)
  287.     {
  288.     for ( ; n_sites--; src += 6 )
  289.         {
  290.         byte u   = (src[4] >> 1);
  291.         byte v   = (src[5] >> 1);
  292.         short tu = tab1[u];
  293.         short ts = tab2[u] + tab3[v];
  294.         short tv = tab4[v];
  295.         int p;
  296.  
  297.         for ( p = 0; p < 4; p++ )
  298.             {
  299.             short b = (short) ((unsigned short) src[p]) + tu;
  300.             short g = (short) ((unsigned short) src[p]) + ts;
  301.             short r = (short) ((unsigned short) src[p]) + tv;
  302.  
  303.             if ( b < 0 ) b = 0; else if ( b > 0xff ) b = 0xff;
  304.             if ( g < 0 ) g = 0; else if ( g > 0xff ) g = 0xff;
  305.             if ( r < 0 ) r = 0; else if ( r > 0xff ) r = 0xff;
  306.  
  307.             *dest++ = (byte) b;
  308.             *dest++ = (byte) g;
  309.             *dest++ = (byte) r;
  310.             }
  311.         }
  312.     }
  313. /*...e*/
  314.  
  315. GBM_ERR vid_rdata(int fd, GBM *gbm, byte *data)
  316.     {
  317.     int stride = ((gbm->w * 3 + 3) & ~3);
  318.     int n_sites = gbm->w / 4;
  319.     byte *ibuffer, *sbuffer, *p;
  320.     int i;
  321.  
  322.     if ( (ibuffer = malloc((size_t) (n_sites * 6))) == NULL )
  323.         return GBM_ERR_MEM;
  324.  
  325.     if ( (sbuffer = malloc((size_t) (n_sites * 6))) == NULL )
  326.         {
  327.         free(ibuffer);
  328.         return GBM_ERR_MEM;
  329.         }
  330.  
  331.     gbm_file_lseek(fd, 16L, SEEK_SET);
  332.  
  333.     p = data + ((gbm->h - 1) * stride);
  334.     for ( i = gbm->h - 1; i >= 0; i-- )
  335.         {
  336.         if ( gbm_file_read(fd, (char *) ibuffer, n_sites * 6) != n_sites * 6 )
  337.             {
  338.             free(sbuffer);
  339.             free(ibuffer);
  340.             return GBM_ERR_READ;
  341.             }
  342.         decode_sites(ibuffer, sbuffer, n_sites);
  343.         convert_sites(sbuffer, p, n_sites);
  344.         p -= stride;
  345.         }
  346.     free(sbuffer);
  347.     free(ibuffer);
  348.     return GBM_ERR_OK;
  349.     }
  350. /*...e*/
  351. /*...svid_w:0:*/
  352. /*...sconvert_to_yuv:0:*/
  353. /*...sVersion1:0:*/
  354. /*
  355.  
  356. Y = 51 * R + 100 * G + 19 * B
  357.     -------------------------
  358.              170
  359.  
  360. U = ( B - Y ) * 127 / 227
  361.  
  362. V = ( R - Y ) * 127 / 179
  363.  
  364. */
  365. /*...e*/
  366. /*...sVersion2\44\ 80\37\ saturation \40\as recommended\41\:0:*/
  367. /*
  368.  
  369. Y = 51 * R + 100 * G + 19 * B
  370.     -------------------------
  371.              170
  372.  
  373. U = (1 / 0.8) * ( B - Y ) * 127 / 227
  374.  
  375. V = (1 / 0.8) * ( R - Y ) * 127 / 179
  376.  
  377. */
  378. /*...e*/
  379.  
  380. static void convert_to_yuv(const byte *src, byte *dest, int n_sites)
  381.     {
  382.     while ( n_sites-- )
  383.         {
  384.         short u = 0, v = 0;
  385.         int i;
  386.  
  387.         for ( i = 0; i < 4; i++ )
  388.             {
  389.             byte b = *src++;
  390.             byte g = *src++;
  391.             byte r = *src++;
  392.             short y = ( 51 * r + 100 * g + 19 * b ) / 170;
  393.  
  394.             u += ( (b - y) * (127 * 5) / (227 * 4) );
  395.             v += ( (r - y) * (127 * 5) / (179 * 4) );
  396.  
  397.             if ( y < 0 ) y = 0; else if ( y > 0xff ) y = 0xff;
  398.  
  399.             *dest++ = (byte) (y & 0xfe);
  400.             }
  401.  
  402.         u >>= 2; v >>= 2;
  403.  
  404.         if ( u < -0x80 ) u = -0x80; else if ( u > 0x7f ) u = 0x7f;
  405.         if ( v < -0x80 ) v = -0x80; else if ( v > 0x7f ) v = 0x7f;
  406.  
  407.         *dest++ = (byte) (u & 0xfe);
  408.         *dest++ = (byte) (v & 0xfe);
  409.         }
  410.     }
  411. /*...e*/
  412. /*...sencode_sites:0:*/
  413. /*
  414.  
  415. Supplied:
  416.  
  417. Which pixel:    00000000 11111111 22222222 33333333
  418. What comp:    yyyyyyy_ yyyyyyy_ yyyyyyy_ yyyyyyy_ uuuuuuu_ vvvvvvv_
  419.  
  420. Desired bytewise:
  421.  
  422. Which pixel:    0000         0000     2222 11111111 33333333 2222    
  423. What comp:    yyyguuvv uuvvyyyy uuvvyyyy yyyyyyyg yyyyyyyg yyygu_v_
  424. Bit posn:    321 5454 76767654 32327654 7654321  7654321  321 1 1 
  425.  
  426. */
  427.  
  428. static void encode_sites(const byte *src, byte *dest, int n_sites)
  429.     {
  430.     for ( ; n_sites--; src += 6 )
  431.         {
  432.         *dest++ = (byte) ( ((byte) (src[0] & 0x0e)<<4) |
  433.                    ((byte) (src[4] & 0x30)>>2) |
  434.                    ((byte) (src[5] & 0x30)>>4) );
  435.         *dest++ = (byte) (  (byte) (src[4] & 0xc0)     |
  436.                    ((byte) (src[5] & 0xc0)>>2) |
  437.                    ((byte) (src[0] & 0xf0)>>4) );
  438.         *dest++ = (byte) ( ((byte) (src[4] & 0x0c)<<4) |
  439.                    ((byte) (src[5] & 0x0c)<<2) |
  440.                    ((byte) (src[2] & 0xf0)>>4) );
  441.         *dest++ = (byte)    (byte) (src[1] & 0xfe)      ;
  442.         *dest++ = (byte)    (byte) (src[3] & 0xfe)      ;
  443.         *dest++ = (byte) ( ((byte) (src[2] & 0x0e)<<4) |
  444.                    ((byte) (src[4] & 0x02)<<2) |
  445.                     (byte) (src[5] & 0x02)     );
  446.         }
  447.     }
  448. /*...e*/
  449.  
  450. GBM_ERR vid_w(const char *fn, int fd, const GBM *gbm, const GBMRGB *gbmrgb, const byte *data, const char *opt)
  451.     {
  452.     byte buf[16];
  453.     int xpos = 0, ypos = 0;
  454.     int stride = ((gbm->w * 3 + 3) & ~3);
  455.     int n_sites = gbm->w / 4;
  456.     byte *obuffer, *sbuffer;
  457.     const byte *p;
  458.     int i;
  459.     const char *s;
  460.  
  461.     fn=fn; gbmrgb=gbmrgb; /* Suppress 'unref arg' compiler warnings */
  462.  
  463.     if ( (s = gbm_find_word_prefix(opt, "xpos=")) != NULL )
  464.         sscanf(s + 5, "%d", &xpos);
  465.  
  466.     if ( (s = gbm_find_word_prefix(opt, "ypos=")) != NULL )
  467.         sscanf(s + 5, "%d", &ypos);
  468.  
  469.     memcpy(buf, "YUV12C", 6);
  470.     buf[ 6] = 0;
  471.     buf[ 7] = 0;
  472.     buf[ 8] = low_byte(xpos);
  473.     buf[ 9] = high_byte(xpos);
  474.     buf[10] = low_byte(ypos);
  475.     buf[11] = high_byte(ypos);
  476.     buf[12] = low_byte(gbm->w & ~3);
  477.     buf[13] = high_byte(gbm->w & ~3);
  478.     buf[14] = low_byte(gbm->h);
  479.     buf[15] = high_byte(gbm->h);
  480.  
  481.     if ( gbm_file_write(fd, buf, 16) != 16 )
  482.         return GBM_ERR_WRITE;
  483.  
  484.     if ( (obuffer = malloc((size_t) (n_sites * 6))) == NULL )
  485.         return GBM_ERR_MEM;
  486.  
  487.     if ( (sbuffer = malloc((size_t) (n_sites * 6))) == NULL )
  488.         {
  489.         free(obuffer);
  490.         return GBM_ERR_MEM;
  491.         }
  492.  
  493.     p = data + ((gbm->h - 1) * stride);
  494.     for ( i = gbm->h - 1; i >= 0; i-- )
  495.         {
  496.         convert_to_yuv(p, sbuffer, n_sites);
  497.         encode_sites(sbuffer, obuffer, n_sites);
  498.         if ( gbm_file_write(fd, (char *) obuffer, n_sites * 6) != n_sites * 6 )
  499.             {
  500.             free(sbuffer);
  501.             free(obuffer);
  502.             return GBM_ERR_WRITE;
  503.             }
  504.         p -= stride;
  505.         }
  506.     free(sbuffer);
  507.     free(obuffer);
  508.  
  509.     return GBM_ERR_OK;
  510.     }
  511. /*...e*/
  512. /*...svid_err:0:*/
  513. const char *vid_err(GBM_ERR rc)
  514.     {
  515.     switch ( (int) rc )
  516.         {
  517.         case GBM_ERR_VID_BAD_W:
  518.             return "width not a multiple of 4 pixels";
  519.         }
  520.     return NULL;
  521.     }
  522. /*...e*/
  523.