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