home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 18.ddi / SAMPLES / CROPDIB / CROPDIB.C_ / CROPDIB.C
Encoding:
C/C++ Source or Header  |  1993-02-08  |  17.4 KB  |  581 lines

  1. /* Microsoft Multimedia Systems Sample Code Library
  2.  *
  3.  * CropDIB.c is a Windows with Multimedia application that crops a
  4.  * series of DIBs. It uses the DIB driver; although this is the only 
  5.  * multimedia component that it demonstrates, the DIB.C module contains
  6.  * many useful functions for working with DIBs and palettes.
  7.  *
  8.  * This application crops and "brighten" (add a specified increment to
  9.  * the palette entries) a series of DIBs. 
  10.  *
  11.  * If an input "pattern" is specified, it opens a series of input files; 
  12.  * otherwise, it opens only the specified filename. From each input file,
  13.  * it can read one or a series of DIBs.
  14.  *
  15.  * If an output "pattern" is specified, it writes the DIBs to a series 
  16.  * of output files; otherwise, it writes all the DIBs to the single
  17.  * specified filename.
  18.  *
  19.  * Demonstrates:
  20.  *         Use of DIB Driver
  21.  *         Direct manipulation of DIB pixel data
  22.  *         Direct manipulation of DIB palette data
  23.  *         Cacheing of Driver to avoid re-load
  24.  *
  25.  * (C) Copyright Microsoft Corp. 1991.  All rights reserved.
  26.  *
  27.  * You have a royalty-free right to use, modify, reproduce and 
  28.  * distribute the Sample Files (and/or any modified version) in 
  29.  * any way you find useful, provided that you agree that 
  30.  * Microsoft has no warranty obligations or liability for any 
  31.  * Sample Application Files which are modified.
  32.  *
  33.  */
  34.  
  35. #include <windows.h>
  36. #include <stdlib.h>
  37. #include "cropdib.h"
  38. #include "dib.h"
  39.  
  40.  
  41. /* Globals */
  42. char    gszAppName[] = "CropDIB";       // For title bar etc.
  43. HANDLE  ghInst;                         // Program instance handle
  44.  
  45.  
  46. /* Wait cursor */
  47. static HCURSOR  ghcurSave;              // Previous cursor
  48. int      giCurSave = 0;                 // Use count variable for StartWait()
  49. #define StartWait()     ((giCurSave++ == 0)     \
  50.     ? (ghcurSave = SetCursor(LoadCursor(NULL, IDC_WAIT))) : 0)
  51. #define EndWait()       ((--giCurSave == 0)     \
  52.     ? SetCursor(ghcurSave) : 0)
  53.  
  54.  
  55. /* prototypes */
  56. int  ErrMsg (HWND hwnd, int idsfmt, ...);
  57. BOOL NEAR PASCAL DoCrop(HWND hwnd);
  58. GLOBALHANDLE NEAR PASCAL CropDIB(GLOBALHANDLE hdibOld,
  59.     int xCrop, int yCrop, int wCrop, int hCrop);
  60. void NEAR PASCAL BrightenDIB(GLOBALHANDLE hdib, int iBrightenBy);
  61. BOOL NEAR PASCAL IsPattern(LPSTR sz);
  62. int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszCmdLine, int iCmdShow);
  63. BOOL FAR PASCAL __export AboutDlgProc(HWND hwnd, unsigned wMsg,WORD wParam, LONG lParam);
  64. BOOL FAR PASCAL __export CropDIBDlgProc(HWND hwnd, unsigned wMsg,WORD wParam, LONG lParam);
  65.  
  66.  
  67. /* DoCrop(hwnd)
  68.  *
  69.  * Perform cropping operation, using information in controls in
  70.  * dialog box <hwnd>.
  71.  */
  72. BOOL NEAR PASCAL DoCrop(
  73.     HWND hwnd)                      // Dialog-box window handle
  74. {
  75.     BOOL  fOK = FALSE;
  76.     char  achInFilePat[_MAX_PATH];  // Input file or pattern
  77.     char  achOutFilePat[_MAX_PATH]; // Output file or pattern
  78.     char  achInFile[_MAX_PATH];     // Actual input file name
  79.     char  achOutFile[_MAX_PATH];    // Actual output file name
  80.     HFILE   fhIn = HFILE_ERROR;                // Input file handle (or -1)
  81.     HFILE   fhOut = HFILE_ERROR;               // Output file handle (or -1)
  82.  
  83.     int   xCrop, yCrop;             // Crop rectangle location
  84.     int   wCrop, hCrop;             // Crop rectangle size
  85.     int   iBrightenBy;              // Brighten by how much?
  86.  
  87.     int   iInFrameNo;               // Input frame number
  88.     int   iOutFrameNo;              // Output frame number
  89.     GLOBALHANDLE hdib = NULL;       // Memory DIB (or NULL)
  90.     BOOL  fFirstDIBRead;            // Make file has at least 1 DIB
  91.  
  92.     LPSTR szCopyCrop;               // "Copying" or "Cropping"
  93.     char  ach[_MAX_PATH + 50];      // Status message buffer
  94.  
  95.     /* Read parameters from dialog box fields.
  96.      */
  97.     achInFilePat[0] == 0;
  98.     GetDlgItemText(hwnd, ID_INPUTFILEEDIT, 
  99.         achInFilePat, sizeof(achInFilePat));
  100.  
  101.     achOutFilePat[0] == 0;
  102.     GetDlgItemText(hwnd, ID_OUTPUTFILEEDIT,
  103.         achOutFilePat, sizeof(achInFilePat));
  104.  
  105.     xCrop = GetDlgItemInt(hwnd, ID_XEDIT, NULL, TRUE);
  106.     yCrop = GetDlgItemInt(hwnd, ID_YEDIT, NULL, TRUE);
  107.     wCrop = GetDlgItemInt(hwnd, ID_WEDIT, NULL, TRUE);
  108.     hCrop = GetDlgItemInt(hwnd, ID_HEDIT, NULL, TRUE);
  109.  
  110.     iBrightenBy = GetDlgItemInt(hwnd, ID_BRIGHTEDIT, NULL, TRUE);
  111.  
  112.     szCopyCrop = ((wCrop == 0) && (hCrop == 0)) ? "Copying" : "Cropping";
  113.  
  114.     /* Open input and output files (if no pattern specified).
  115.      */
  116.     if(!IsPattern(achInFilePat))
  117.     {
  118.         fhIn = _lopen((LPSTR)achInFilePat, OF_READ);
  119.         if(fhIn < 0)
  120.         {
  121.             Error1(hwnd, IDS_CANTOPENFILE, (LPSTR)achInFilePat);
  122.             goto DoCrop_EXIT;
  123.         }
  124.         lstrcpy(achInFile, achInFilePat);
  125.     }
  126.  
  127.     if(!IsPattern(achOutFilePat))
  128.     {
  129.         fhOut = _lcreat((LPSTR)achOutFilePat, NULL);
  130.         if(fhOut < 0)
  131.         {
  132.             Error1(hwnd, IDS_CANTOPENFILE, (LPSTR)achOutFilePat);
  133.             goto DoCrop_EXIT;
  134.         }
  135.         lstrcpy(achOutFile, achOutFilePat);
  136.     }
  137.  
  138.     /* For each input file, process all the DIBs in the input file
  139.      */
  140.     iInFrameNo = iOutFrameNo = 0;
  141.     while(TRUE)
  142.     {
  143.         if(IsPattern(achInFilePat))
  144.         {
  145.             wsprintf(achInFile, achInFilePat, iInFrameNo++);
  146.             fhIn = _lopen((LPSTR)achInFile, READ);
  147.             if(fhIn < 0)
  148.             {
  149.                 if(iInFrameNo == 1)
  150.                 {
  151.                     iOutFrameNo++;  // If first open fails, continue; pattern
  152.                     continue;       // may be 1-relative.
  153.                 }                
  154.                 else
  155.                 {
  156.                     break;
  157.                 }
  158.             }
  159.         }
  160.  
  161.         /* For each DIB in input file <fhIn>, write the DIBs into one or
  162.          * more output files.
  163.          */
  164.         fFirstDIBRead = TRUE;
  165.         while(TRUE)
  166.         {
  167.             /* Open a DIB.
  168.              */
  169.             wsprintf(ach, "%s from %s", (LPSTR)szCopyCrop,
  170.                 (LPSTR)achInFile);
  171.             SetDlgItemText(hwnd, ID_STATUSTEXT, ach);
  172.             
  173.             if((hdib = OpenDIB(fhIn)) == NULL)
  174.             {
  175.                 if(fFirstDIBRead)
  176.                 {
  177.                     Error1(hwnd, IDS_ERRORREADING, (LPSTR)achInFile);
  178.                     goto DoCrop_EXIT;
  179.                 }
  180.                 else
  181.                     break;
  182.             }
  183.             fFirstDIBRead = FALSE;
  184.  
  185.             /* Brighten the DIB.
  186.              */
  187.             if(iBrightenBy != 0)
  188.                 BrightenDIB(hdib, iBrightenBy);
  189.  
  190.             /* Crop the DIB.
  191.              */
  192.             if((wCrop != 0) || (hCrop != 0))
  193.             {
  194.                 GLOBALHANDLE    hdibNew;
  195.  
  196.                 /* Preserve hdib in case CropDib fails.
  197.                  */
  198.                 hdibNew = CropDIB(hdib, xCrop, yCrop, wCrop, hCrop);
  199.                 if(hdibNew == NULL)
  200.                     goto DoCrop_EXIT;
  201.                 hdib = hdibNew;
  202.             }
  203.  
  204.             /* If there's an output file pattern, open the
  205.              * next output file; otherwise we append the DIB to the
  206.              * already open output file.
  207.              */
  208.             if(IsPattern(achOutFilePat))
  209.             {
  210.                 wsprintf(achOutFile, achOutFilePat,
  211.                     iOutFrameNo++);
  212.                 fhOut = _lcreat((LPSTR)achOutFile, NULL);
  213.                 if(fhOut < 0)
  214.                 {
  215.                     Error1(hwnd, IDS_CANTOPENFILE,
  216.                         (LPSTR)achOutFile);
  217.                     goto DoCrop_EXIT;
  218.                 }
  219.             }
  220.  
  221.             /* Write the DIB to <fhOut>.
  222.              */
  223.             wsprintf(ach, "%s from %s to %s", (LPSTR)szCopyCrop,
  224.                 (LPSTR)achInFile, (LPSTR)achOutFile);
  225.             SetDlgItemText(hwnd, ID_STATUSTEXT, ach);
  226.  
  227.             if(!WriteDIB(fhOut, hdib))
  228.             {
  229.                 Error1(hwnd, IDS_ERRORREADING, (LPSTR)achInFile);
  230.                 goto DoCrop_EXIT;
  231.             }
  232.  
  233.             GlobalFree(hdib), hdib = NULL;
  234.  
  235.             /* Close the output file (if specified from a pattern).
  236.              */
  237.             if(IsPattern(achOutFilePat))
  238.             {
  239.                 _lclose(fhOut);
  240.                 fhOut = HFILE_ERROR;
  241.             }
  242.         }
  243.  
  244.         if(IsPattern(achInFilePat))
  245.         {
  246.             _lclose(fhIn);
  247.             fhIn = HFILE_ERROR;
  248.         }
  249.         else
  250.             break;
  251.     }
  252.  
  253.     fOK = TRUE;
  254.  
  255. DoCrop_EXIT:
  256.  
  257.     if(fhIn >= 0)
  258.     {
  259.         _lclose(fhIn);
  260.         fhIn = HFILE_ERROR;
  261.     }
  262.  
  263.     if(fhOut >= 0)
  264.     {
  265.         _lclose(fhOut);
  266.         fhOut = HFILE_ERROR;
  267.     }
  268.  
  269.     if(hdib != NULL)
  270.     {
  271.         GlobalFree(hdib);
  272.         hdib = NULL;
  273.     }
  274.     return fOK;
  275. }
  276.  
  277.  
  278. /* hdibNew = CropDIB(hdibOld, xCrop, yCrop, wCrop, hCrop)
  279.  *
  280.  * Crops the specified rectangle from memory DIB <hdibOld> and returns
  281.  * a new memory DIB containing the cropped portion of the original DIB.
  282.  * If successful, it frees the original DIB (hdibOld).
  283.  *
  284.  * On failure, the function displays a message and returns NULL. <hdibOld> 
  285.  * is not freed.
  286.  */
  287. GLOBALHANDLE NEAR PASCAL CropDIB(
  288.     GLOBALHANDLE hdibOld,                   // DIB to crop
  289.     int xCrop,
  290.     int yCrop,                              // Crop origin
  291.     int wCrop,
  292.     int hCrop)                              // Crop extents
  293. {
  294.     BOOL               fOK =     FALSE;
  295.     GLOBALHANDLE       hdibNew = NULL;
  296.     LPBITMAPINFOHEADER lpbiOld = NULL;
  297.     BITMAPINFOHEADER   bihOld;
  298.     BYTE huge *        pBitsOld;
  299.  
  300.     LPBITMAPINFOHEADER lpbiNew = NULL;
  301.     HDC                hdcNew =  NULL;
  302.  
  303.     /* Create a DIB to hold the cropped portion of the <hdibOld> 
  304.      */
  305.     hdibNew = CreateDib(hdibOld, wCrop, hCrop);
  306.     if(hdibNew == NULL)
  307.     {
  308.         Error(NULL, IDS_OUTOFMEMORY);
  309.         goto CropDIB_EXIT;
  310.     }
  311.  
  312.     /* Lock both DIBs 
  313.      */
  314.     lpbiOld = (LPBITMAPINFOHEADER)GlobalLock(hdibOld);
  315.     lpbiNew = (LPBITMAPINFOHEADER)GlobalLock(hdibNew);
  316.  
  317.     pBitsOld = (LPSTR)lpbiOld + (WORD)lpbiOld->biSize + PaletteSize(lpbiOld);
  318.  
  319.     /* Get a DC onto the new DIB.
  320.      */
  321.     hdcNew = CreateDC("DIB", NULL, NULL, (LPSTR)lpbiNew);
  322.     if(hdcNew == NULL)
  323.     {
  324.         if((lpbiOld->biBitCount == 24) || (lpbiOld->biCompression != BI_RGB))
  325.         {
  326.             Error(NULL, IDS_FORMATNOTSUPPORTED);
  327.         }
  328.         else
  329.         {
  330.             Error(NULL, IDS_CANTLOADDIBDRV);
  331.         }
  332.         goto CropDIB_EXIT;
  333.     }
  334.  
  335.     /* Copy from the old DIB to the new DIB. Get the BITMAPINFOHEADER
  336.      * values and calculate the Y-origin of the crop area (the bitmap
  337.      * origin is at the lower-left corner).
  338.      */
  339.     DibInfo(hdibOld, &bihOld);              // Get BITMAPINFOHEADER
  340.  
  341.     yCrop = (int)bihOld.biHeight - (yCrop + hCrop);
  342.  
  343.     StretchDIBits(  hdcNew,                 // Destination DC
  344.                     0, 0,                   // Destination origin
  345.                     wCrop, hCrop,           // Destination width & height
  346.                     xCrop, yCrop,           // Source origin
  347.                     wCrop, hCrop,           // Source width & height
  348.                     pBitsOld,               // Bitmap bits
  349.                     (LPBITMAPINFO)lpbiOld,  // Bitmap header
  350.                     DIB_RGB_COLORS,         // Meaning of palette entries
  351.                     SRCCOPY);               // ROP
  352.     
  353.     fOK = TRUE;
  354.  
  355. CropDIB_EXIT:
  356.  
  357.     if(hdcNew != NULL)
  358.         DeleteDC(hdcNew);
  359.     if(lpbiOld != NULL)
  360.         GlobalUnlock(hdibOld);
  361.     if(lpbiNew != NULL)
  362.         GlobalUnlock(hdibNew);
  363.  
  364.     if(fOK)
  365.     {
  366.         /* Successful -- delete <hdibOld> and return <hdibNew> 
  367.          */
  368.         GlobalFree(hdibOld);
  369.         return hdibNew;
  370.     }
  371.     else
  372.         return NULL;
  373. }
  374.  
  375.  
  376. /* BrightenDIB(hdib, iBrightenBy)
  377.  *
  378.  * Brighten <hdib> by adding <iBrightenBy> to each component of its palette.
  379.  */
  380. void NEAR PASCAL BrightenDIB(
  381.     GLOBALHANDLE    hdib,                   // DIB to brighten
  382.     int      iBrightenBy )                  // How much brightness to add
  383. {
  384.     LPBITMAPINFOHEADER lpbi;
  385.     RGBQUAD FAR *prgb;
  386.     int cPalEntries;
  387.     int r, g, b;
  388.  
  389.  
  390.     /* Lock the DIB.
  391.      */
  392.     if((lpbi = (LPBITMAPINFOHEADER)GlobalLock(hdib)) == NULL)
  393.         return;
  394.  
  395.     prgb = (RGBQUAD FAR *)((LPBYTE)lpbi + lpbi->biSize);
  396.  
  397.     cPalEntries = (int)lpbi->biClrUsed;
  398.  
  399.     while(cPalEntries > 0)
  400.     {
  401.         r = (int)prgb->rgbRed   + iBrightenBy;
  402.         g = (int)prgb->rgbGreen + iBrightenBy;
  403.         b = (int)prgb->rgbBlue  + iBrightenBy;
  404.  
  405.         prgb->rgbRed =   (BYTE)max(0, min(r, 255));
  406.         prgb->rgbGreen = (BYTE)max(0, min(g, 255));
  407.         prgb->rgbBlue =  (BYTE)max(0, min(b, 255));
  408.  
  409.         prgb++;
  410.         cPalEntries--;
  411.     }
  412.     GlobalUnlock(hdib);
  413. }
  414.  
  415.  
  416. /* fPattern = IsPattern(sz)
  417.  *
  418.  * Return TRUE if <sz> is a numbered file pattern, e.g. "frm%02.dib".
  419.  */
  420. BOOL NEAR PASCAL IsPattern(
  421.     LPSTR sz)
  422. {
  423.     while(*sz != 0)
  424.     {
  425.         if(*sz++ == '%')
  426.             return TRUE;
  427.     }
  428.  
  429.     return FALSE;
  430. }
  431.  
  432.  
  433. /* WinMain(hInst, hPrev, lpszCmdLine, cmdShow)
  434.  * 
  435.  * The main procedure for the App.
  436.  */
  437. int PASCAL WinMain(
  438.     HINSTANCE  hInst,          // Instance handle of current instance
  439.     HINSTANCE  hPrev,          // Instance handle of previous instance
  440.     LPSTR   lpszCmdLine,        // Null-terminated command line
  441.     int     iCmdShow )          // How window should be initially displayed
  442. {
  443.     FARPROC  fpfn;
  444.  
  445.     /* Save instance handle for dialog boxes */
  446.     ghInst = hInst;
  447.  
  448.  
  449.     /* Display CropDIB dialog box */
  450.  
  451.     fpfn = MakeProcInstance((FARPROC)CropDIBDlgProc, ghInst);
  452.     DialogBox(ghInst, MAKEINTRESOURCE(CROPDIBBOX), NULL, (DLGPROC)fpfn);
  453.     FreeProcInstance(fpfn);
  454.  
  455.     return TRUE;
  456. }
  457.  
  458.  
  459. /* AboutDlgProc(hwnd, wMsg, wParam, lParam)
  460.  *
  461.  * This function handles messages belonging to the "About" dialog box.
  462.  * The only message that it looks for is WM_COMMAND, indicating the user
  463.  * has pressed the "OK" button.  When this happens, it takes down
  464.  * the dialog box.
  465.  */
  466. BOOL FAR PASCAL __export AboutDlgProc(
  467.     HWND     hwnd,              // Window handle of "about" dialog box
  468.     unsigned wMsg,              // Message number
  469.     WORD     wParam,            // Message-dependent parameter
  470.     LONG     lParam )           // Message-dependent parameter
  471. {
  472.     switch (wMsg)
  473.     {
  474.         case WM_INITDIALOG:
  475.             return TRUE;
  476.  
  477.         case WM_COMMAND:
  478.             if(wParam == IDOK)
  479.                 EndDialog(hwnd, TRUE);
  480.             break;
  481.     }
  482.     return FALSE;
  483. }
  484.  
  485.  
  486. /* CropDIBDlgProc(hwnd, wMsg, wParam, lParam)
  487.  *
  488.  * This function handles messages belonging to the "CropDIB" dialog box.
  489.  */
  490. BOOL FAR PASCAL __export CropDIBDlgProc(
  491.     HWND     hwnd,              // Window handle of "about" dialog box
  492.     unsigned wMsg,              // Message number
  493.     WORD     wParam,            // Message-dependent parameter
  494.     LONG     lParam )           // Message-dependent parameter
  495. {
  496.     FARPROC  fpfn;
  497.     HMENU    hmenuSystem;       // Handle to system menu
  498.     HDC      hdcCache;
  499.  
  500.     switch (wMsg)
  501.     {
  502.         case WM_INITDIALOG:
  503.  
  504.             /* append "About" menu item to system menu */
  505.             hmenuSystem = GetSystemMenu(hwnd, FALSE);
  506.             AppendMenu(hmenuSystem, MF_SEPARATOR, 0, NULL);
  507.             AppendMenu(hmenuSystem, MF_STRING, IDM_ABOUT,
  508.                 "&About CropDIB...");
  509.             return TRUE;
  510.  
  511.         case WM_SYSCOMMAND:
  512.             switch (wParam)
  513.             {
  514.                 case IDM_ABOUT:
  515.  
  516.                     /* request to display "About" dialog box */
  517.                     fpfn = MakeProcInstance((FARPROC) AboutDlgProc, ghInst);
  518.                     DialogBox(ghInst, MAKEINTRESOURCE(ABOUTBOX),
  519.                                 hwnd, (DLGPROC)fpfn);
  520.                     FreeProcInstance(fpfn);
  521.  
  522.                     break;
  523.             }
  524.             break;
  525.  
  526.         case WM_COMMAND:
  527.  
  528.             switch (wParam)
  529.             {
  530.                 case IDOK:              // "Begin"
  531.  
  532.                     StartWait();
  533.  
  534.                     /* Cache the DIB driver here so we don't need to reload
  535.                      * it every time we do a crop.
  536.                      */
  537.                     hdcCache = CreateDC("DIB", NULL, NULL, NULL);
  538.                     if(hdcCache == NULL)
  539.                     {
  540.                         Error(hwnd, IDS_CANTLOADDIBDRV);
  541.                         EndWait();
  542.                         EndDialog(hwnd, FALSE);
  543.                         break;
  544.                     }
  545.                     DoCrop(hwnd);
  546.  
  547.                     /* Clear the status text control */
  548.                     SetDlgItemText(hwnd, ID_STATUSTEXT, "");
  549.  
  550.                     /* Get rid of the cache */
  551.                     DeleteDC(hdcCache);
  552.  
  553.                     EndWait();
  554.                     break;
  555.  
  556.                 case IDCANCEL:          // "Done"
  557.  
  558.                     EndDialog(hwnd, TRUE);
  559.                     break;
  560.             }
  561.             break;
  562.     }
  563.     return FALSE;
  564. }
  565.  
  566. /* ErrMsg(hWnd, iszfmt, ...)
  567.  *
  568.  * Displays a message box with the formatted string supplied in <iszfmt>.
  569.  */
  570. int ErrMsg(HWND hwnd, int iszfmt, ...)
  571. {
  572.     char    ach[128];
  573.     char    sz[80];
  574.     
  575.     LoadString(ghInst,iszfmt,sz,sizeof(sz));
  576.  
  577.     wvsprintf (ach, sz, (LPSTR)(&iszfmt + 1));     // Format the string 
  578.     MessageBox(hwnd, ach, NULL, MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
  579.     return FALSE;
  580. }
  581.