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