home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / imagedit / image.c < prev    next >
Text File  |  1996-06-12  |  16KB  |  515 lines

  1.     /****************************************************************************/
  2.     /*                                                                          */
  3.     /*                 Copyright (C) 1987-1996 Microsoft Corp.                */
  4.     /*                           All Rights Reserved                            */
  5.     /*                                                                          */
  6.     /****************************************************************************/
  7.     /****************************** Module Header *******************************
  8.     * Module Name: image.c
  9.     *
  10.     * Routines for opening and saving images.
  11.     *
  12.     * History:
  13.     *
  14.     ****************************************************************************/
  15.     
  16.     #include "imagedit.h"
  17.     
  18.     #include <stdio.h>
  19.     #include <string.h>
  20.     
  21.     
  22.     
  23.     /************************************************************************
  24.     * ImageNew
  25.     *
  26.     * Creates a new image for the specified device.
  27.     *
  28.     * Arguments:
  29.     *
  30.     * History:
  31.     *
  32.     ************************************************************************/
  33.     
  34.     BOOL ImageNew(
  35.         PDEVICE pDevice)
  36.     {
  37.         PIMAGEINFO pImage;
  38.     
  39.         if (!(pImage = ImageLinkAlloc(pDevice, pDevice->cx, pDevice->cy,
  40.                 0, 0, pDevice->nColors)))
  41.             return FALSE;
  42.     
  43.         /*
  44.          * Allocate work space for the new image.
  45.          */
  46.         if (!ImageDCCreate(pDevice->iType, pImage->cx, pImage->cy,
  47.                 pImage->nColors)) {
  48.             ImageLinkFree(pImage);
  49.             return FALSE;
  50.         }
  51.     
  52.         gpImageCur = pImage;
  53.         gnImages++;
  54.         giType = pDevice->iType;
  55.     
  56.         /*
  57.          * Initialize the pick rectangle to encompass the entire image.
  58.          */
  59.         PickSetRect(0, 0, gcxImage - 1, gcyImage - 1);
  60.     
  61.         /*
  62.          * Mark the newly created image as dirty to be sure it gets saved.
  63.          */
  64.         fImageDirty = TRUE;
  65.     
  66.         /*
  67.          * Update the palettes.
  68.          */
  69.         SetColorPalette(gnColors, giType, FALSE);
  70.         PropBarUpdate();
  71.         ToolboxUpdate();
  72.         ViewReset();
  73.     
  74.         /*
  75.          * Reset the workspace window and then show it.
  76.          */
  77.         WorkReset();
  78.         ShowWindow(ghwndWork, SW_SHOWNORMAL);
  79.     
  80.         return TRUE;
  81.     }
  82.     
  83.     
  84.     
  85.     /************************************************************************
  86.     * ImageNewBitmap
  87.     *
  88.     * Creates a new bitmap image given a set of characteristics.  After
  89.     * device link is created for those characteristics, ImageNew() is
  90.     * called to do the actual work.
  91.     *
  92.     * Arguments:
  93.     *
  94.     * History:
  95.     *
  96.     ************************************************************************/
  97.     
  98.     BOOL ImageNewBitmap(
  99.         INT cx,
  100.         INT cy,
  101.         INT nColors)
  102.     {
  103.         PDEVICE pDevice;
  104.     
  105.         if (!(pDevice = DeviceLinkAlloc(FT_BITMAP, NULL, nColors, cx, cy)))
  106.             return FALSE;
  107.     
  108.         return ImageNew(pDevice);
  109.     }
  110.     
  111.     
  112.     
  113.     /************************************************************************
  114.     * ImageOpen
  115.     *
  116.     * Determines what has to be done to open the specified image.  If it
  117.     * is not already the current image, it will save the current image
  118.     * then will call ImageOpen2() to open the new one.
  119.     *
  120.     * Arguments:
  121.     *
  122.     * History:
  123.     *
  124.     ************************************************************************/
  125.     
  126.     BOOL ImageOpen(
  127.         PIMAGEINFO pImage)
  128.     {
  129.         /*
  130.          * New image is already current.  Return success.
  131.          */
  132.         if (pImage == gpImageCur)
  133.             return TRUE;
  134.     
  135.         /*
  136.          * Is this an image for a known device?
  137.          */
  138.         if (pImage->pDevice) {
  139.             /*
  140.              * Save away the current image.
  141.              */
  142.             ImageSave();
  143.     
  144.             /*
  145.              * Do the real open of the new image.
  146.              */
  147.             return ImageOpen2(pImage);
  148.         }
  149.         else {
  150.             Message(MSG_CANTEDITIMAGE);
  151.             return FALSE;
  152.         }
  153.     }
  154.     
  155.     
  156.     
  157.     /************************************************************************
  158.     * ImageOpen2
  159.     *
  160.     * Unconditionally opens up the specified image for editing.  This involves
  161.     * parsing the DIB into various globals, putting the bits onto the screen
  162.     * and updating the different palettes appropriately.
  163.     *
  164.     * Arguments:
  165.     *
  166.     * History:
  167.     *
  168.     ************************************************************************/
  169.     
  170.     BOOL ImageOpen2(
  171.         PIMAGEINFO pImage)
  172.     {
  173.         HCURSOR hcurOld;
  174.         LPBITMAPINFO lpbi;
  175.         INT iBitCount;
  176.         INT cx;
  177.         INT cy;
  178.         INT nColors;
  179.         DWORD cbColorTable;
  180.         DWORD cbBits;
  181.         LPBYTE lpDIBBits;
  182.         HBITMAP hbmMono;
  183.         HBITMAP hbmImage;
  184.         PBITMAPINFO pbi;
  185.     
  186.         hcurOld = SetCursor(hcurWait);
  187.     
  188.         lpbi = (LPBITMAPINFO)pImage->DIBPtr;
  189.         iBitCount = lpbi->bmiHeader.biBitCount;
  190.     
  191.         cx = (INT)lpbi->bmiHeader.biWidth;
  192.         cy = (INT)lpbi->bmiHeader.biHeight;
  193.         if (giType != FT_BITMAP)
  194.             cy /= 2;
  195.     
  196.         nColors = pImage->nColors;
  197.     
  198.         /*
  199.          * Allocate work space for the image.
  200.          */
  201.         if (!ImageDCCreate(giType, cx, cy, nColors))
  202.             goto Error1;
  203.     
  204.         /*
  205.          * Create a temporary bitmap.
  206.          */
  207.         if (!(hbmMono = CreateBitmap(1, 1, 1, 1, NULL))) {
  208.             Message(MSG_OUTOFMEMORY);
  209.             goto Error2;
  210.         }
  211.     
  212.         cbColorTable = (1 << iBitCount) * sizeof(RGBQUAD);
  213.         lpDIBBits = (LPSTR)lpbi + sizeof(BITMAPINFOHEADER) + cbColorTable;
  214.         cbBits = (((((DWORD)cx * iBitCount) + 31) & 0xffffffe0) >> 3) * cy;
  215.     
  216.         /*
  217.          * Make a copy of the info header and color table.
  218.          */
  219.         if (!(pbi = (PBITMAPINFO)MyAlloc(
  220.                 sizeof(BITMAPINFOHEADER) + (INT)cbColorTable)))
  221.             goto Error3;
  222.     
  223.         memcpy((LPBYTE)pbi, lpbi, sizeof(BITMAPINFOHEADER) + (INT)cbColorTable);
  224.     
  225.         /*     * Adjust some fields.  The size field in an icon/cursor dib
  226.          * includes the AND mask bits, which we don't want to include
  227.          * right now.
  228.          */
  229.         pbi->bmiHeader.biHeight = cy;
  230.         pbi->bmiHeader.biSizeImage = cbBits;
  231.     
  232.         /*
  233.          * Set the bits into the XOR mask.
  234.          */
  235.         hbmImage = SelectObject(ghdcImage, hbmMono);
  236.         SetDIBits(ghdcImage, hbmImage, 0, cy, lpDIBBits, pbi, DIB_RGB_COLORS);
  237.         SelectObject(ghdcImage, hbmImage);
  238.     
  239.         /*
  240.          * If we are editing an icon or cursor, we need to set the bits
  241.          * for the AND mask also now.
  242.          */
  243.         if (giType != FT_BITMAP) {
  244.             /*
  245.              * Skip past the XOR mask bits to the AND bits that follow.
  246.              */
  247.             lpDIBBits += cbBits;
  248.     
  249.             cbColorTable = 2 * sizeof(RGBQUAD);
  250.     
  251.             /*
  252.              * Adjust some fields in the copy of the bitmap info structure,
  253.              * then copy a monochrome color table into it.  Note that we
  254.              * are using the same allocated copy, which is ok because there
  255.              * will always be enough room allocated for the monochrome
  256.              * color table.
  257.              */
  258.             pbi->bmiHeader.biBitCount = 1;
  259.             pbi->bmiHeader.biSizeImage =
  260.                     cy * ((((DWORD)cx + 31) & 0xffffffe0) >> 3);
  261.             pbi->bmiHeader.biClrImportant = 0;
  262.             pbi->bmiHeader.biClrUsed = 0;
  263.             memcpy((PBYTE)pbi->bmiColors, (PBYTE)gargbColorTable2,
  264.                     (INT)cbColorTable);
  265.     
  266.             /*
  267.              * Set the bits into the AND mask.
  268.              */
  269.             hbmImage = SelectObject(ghdcANDMask, hbmMono);
  270.             SetDIBits(ghdcANDMask, hbmImage, 0, cy, lpDIBBits, pbi,
  271.                     DIB_RGB_COLORS);
  272.             SelectObject(ghdcANDMask, hbmImage);
  273.     
  274.             /*
  275.              * Combine the XOR and AND masks into a viewable image.
  276.              */
  277.             ImageDCCombine(ghdcImage, gcxImage, gcyImage, ghdcANDMask);
  278.         }
  279.     
  280.         MyFree(pbi);
  281.         DeleteObject(hbmMono);
  282.     
  283.         /*
  284.          * Set the current image pointer.
  285.          */
  286.         gpImageCur = pImage;
  287.         fImageDirty = FALSE;
  288.         /*
  289.          * Initialize the pick rectangle to encompass the entire image.
  290.          */
  291.         PickSetRect(0, 0, gcxImage - 1, gcyImage - 1);
  292.     
  293.         SetColorPalette(gnColors, giType, FALSE);
  294.     
  295.         /*
  296.          * Update the properties bar info and toolbox.
  297.          */
  298.         PropBarUpdate();
  299.         ToolboxUpdate();
  300.     
  301.         ViewReset();
  302.     
  303.         /*
  304.          * Reset the workspace window and then show it.
  305.          */
  306.         WorkReset();
  307.         ShowWindow(ghwndWork, SW_SHOWNORMAL);
  308.     
  309.         SetCursor(hcurOld);
  310.     
  311.         return TRUE;
  312.     
  313.     Error3:
  314.         DeleteObject(hbmMono);
  315.     
  316.     Error2:
  317.         ImageDCDelete();
  318.     
  319.     Error1:
  320.         SetCursor(hcurOld);
  321.     
  322.         return FALSE;
  323.     }
  324.     
  325.     
  326.     
  327.     /************************************************************************
  328.     * ImageSave
  329.     *
  330.     * Saves the state of the current image into the image list (if it
  331.     * is dirty).
  332.     *
  333.     * History:
  334.     *
  335.     ************************************************************************/
  336.     
  337.     VOID ImageSave(VOID)
  338.     {
  339.         HCURSOR hcurOld;
  340.         INT iBitCount;
  341.         DWORD cbColorTable;
  342.         DWORD cbXORBits;
  343.         DWORD cbANDBits;
  344.         HANDLE hDIB;
  345.         DWORD dwDIBSize;
  346.         LPBITMAPINFOHEADER lpbih;
  347.         LPBYTE lpBits;
  348.         HBITMAP hbmMono;
  349.         HBITMAP hbmImage;
  350.     
  351.         if (!fImageDirty)
  352.             return;
  353.     
  354.         hcurOld = SetCursor(hcurWait);
  355.     
  356.         /*
  357.          * Separate out the XOR and AND masks for ico/cur images.
  358.          */
  359.         if (giType != FT_BITMAP)
  360.             ImageDCSeparate(ghdcImage, gcxImage, gcyImage, ghdcANDMask, grgbScreen);
  361.     
  362.         /*
  363.          * Create a temporary bitmap.
  364.          */
  365.         if (!(hbmMono = CreateBitmap(1, 1, 1, 1, NULL))) {
  366.             Message(MSG_OUTOFMEMORY);
  367.             goto Error1;
  368.         }
  369.     
  370.         switch (gpImageCur->nColors) {
  371.             case 2:
  372.                 iBitCount = 1;
  373.                 break;
  374.     
  375.             case 16:
  376.                 iBitCount = 4;
  377.                 break;
  378.         }
  379.     
  380.         cbColorTable = (DWORD)gpImageCur->nColors * sizeof(RGBQUAD);
  381.         cbXORBits = (((((DWORD)gpImageCur->cx * iBitCount) + 31)
  382.                 & 0xffffffe0) >> 3) * gpImageCur->cy;
  383.     
  384.         switch (giType) {
  385.             case FT_BITMAP:
  386.                 cbANDBits = 0;
  387.                 break;
  388.     
  389.             case FT_ICON:
  390.             case FT_CURSOR:
  391.                 cbANDBits = (DWORD)gpImageCur->cy *
  392.                         ((((DWORD)gpImageCur->cx + 31) & 0xffffffe0) >> 3);
  393.                 break;
  394.         }
  395.     
  396.         dwDIBSize = sizeof(BITMAPINFOHEADER) + cbColorTable + cbXORBits +
  397.                 cbANDBits;
  398.     
  399.         /*
  400.          * Allocate space for the DIB for this image.
  401.          */
  402.         if (!(hDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwDIBSize))) {
  403.             Message(MSG_OUTOFMEMORY);
  404.             goto Error2;
  405.         }
  406.     
  407.         lpbih = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  408.     
  409.         /*
  410.          * For icons and cursors, we need to get the AND mask bits first.
  411.          */
  412.         if (giType != FT_BITMAP) {
  413.             /*
  414.              * Point to where the AND bits should go.
  415.              */
  416.             lpBits = (LPBYTE)lpbih + sizeof(BITMAPINFOHEADER) +
  417.                     cbColorTable + cbXORBits;
  418.     
  419.             /*
  420.              * Fill in the bitmap info header for getting the AND bits.
  421.              */
  422.             lpbih->biSize          = sizeof(BITMAPINFOHEADER);
  423.             lpbih->biWidth         = gpImageCur->cx;
  424.             lpbih->biHeight        = gpImageCur->cy;
  425.             lpbih->biPlanes        = 1;
  426.             lpbih->biBitCount      = 1;
  427.             lpbih->biCompression   = BI_RGB;
  428.             lpbih->biSizeImage     = cbANDBits;
  429.             lpbih->biXPelsPerMeter = 0;
  430.             lpbih->biYPelsPerMeter = 0;
  431.             lpbih->biClrImportant  = 0;
  432.             lpbih->biClrUsed       = 0;
  433.     
  434.             /*
  435.              * Get the bits from the AND mask.
  436.              */
  437.             hbmImage = SelectObject(ghdcANDMask, hbmMono);
  438.             GetDIBits(ghdcANDMask, hbmImage, 0, gpImageCur->cy, lpBits,
  439.                     (LPBITMAPINFO)lpbih, DIB_RGB_COLORS);
  440.             SelectObject(ghdcANDMask, hbmImage);
  441.         }
  442.     
  443.         /*
  444.          * Fill in the bitmap info header for getting the XOR bits.
  445.          */
  446.         lpbih->biSize          = sizeof(BITMAPINFOHEADER);
  447.         lpbih->biWidth         = gpImageCur->cx;
  448.         lpbih->biHeight        = gpImageCur->cy;
  449.         lpbih->biPlanes        = 1;
  450.         lpbih->biBitCount      = iBitCount;
  451.         lpbih->biCompression   = BI_RGB;
  452.         lpbih->biSizeImage     = cbXORBits;
  453.         lpbih->biXPelsPerMeter = 0;
  454.         lpbih->biYPelsPerMeter = 0;
  455.         lpbih->biClrImportant  = 0;
  456.         lpbih->biClrUsed       = 0;
  457.     
  458.         /*
  459.          * Point to where the XOR bits should go.
  460.          */
  461.         lpBits = (LPBYTE)lpbih + sizeof(BITMAPINFOHEADER) + cbColorTable;
  462.     
  463.         /*
  464.          * Get the bits from the XOR mask.
  465.          */
  466.         hbmImage = SelectObject(ghdcImage, hbmMono);
  467.         GetDIBits(ghdcImage, hbmImage, 0, gpImageCur->cy, lpBits,
  468.                 (LPBITMAPINFO)lpbih, DIB_RGB_COLORS);
  469.         SelectObject(ghdcImage, hbmImage);
  470.     
  471.         /*
  472.          * For icons and cursors, we have a few extra steps.
  473.          */
  474.         if (giType != FT_BITMAP) {
  475.             /*
  476.              * Set the fields in the info structure to their final
  477.              * values.  The saved value in the bitmap info header for the
  478.              * height in an icon/cursor DIB is really twice the height of
  479.              * the image, and the size of the image is the size of both
  480.              * the XOR and the AND mask bits.
  481.              */
  482.             lpbih->biHeight *= 2;
  483.             lpbih->biSizeImage = cbXORBits + cbANDBits;
  484.     
  485.             /*
  486.              * Recombine the XOR and AND masks now that we have their bits.
  487.              */
  488.             ImageDCCombine(ghdcImage, gcxImage, gcyImage, ghdcANDMask);
  489.         }
  490.     
  491.         /*
  492.          * Free any old DIB.
  493.          */
  494.         if (gpImageCur->DIBhandle) {
  495.             GlobalUnlock(gpImageCur->DIBhandle);
  496.             GlobalFree(gpImageCur->DIBhandle);
  497.         }
  498.     
  499.         /*
  500.          * Set the image structure to point to the newly created DIB.
  501.          */
  502.         gpImageCur->DIBSize = dwDIBSize;
  503.         gpImageCur->DIBhandle = hDIB;
  504.         gpImageCur->DIBPtr = (LPBYTE)lpbih;
  505.     
  506.         fFileDirty = TRUE;
  507.         fImageDirty = FALSE;
  508.     
  509.     Error2:
  510.         DeleteObject(hbmMono);
  511.     
  512.     Error1:
  513.         SetCursor (hcurOld);
  514.     }
  515.