|
|
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.