home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / videotlk.zip / SAMPLES / EX5 / EX5CAP.C < prev    next >
Text File  |  1999-02-25  |  18KB  |  485 lines

  1.  
  2. /*------------------------------------------------------------------*
  3.  *                                                                  *
  4.  *  Video Toolkit For OS/2 Version 1.0                              *
  5.  *  Example PM Application No. 5.                                   *
  6.  *  Date : 13/07/95.                                                *
  7.  *  Copyright Abbotsbury Software Ltd. (c), United Kingdom. 1999.   *
  8.  *                                                                  *
  9.  *  Filename : ex5cap.c                                             *
  10.  *                                                                  *
  11.  *------------------------------------------------------------------*/
  12.  
  13. #define     INCL_PM
  14. #define     INCL_DOS
  15. #define     INCL_SW
  16. #define     INCL_OS2MM
  17.  
  18. #include    <os2.h>
  19. #include    <os2me.h>
  20. #include    <stdio.h>
  21. #include    <stdlib.h>
  22. #include    <string.h>
  23. #include    <time.h>
  24. #include    <memory.h>
  25. #include    <malloc.h>
  26. #include    <vcadd.h>
  27. #include    <vcai.h>
  28. #include    "ex5.h"
  29. #include    "ex5cap.h"
  30. #include    "rgbconv.h"
  31.  
  32. extern  HAB     Hab;
  33. extern  HWND    HwndFrame, HwndClient;
  34. extern  LONG    Width, Height, X, Y;
  35. extern  BOOL    CaptureOpen, ConvertASM;
  36. extern  LONG    NumColours;
  37. extern  LONG    Colours[256];
  38.  
  39. extern  void    msg_box (UCHAR *txt, UCHAR *title, ULONG options);
  40. extern  void    err_msg (CHAR *text);
  41.  
  42. static  UCHAR   *Bmp_data;
  43. static  BITMAPINFOHEADER2   Bmp_ihdr;
  44. static  CHAR    txt[80];
  45.  
  46.  
  47.                         // function protocols.
  48. MRESULT EXPENTRY CaptureDlgProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
  49.  
  50.                         // static function protocols.
  51. static  BOOL    create_bitmap_Hdc_Hps (PHDC phdc, PHPS phps);
  52. static  void    bmp_file_proc (void);
  53. static  LONG    hextol (char *t);
  54. static  void    convert_YUV422_RGB (BYTE *src, BYTE *dest, ULONG num);
  55. static  BYTE    get_colour (HPS hps, USHORT r, USHORT g, USHORT b);
  56.  
  57.                         // functions.
  58. MRESULT EXPENTRY CaptureDlgProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  59. {
  60.     static  HWND    hwnd_menu;
  61.     static  HBITMAP hbm;
  62.     static  HPS     hpsBMP;
  63.     static  HDC     hdcBMP;
  64.     static  LONG    x, y, width, height;
  65.     static  UCHAR   *buf, *data;
  66.     BITMAPINFO2     bmpi;
  67.     PBITMAPINFO2    pbmpi = &bmpi;
  68.     PBITMAPINFOHEADER2  pbmpih = &Bmp_ihdr;
  69.     ULONG   len, i, j, size;
  70.     ERRORID err;
  71.     LONG    bx, by, ty;
  72.     HPS     hps;
  73.     RECTL   rcl;
  74.     POINTL  pts;
  75.     APIRET  rc;
  76.     SWP     swp;
  77.  
  78.         switch (msg)
  79.         {
  80.             case WM_INITDLG :
  81.                 hwnd_menu = WinLoadMenu (hwnd, NULLHANDLE, IDD_CAPTURE);
  82.                 x = y = 0;
  83.                 bx = WinQuerySysValue (HWND_DESKTOP, SV_CXDLGFRAME);
  84.                 by = WinQuerySysValue (HWND_DESKTOP, SV_CYDLGFRAME);
  85.                 ty = WinQuerySysValue (HWND_DESKTOP, SV_CYTITLEBAR);
  86.                 WinSetWindowPos (hwnd, HWND_TOP, x, y,
  87.                                  Width + (bx * 2), Height + (by * 2) + ty,
  88.                                  SWP_SIZE | SWP_MOVE);
  89.                 WinSendMsg (hwnd, MSG_CAPTURE, NULL, NULL);
  90.                 CaptureOpen = TRUE;
  91.                 break;
  92.             case WM_PAINT :
  93.                 hps = WinBeginPaint (hwnd, NULLHANDLE, &rcl);
  94.                 WinQueryWindowRect (hwnd, &rcl);
  95.                 WinFillRect (hps, &rcl, CLR_PALEGRAY);
  96.                 bx = WinQuerySysValue (HWND_DESKTOP, SV_CXDLGFRAME);
  97.                 by = WinQuerySysValue (HWND_DESKTOP, SV_CYDLGFRAME);
  98.                 pts.x = 0 + bx;
  99.                 pts.y = 0 + by;
  100.                 WinDrawBitmap (hps, hbm, NULL, &pts, CLR_NEUTRAL,
  101.                                CLR_BACKGROUND, DBM_NORMAL | DBM_IMAGEATTRS);
  102.                 WinDrawBorder (hps, &rcl, bx, by, CLR_YELLOW,
  103.                                CLR_DARKGRAY, DB_AREAATTRS | DB_DLGBORDER);
  104.                 WinEndPaint (hps);
  105.                 break;
  106.             case WM_COMMAND :
  107.                 switch (SHORT1FROMMP (mp1))
  108.                 {
  109.                     case IDM_CAPT_FILE_SAVE :
  110.                         bmp_file_proc ();
  111.                         return 0;
  112.                     default :
  113.                         break;
  114.                 }
  115.                 return 0;
  116.             case WM_CLOSE :
  117.             case WM_QUIT :
  118.             case WM_DESTROY :
  119.                 GpiDestroyPS (hpsBMP);
  120.                 DevCloseDC (hdcBMP);
  121.                 GpiDeleteBitmap (hbm);
  122.                 DosFreeMem (Bmp_data);
  123.                 DosFreeMem (buf);
  124.                 CaptureOpen = FALSE;
  125.                 break;
  126.             case MSG_CAPTURE :
  127.                 if (hbm)
  128.                 {
  129.                     GpiDestroyPS (hpsBMP);
  130.                     DevCloseDC (hdcBMP);
  131.                     GpiDeleteBitmap (hbm);
  132.                 }
  133.  
  134.                 width = (Width / 8) * 8;
  135.                 height = (Height / 8) * 8;
  136.                 WinQueryWindowPos (hwnd, &swp);
  137.                 x = swp.x;
  138.                 y = swp.y;
  139.                 bx = WinQuerySysValue (HWND_DESKTOP, SV_CXDLGFRAME);
  140.                 by = WinQuerySysValue (HWND_DESKTOP, SV_CYDLGFRAME);
  141.                 ty = WinQuerySysValue (HWND_DESKTOP, SV_CYTITLEBAR);
  142.                 WinSetWindowPos (hwnd, HWND_TOP, x, swp.y,
  143.                                  Width + (bx * 2), Height + (by * 2) + (ty * 2),
  144.                                  SWP_SIZE | SWP_MOVE);
  145.                 len = (ULONG)((width * height) * 2);
  146.                 rc = DosAllocMem ((PPVOID)&buf, len + 4L,
  147.                                   (PAG_COMMIT | PAG_WRITE));
  148.                 if (rc)
  149.                 {
  150.                     sprintf (txt, "error - DosAllocMem %d", rc);
  151.                     msg_box (txt, "Error", MB_ERROR | MB_OK);
  152.                     return;
  153.                 }
  154.  
  155.                 rc = DosAllocMem ((PPVOID)&Bmp_data, (width * height * 4) + 4L,
  156.                                   (PAG_WRITE | PAG_COMMIT));
  157.                 if (rc)
  158.                 {
  159.                     sprintf (txt, "error - DosAllocMem %d", rc);
  160.                     msg_box (txt, "Error", MB_ERROR | MB_OK);
  161.                     return;
  162.                 }
  163.  
  164.                 if (!ConvertASM)
  165.                 {
  166.                     rc = DosAllocMem ((PPVOID)&data,
  167.                                       (width * height * 4) + 4L,
  168.                                       (PAG_WRITE | PAG_COMMIT));
  169.                     if (rc)
  170.                     {
  171.                         sprintf (txt, "error - DosAllocMem %d", rc);
  172.                         msg_box (txt, "Error", MB_ERROR | MB_OK);
  173.                         return;
  174.                     }
  175.                 }
  176.  
  177.                 VcaiImageScaleGet ((USHORT)len,   (ULONG)buf,
  178.                                    (USHORT)x,     (USHORT)(y + height),
  179.                                    (USHORT)width, (USHORT)height,
  180.                                    (USHORT)X,     (USHORT)Y,
  181.                                    (USHORT)width, (USHORT)height);
  182.  
  183.                 if (ConvertASM)
  184.                 {
  185.                     YUV422_TO_IRGB24 ((USHORT *)buf, (BYTE *)Bmp_data,
  186.                                       (ULONG)width,  (ULONG)height);
  187.                 }
  188.                 else
  189.                 {
  190.                     convert_YUV422_RGB (buf, data, len);
  191.  
  192.                                 // Transfer scan lines to bottom up.
  193.                     for (i = 0, j = (width * height) - width;
  194.                          i < height;
  195.                          i++, j-=width)
  196.                     {
  197.                         memcpy (Bmp_data + j, data + (i*width), (size_t)width);
  198.                     }
  199.                 }
  200.  
  201.                 if (ConvertASM)
  202.                 {
  203.                     pbmpi = malloc (sizeof (BITMAPINFO2));
  204.                 }
  205.                 else
  206.                 {
  207.                     size = (sizeof (RGB2)) * (NumColours - 1);
  208.                     pbmpi = malloc (sizeof (BITMAPINFO2) + size);
  209.                 }
  210.                 pbmpih->cbFix = pbmpi->cbFix = sizeof (BITMAPINFOHEADER2);
  211.                 pbmpih->cx            = pbmpi->cx            = width;
  212.                 pbmpih->cy            = pbmpi->cy            = height;
  213.                 pbmpih->cPlanes       = pbmpi->cPlanes       = 1;
  214.                 if (!ConvertASM)
  215.                 {
  216.                     switch ((ULONG)NumColours)
  217.                     {
  218.                         case 2 :
  219.                             pbmpih->cBitCount = pbmpi->cBitCount = 1;
  220.                             break;
  221.                         case 16 :
  222.                             pbmpih->cBitCount = pbmpi->cBitCount = 4;
  223.                             break;
  224.                         case 256 :
  225.                             pbmpih->cBitCount = pbmpi->cBitCount = 8;
  226.                             break;
  227.                         default:
  228.                             break;
  229.                     }
  230.                 }
  231.                 else
  232.                 {
  233.                     pbmpih->cBitCount     = pbmpi->cBitCount     = 24;
  234.                 }
  235.                 pbmpih->ulCompression = pbmpi->ulCompression = BCA_UNCOMP;
  236.                 pbmpih->cbImage       = pbmpi->cbImage       = 0L;
  237.                 pbmpih->cxResolution  = pbmpi->cxResolution  = width;
  238.                 pbmpih->cyResolution  = pbmpi->cyResolution  = height;
  239.                 if (!ConvertASM)
  240.                 {
  241.                     pbmpih->cclrUsed      = pbmpi->cclrUsed      = NumColours;
  242.                     pbmpih->cclrImportant = pbmpi->cclrImportant = NumColours;
  243.                 }
  244.                 else
  245.                 {
  246.                     pbmpih->cclrUsed      = pbmpi->cclrUsed      = 0L;
  247.                     pbmpih->cclrImportant = pbmpi->cclrImportant = 0L;
  248.                 }
  249.                 pbmpih->usUnits       = pbmpi->usUnits       = BRU_METRIC;
  250.                 pbmpih->usReserved    = pbmpi->usReserved    = 0;
  251.                 pbmpih->usRecording   = pbmpi->usRecording   = BRA_BOTTOMUP;
  252.                 pbmpih->usRendering   = pbmpi->usRendering   = BRH_NOTHALFTONED;
  253.                 pbmpih->cSize1        = pbmpi->cSize1        = 0L;
  254.                 pbmpih->cSize2        = pbmpi->cSize2        = 0L;
  255.                 pbmpih->ulColorEncoding = pbmpi->ulColorEncoding = BCE_RGB;
  256.                 if (!ConvertASM)
  257.                 {
  258.                     for (i = 0; i < NumColours; i++)
  259.                     {
  260.                         pbmpi->argbColor[i].bBlue  =
  261.                                            (BYTE)(Colours[i] & 0x000000FF);
  262.                         pbmpi->argbColor[i].bGreen =
  263.                                     (BYTE)((Colours[i] & 0x0000FF00) / 0x100);
  264.                         pbmpi->argbColor[i].bRed   =
  265.                                   (BYTE)((Colours[i] & 0x00FF0000) / 0x10000);
  266.                         pbmpi->argbColor[i].fcOptions = 0;
  267.                     }
  268.                 }
  269.                 create_bitmap_Hdc_Hps (&hdcBMP, &hpsBMP);
  270.                 hbm = GpiCreateBitmap (hpsBMP, pbmpih, 0L, NULL, NULL);
  271.                 if (hbm == 0)
  272.                 {
  273.                     err_msg ("GpiCreateBitmap");
  274.                     return;
  275.                 }
  276.                 if (GpiSetBitmap (hpsBMP, hbm) == HBM_ERROR)
  277.                 {
  278.                     err_msg ("GpiSetBitmap");
  279.                     return;
  280.                 }
  281.                 if (GpiSetBitmapBits (hpsBMP, 0L, height, Bmp_data, pbmpi)
  282.                     != height)
  283.                 {
  284.                     err_msg ("GpiSetBitmapBits");
  285.                     return;
  286.                 }
  287.                 DosFreeMem (data);
  288.                 DosFreeMem (buf);
  289.                 DosFreeMem (Bmp_data);
  290.                 free (pbmpi);
  291.                 WinQueryWindowRect (hwnd, &rcl);
  292.                 WinInvalidateRect (hwnd, &rcl, TRUE);
  293.                 break;
  294.             default :
  295.                 break;
  296.         }
  297.         return WinDefDlgProc (hwnd, msg, mp1, mp2);
  298. }
  299.  
  300. static BOOL create_bitmap_Hdc_Hps (PHDC phdc, PHPS phps)
  301. {
  302.     SIZEL    sizl;
  303.     HDC      hdc;
  304.     HPS      hps;
  305.     DEVOPENSTRUC dop = {NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL,
  306.                         NULL};
  307.  
  308.         hdc = DevOpenDC (Hab, OD_MEMORY, "*", 3L, (PDEVOPENDATA) &dop,
  309.                          NULLHANDLE);
  310.         if (!hdc)
  311.             return (FALSE);
  312.  
  313.         sizl.cx = sizl.cy = 1L;
  314.         hps = GpiCreatePS (Hab, hdc, &sizl, PU_PELS | GPIA_ASSOC | GPIT_MICRO);
  315.         if (!hps)
  316.             return (FALSE);
  317.  
  318.         *phdc = hdc;
  319.         *phps = hps;
  320.         return (TRUE);
  321. }
  322.  
  323. static void bmp_file_proc ()
  324. {
  325.     HWND    hwndDlg;
  326.     CHAR    title[20];
  327.     FILE    *fd;
  328.     BYTE    *d;
  329.     LONG    width, height;
  330.     ULONG   i;
  331.     FILEDLG file_dlg;
  332.     BITMAPFILEHEADER2   bmp_fhdr;
  333.  
  334.                                     // initialise FILEDLG structure.
  335.         memset (&file_dlg, 0, sizeof (FILEDLG));
  336.         file_dlg.cbSize = sizeof (FILEDLG);
  337.         file_dlg.fl = FDS_HELPBUTTON | FDS_CENTER | FDS_SAVEAS_DIALOG;
  338.         sprintf (title, "Save bitmap");
  339.         file_dlg.pszTitle = title;
  340.         sprintf (file_dlg.szFullFile, "*.bmp");
  341.  
  342.                                     // open file dialog.
  343.         hwndDlg = WinFileDlg (HWND_DESKTOP, HwndFrame, &file_dlg);
  344.         if (hwndDlg && (file_dlg.lReturn != DID_OK))
  345.             return;
  346.  
  347.                                     // save bitmap.
  348.         fd = fopen (file_dlg.szFullFile, "wb");
  349.         if (!fd)
  350.             return;
  351.         bmp_fhdr.usType  = BFT_BMAP;
  352.         bmp_fhdr.cbSize  = sizeof (BITMAPFILEHEADER2);
  353.         bmp_fhdr.offBits = bmp_fhdr.cbSize;
  354.         bmp_fhdr.bmp2    = Bmp_ihdr;
  355.         d = (BYTE *)&bmp_fhdr;
  356.         for (i = 0; i < (sizeof (BITMAPFILEHEADER2)); i++, d++)
  357.             fputc ((INT) *d, fd);
  358.         width = (Width / 8) * 8;
  359.         height = (Height / 8) * 8;
  360.         for (i = 0; i < (width * height * 4); i++)
  361.             fputc (Bmp_data[i], fd);
  362.         fclose (fd);
  363. }
  364.  
  365. static LONG hextol (char *t)
  366. {
  367.     LONG tot;
  368.  
  369.         tot = 0L;
  370.  
  371.         while (*t)
  372.         {
  373.             if (*t >= '0' && *t <= '9')
  374.                 break;
  375.             if (*t >= 'a' && *t <= 'f')
  376.                 break;
  377.             if (*t >= 'A' && *t <= 'F')
  378.                 break;
  379.             t++;
  380.         }
  381.         while (*t)
  382.         {
  383.             if ((!(*t >= '0' && *t <= '9')) &&
  384.                 (!(*t >= 'a' && *t <= 'f')) &&
  385.                 (!(*t >= 'A' && *t <= 'F')))
  386.                 break;
  387.  
  388.             if (*t >= '0' && *t <= '9')
  389.             {
  390.                 tot *= 16L;
  391.                 tot += (*t - '0');
  392.                 t++;
  393.                 continue;
  394.             }
  395.             if (*t >= 'a' && *t <= 'f')
  396.             {
  397.                 tot *= 16L;
  398.                 tot += (*t - 'a') + 0xA;
  399.                 t++;
  400.                 continue;
  401.             }
  402.             if (*t >= '0' && *t <= '9')
  403.             {
  404.                 tot *= 16L;
  405.                 tot += (*t - 'A') + 0xA;
  406.                 t++;
  407.                 continue;
  408.             }
  409.         }
  410.         return tot;
  411. }
  412.  
  413. static void convert_YUV422_RGB (BYTE *src, BYTE *dest, ULONG len)
  414. {
  415.     /*
  416.         Convert YUV 4:2:2 image data to RGB format for use in creating
  417.         a bitmap of the image. This code only supports resolutions with
  418.         256 colours.
  419.  
  420.         Rt = (V * 179) / 127.
  421.         Bt = (U * 227) / 127.
  422.         R1 = Rt + Y1.
  423.         R2 = Rt + Y2.
  424.         B1 = Bt + Y1.
  425.         B2 = Bt + Y2.
  426.         G1 = ((170 * Y1) - (51 * R1) - (19 * B1)) / 100.
  427.         G2 = ((170 * Y2) - (51 * R2) - (19 * B2)) / 100.
  428.     */
  429.  
  430.     USHORT  R1, R2, G1, G2, B1, B2, Y1, Y2, Rt, Bt;
  431.     SHORT   U, V;
  432.     LONG    RGB1, RGB2, d;
  433.     ULONG   i, j;
  434.     HPS     hps;
  435.  
  436.         hps = WinGetPS (HwndClient);
  437.         if (!GpiCreateLogColorTable (hps, LCOL_RESET, LCOLF_CONSECRGB, 0L,
  438.                                      NumColours, Colours))
  439.             err_msg ("GpiCreateLogColorTable");
  440.         for (i = 0, j = 0; i < len; i+=4, j+=2)
  441.         {
  442.             Y1 = (USHORT)(src[i] & 0xff);
  443.             U  = (SHORT)(src[i+1] & 0xff);
  444.             Y2 = (USHORT)(src[i+2] & 0xff);
  445.             V  = (SHORT)(src[i+3] & 0xff);
  446.             U -= 128;
  447.             V -= 128;
  448.             Rt = (V * 179) / 127;
  449.             Bt = (U * 227) / 127;
  450.             R1 = Rt + Y1;
  451.             R2 = Rt + Y2;
  452.             B1 = Bt + Y1;
  453.             B2 = Bt + Y2;
  454.             G1 = ((170 * Y1) - (51 * R1) - (19 * B1)) / 100;
  455.             G2 = ((170 * Y2) - (51 * R2) - (19 * B2)) / 100;
  456.             R1 = (R1 >= 0x100) ? 0xFF :
  457.                  (R1 <= 0) ? 0 : R1;
  458.             R2 = (R2 >= 0x100) ? 0xFF :
  459.                  (R2 <= 0) ? 0 : R2;
  460.             B1 = (B1 >= 0x100) ? 0xFF :
  461.                  (B1 <= 0) ? 0 : B1;
  462.             B2 = (B2 >= 0x100) ? 0xFF :
  463.                  (B2 <= 0) ? 0 : B2;
  464.             G1 = (G1 >= 0x100) ? 0xFF :
  465.                  (G1 <= 0) ? 0 : G1;
  466.             G2 = (G2 >= 0x100) ? 0xFF :
  467.                  (G2 <= 0) ? 0 : G2;
  468.             dest[j]   = get_colour (hps, R1, G1, B1);
  469.             dest[j+1] = get_colour (hps, R2, G2, B2);
  470.         }
  471.         WinReleasePS (hps);
  472. }
  473.  
  474. static BYTE get_colour (HPS hps, USHORT r, USHORT g, USHORT b)
  475. {
  476.     ULONG   i;
  477.     LONG    d;
  478.     LONG    rgb;
  479.  
  480.         rgb = (LONG)((r * 0x10000) + (g * 0x100) + b);
  481.         rgb = GpiQueryNearestColor (hps, 0, rgb);
  482.         d = GpiQueryColorIndex (hps, 0, rgb);
  483.         return (BYTE)(d & 0xff);
  484. }
  485.