home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************/
- /* */
- /* Copyright (C) 1987-1996 Microsoft Corp. */
- /* All Rights Reserved */
- /* */
- /****************************************************************************/
- /****************************** Module Header *******************************
- * Module Name: image.c
- *
- * Routines for opening and saving images.
- *
- * History:
- *
- ****************************************************************************/
-
- #include "imagedit.h"
-
- #include <stdio.h>
- #include <string.h>
-
-
-
- /************************************************************************
- * ImageNew
- *
- * Creates a new image for the specified device.
- *
- * Arguments:
- *
- * History:
- *
- ************************************************************************/
-
- BOOL ImageNew(
- PDEVICE pDevice)
- {
- PIMAGEINFO pImage;
-
- if (!(pImage = ImageLinkAlloc(pDevice, pDevice->cx, pDevice->cy,
- 0, 0, pDevice->nColors)))
- return FALSE;
-
- /*
- * Allocate work space for the new image.
- */
- if (!ImageDCCreate(pDevice->iType, pImage->cx, pImage->cy,
- pImage->nColors)) {
- ImageLinkFree(pImage);
- return FALSE;
- }
-
- gpImageCur = pImage;
- gnImages++;
- giType = pDevice->iType;
-
- /*
- * Initialize the pick rectangle to encompass the entire image.
- */
- PickSetRect(0, 0, gcxImage - 1, gcyImage - 1);
-
- /*
- * Mark the newly created image as dirty to be sure it gets saved.
- */
- fImageDirty = TRUE;
-
- /*
- * Update the palettes.
- */
- SetColorPalette(gnColors, giType, FALSE);
- PropBarUpdate();
- ToolboxUpdate();
- ViewReset();
-
- /*
- * Reset the workspace window and then show it.
- */
- WorkReset();
- ShowWindow(ghwndWork, SW_SHOWNORMAL);
-
- return TRUE;
- }
-
-
-
- /************************************************************************
- * ImageNewBitmap
- *
- * Creates a new bitmap image given a set of characteristics. After
- * device link is created for those characteristics, ImageNew() is
- * called to do the actual work.
- *
- * Arguments:
- *
- * History:
- *
- ************************************************************************/
-
- BOOL ImageNewBitmap(
- INT cx,
- INT cy,
- INT nColors)
- {
- PDEVICE pDevice;
-
- if (!(pDevice = DeviceLinkAlloc(FT_BITMAP, NULL, nColors, cx, cy)))
- return FALSE;
-
- return ImageNew(pDevice);
- }
-
-
-
- /************************************************************************
- * ImageOpen
- *
- * Determines what has to be done to open the specified image. If it
- * is not already the current image, it will save the current image
- * then will call ImageOpen2() to open the new one.
- *
- * Arguments:
- *
- * History:
- *
- ************************************************************************/
-
- BOOL ImageOpen(
- PIMAGEINFO pImage)
- {
- /*
- * New image is already current. Return success.
- */
- if (pImage == gpImageCur)
- return TRUE;
-
- /*
- * Is this an image for a known device?
- */
- if (pImage->pDevice) {
- /*
- * Save away the current image.
- */
- ImageSave();
-
- /*
- * Do the real open of the new image.
- */
- return ImageOpen2(pImage);
- }
- else {
- Message(MSG_CANTEDITIMAGE);
- return FALSE;
- }
- }
-
-
-
- /************************************************************************
- * ImageOpen2
- *
- * Unconditionally opens up the specified image for editing. This involves
- * parsing the DIB into various globals, putting the bits onto the screen
- * and updating the different palettes appropriately.
- *
- * Arguments:
- *
- * History:
- *
- ************************************************************************/
-
- BOOL ImageOpen2(
- PIMAGEINFO pImage)
- {
- HCURSOR hcurOld;
- LPBITMAPINFO lpbi;
- INT iBitCount;
- INT cx;
- INT cy;
- INT nColors;
- DWORD cbColorTable;
- DWORD cbBits;
- LPBYTE lpDIBBits;
- HBITMAP hbmMono;
- HBITMAP hbmImage;
- PBITMAPINFO pbi;
-
- hcurOld = SetCursor(hcurWait);
-
- lpbi = (LPBITMAPINFO)pImage->DIBPtr;
- iBitCount = lpbi->bmiHeader.biBitCount;
-
- cx = (INT)lpbi->bmiHeader.biWidth;
- cy = (INT)lpbi->bmiHeader.biHeight;
- if (giType != FT_BITMAP)
- cy /= 2;
-
- nColors = pImage->nColors;
-
- /*
- * Allocate work space for the image.
- */
- if (!ImageDCCreate(giType, cx, cy, nColors))
- goto Error1;
-
- /*
- * Create a temporary bitmap.
- */
- if (!(hbmMono = CreateBitmap(1, 1, 1, 1, NULL))) {
- Message(MSG_OUTOFMEMORY);
- goto Error2;
- }
-
- cbColorTable = (1 << iBitCount) * sizeof(RGBQUAD);
- lpDIBBits = (LPSTR)lpbi + sizeof(BITMAPINFOHEADER) + cbColorTable;
- cbBits = (((((DWORD)cx * iBitCount) + 31) & 0xffffffe0) >> 3) * cy;
-
- /*
- * Make a copy of the info header and color table.
- */
- if (!(pbi = (PBITMAPINFO)MyAlloc(
- sizeof(BITMAPINFOHEADER) + (INT)cbColorTable)))
- goto Error3;
-
- memcpy((LPBYTE)pbi, lpbi, sizeof(BITMAPINFOHEADER) + (INT)cbColorTable);
-
- /* * Adjust some fields. The size field in an icon/cursor dib
- * includes the AND mask bits, which we don't want to include
- * right now.
- */
- pbi->bmiHeader.biHeight = cy;
- pbi->bmiHeader.biSizeImage = cbBits;
-
- /*
- * Set the bits into the XOR mask.
- */
- hbmImage = SelectObject(ghdcImage, hbmMono);
- SetDIBits(ghdcImage, hbmImage, 0, cy, lpDIBBits, pbi, DIB_RGB_COLORS);
- SelectObject(ghdcImage, hbmImage);
-
- /*
- * If we are editing an icon or cursor, we need to set the bits
- * for the AND mask also now.
- */
- if (giType != FT_BITMAP) {
- /*
- * Skip past the XOR mask bits to the AND bits that follow.
- */
- lpDIBBits += cbBits;
-
- cbColorTable = 2 * sizeof(RGBQUAD);
-
- /*
- * Adjust some fields in the copy of the bitmap info structure,
- * then copy a monochrome color table into it. Note that we
- * are using the same allocated copy, which is ok because there
- * will always be enough room allocated for the monochrome
- * color table.
- */
- pbi->bmiHeader.biBitCount = 1;
- pbi->bmiHeader.biSizeImage =
- cy * ((((DWORD)cx + 31) & 0xffffffe0) >> 3);
- pbi->bmiHeader.biClrImportant = 0;
- pbi->bmiHeader.biClrUsed = 0;
- memcpy((PBYTE)pbi->bmiColors, (PBYTE)gargbColorTable2,
- (INT)cbColorTable);
-
- /*
- * Set the bits into the AND mask.
- */
- hbmImage = SelectObject(ghdcANDMask, hbmMono);
- SetDIBits(ghdcANDMask, hbmImage, 0, cy, lpDIBBits, pbi,
- DIB_RGB_COLORS);
- SelectObject(ghdcANDMask, hbmImage);
-
- /*
- * Combine the XOR and AND masks into a viewable image.
- */
- ImageDCCombine(ghdcImage, gcxImage, gcyImage, ghdcANDMask);
- }
-
- MyFree(pbi);
- DeleteObject(hbmMono);
-
- /*
- * Set the current image pointer.
- */
- gpImageCur = pImage;
- fImageDirty = FALSE;
- /*
- * Initialize the pick rectangle to encompass the entire image.
- */
- PickSetRect(0, 0, gcxImage - 1, gcyImage - 1);
-
- SetColorPalette(gnColors, giType, FALSE);
-
- /*
- * Update the properties bar info and toolbox.
- */
- PropBarUpdate();
- ToolboxUpdate();
-
- ViewReset();
-
- /*
- * Reset the workspace window and then show it.
- */
- WorkReset();
- ShowWindow(ghwndWork, SW_SHOWNORMAL);
-
- SetCursor(hcurOld);
-
- return TRUE;
-
- Error3:
- DeleteObject(hbmMono);
-
- Error2:
- ImageDCDelete();
-
- Error1:
- SetCursor(hcurOld);
-
- return FALSE;
- }
-
-
-
- /************************************************************************
- * ImageSave
- *
- * Saves the state of the current image into the image list (if it
- * is dirty).
- *
- * History:
- *
- ************************************************************************/
-
- VOID ImageSave(VOID)
- {
- HCURSOR hcurOld;
- INT iBitCount;
- DWORD cbColorTable;
- DWORD cbXORBits;
- DWORD cbANDBits;
- HANDLE hDIB;
- DWORD dwDIBSize;
- LPBITMAPINFOHEADER lpbih;
- LPBYTE lpBits;
- HBITMAP hbmMono;
- HBITMAP hbmImage;
-
- if (!fImageDirty)
- return;
-
- hcurOld = SetCursor(hcurWait);
-
- /*
- * Separate out the XOR and AND masks for ico/cur images.
- */
- if (giType != FT_BITMAP)
- ImageDCSeparate(ghdcImage, gcxImage, gcyImage, ghdcANDMask, grgbScreen);
-
- /*
- * Create a temporary bitmap.
- */
- if (!(hbmMono = CreateBitmap(1, 1, 1, 1, NULL))) {
- Message(MSG_OUTOFMEMORY);
- goto Error1;
- }
-
- switch (gpImageCur->nColors) {
- case 2:
- iBitCount = 1;
- break;
-
- case 16:
- iBitCount = 4;
- break;
- }
-
- cbColorTable = (DWORD)gpImageCur->nColors * sizeof(RGBQUAD);
- cbXORBits = (((((DWORD)gpImageCur->cx * iBitCount) + 31)
- & 0xffffffe0) >> 3) * gpImageCur->cy;
-
- switch (giType) {
- case FT_BITMAP:
- cbANDBits = 0;
- break;
-
- case FT_ICON:
- case FT_CURSOR:
- cbANDBits = (DWORD)gpImageCur->cy *
- ((((DWORD)gpImageCur->cx + 31) & 0xffffffe0) >> 3);
- break;
- }
-
- dwDIBSize = sizeof(BITMAPINFOHEADER) + cbColorTable + cbXORBits +
- cbANDBits;
-
- /*
- * Allocate space for the DIB for this image.
- */
- if (!(hDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwDIBSize))) {
- Message(MSG_OUTOFMEMORY);
- goto Error2;
- }
-
- lpbih = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
-
- /*
- * For icons and cursors, we need to get the AND mask bits first.
- */
- if (giType != FT_BITMAP) {
- /*
- * Point to where the AND bits should go.
- */
- lpBits = (LPBYTE)lpbih + sizeof(BITMAPINFOHEADER) +
- cbColorTable + cbXORBits;
-
- /*
- * Fill in the bitmap info header for getting the AND bits.
- */
- lpbih->biSize = sizeof(BITMAPINFOHEADER);
- lpbih->biWidth = gpImageCur->cx;
- lpbih->biHeight = gpImageCur->cy;
- lpbih->biPlanes = 1;
- lpbih->biBitCount = 1;
- lpbih->biCompression = BI_RGB;
- lpbih->biSizeImage = cbANDBits;
- lpbih->biXPelsPerMeter = 0;
- lpbih->biYPelsPerMeter = 0;
- lpbih->biClrImportant = 0;
- lpbih->biClrUsed = 0;
-
- /*
- * Get the bits from the AND mask.
- */
- hbmImage = SelectObject(ghdcANDMask, hbmMono);
- GetDIBits(ghdcANDMask, hbmImage, 0, gpImageCur->cy, lpBits,
- (LPBITMAPINFO)lpbih, DIB_RGB_COLORS);
- SelectObject(ghdcANDMask, hbmImage);
- }
-
- /*
- * Fill in the bitmap info header for getting the XOR bits.
- */
- lpbih->biSize = sizeof(BITMAPINFOHEADER);
- lpbih->biWidth = gpImageCur->cx;
- lpbih->biHeight = gpImageCur->cy;
- lpbih->biPlanes = 1;
- lpbih->biBitCount = iBitCount;
- lpbih->biCompression = BI_RGB;
- lpbih->biSizeImage = cbXORBits;
- lpbih->biXPelsPerMeter = 0;
- lpbih->biYPelsPerMeter = 0;
- lpbih->biClrImportant = 0;
- lpbih->biClrUsed = 0;
-
- /*
- * Point to where the XOR bits should go.
- */
- lpBits = (LPBYTE)lpbih + sizeof(BITMAPINFOHEADER) + cbColorTable;
-
- /*
- * Get the bits from the XOR mask.
- */
- hbmImage = SelectObject(ghdcImage, hbmMono);
- GetDIBits(ghdcImage, hbmImage, 0, gpImageCur->cy, lpBits,
- (LPBITMAPINFO)lpbih, DIB_RGB_COLORS);
- SelectObject(ghdcImage, hbmImage);
-
- /*
- * For icons and cursors, we have a few extra steps.
- */
- if (giType != FT_BITMAP) {
- /*
- * Set the fields in the info structure to their final
- * values. The saved value in the bitmap info header for the
- * height in an icon/cursor DIB is really twice the height of
- * the image, and the size of the image is the size of both
- * the XOR and the AND mask bits.
- */
- lpbih->biHeight *= 2;
- lpbih->biSizeImage = cbXORBits + cbANDBits;
-
- /*
- * Recombine the XOR and AND masks now that we have their bits.
- */
- ImageDCCombine(ghdcImage, gcxImage, gcyImage, ghdcANDMask);
- }
-
- /*
- * Free any old DIB.
- */
- if (gpImageCur->DIBhandle) {
- GlobalUnlock(gpImageCur->DIBhandle);
- GlobalFree(gpImageCur->DIBhandle);
- }
-
- /*
- * Set the image structure to point to the newly created DIB.
- */
- gpImageCur->DIBSize = dwDIBSize;
- gpImageCur->DIBhandle = hDIB;
- gpImageCur->DIBPtr = (LPBYTE)lpbih;
-
- fFileDirty = TRUE;
- fImageDirty = FALSE;
-
- Error2:
- DeleteObject(hbmMono);
-
- Error1:
- SetCursor (hcurOld);
- }
-