tkWinImage.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:17k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tkWinImage.c --
  3.  *
  4.  * This file contains routines for manipulation full-color images.
  5.  *
  6.  * Copyright (c) 1995 Sun Microsystems, Inc.
  7.  *
  8.  * See the file "license.terms" for information on usage and redistribution
  9.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  10.  *
  11.  * RCS: @(#) $Id: tkWinImage.c,v 1.6.2.2 2003/10/29 01:08:02 hobbs Exp $
  12.  */
  13. #include "tkWinInt.h"
  14. static int DestroyImage _ANSI_ARGS_((XImage* data));
  15. static unsigned long ImageGetPixel _ANSI_ARGS_((XImage *image, int x, int y));
  16. static int PutPixel _ANSI_ARGS_((XImage *image, int x, int y,
  17.     unsigned long pixel));
  18. /*
  19.  *----------------------------------------------------------------------
  20.  *
  21.  * DestroyImage --
  22.  *
  23.  * This is a trivial wrapper around ckfree to make it possible to
  24.  * pass ckfree as a pointer.
  25.  *
  26.  * Results:
  27.  * None.
  28.  *
  29.  * Side effects:
  30.  * Deallocates the image.
  31.  *
  32.  *----------------------------------------------------------------------
  33.  */
  34. static int
  35. DestroyImage(imagePtr)
  36.      XImage *imagePtr; /* image to free */
  37. {
  38.     if (imagePtr) {
  39. if (imagePtr->data) {
  40.     ckfree((char*)imagePtr->data);
  41. }
  42. ckfree((char*)imagePtr);
  43.     }
  44.     return 0;
  45. }
  46. /*
  47.  *----------------------------------------------------------------------
  48.  *
  49.  * ImageGetPixel --
  50.  *
  51.  * Get a single pixel from an image.
  52.  *
  53.  * Results:
  54.  * Returns the 32 bit pixel value.
  55.  *
  56.  * Side effects:
  57.  * None.
  58.  *
  59.  *----------------------------------------------------------------------
  60.  */
  61. static unsigned long
  62. ImageGetPixel(image, x, y)
  63.     XImage *image;
  64.     int x, y;
  65. {
  66.     unsigned long pixel = 0;
  67.     unsigned char *srcPtr = &(image->data[(y * image->bytes_per_line)
  68.     + ((x * image->bits_per_pixel) / NBBY)]);
  69.     switch (image->bits_per_pixel) {
  70. case 32:
  71. case 24:
  72.     pixel = RGB(srcPtr[2], srcPtr[1], srcPtr[0]);
  73.     break;
  74. case 16:
  75.     pixel = RGB(((((WORD*)srcPtr)[0]) >> 7) & 0xf8,
  76.     ((((WORD*)srcPtr)[0]) >> 2) & 0xf8,
  77.     ((((WORD*)srcPtr)[0]) << 3) & 0xf8);
  78.     break;
  79. case 8:
  80.     pixel = srcPtr[0];
  81.     break;
  82. case 4:
  83.     pixel = ((x%2) ? (*srcPtr) : ((*srcPtr) >> 4)) & 0x0f;
  84.     break;
  85. case 1:
  86.     pixel = ((*srcPtr) & (0x80 >> (x%8))) ? 1 : 0;
  87.     break;
  88.     }
  89.     return pixel;
  90. }
  91. /*
  92.  *----------------------------------------------------------------------
  93.  *
  94.  * PutPixel --
  95.  *
  96.  * Set a single pixel in an image.
  97.  *
  98.  * Results:
  99.  * None.
  100.  *
  101.  * Side effects:
  102.  * None.
  103.  *
  104.  *----------------------------------------------------------------------
  105.  */
  106. static int
  107. PutPixel(image, x, y, pixel)
  108.     XImage *image;
  109.     int x, y;
  110.     unsigned long pixel;
  111. {
  112.     unsigned char *destPtr = &(image->data[(y * image->bytes_per_line)
  113.     + ((x * image->bits_per_pixel) / NBBY)]);
  114.     switch  (image->bits_per_pixel) {
  115. case 32:
  116.     /*
  117.      * Pixel is DWORD: 0x00BBGGRR
  118.      */
  119.     destPtr[3] = 0;
  120. case 24:
  121.     /*
  122.      * Pixel is triplet: 0xBBGGRR.
  123.      */
  124.     destPtr[0] = (unsigned char) GetBValue(pixel);
  125.     destPtr[1] = (unsigned char) GetGValue(pixel);
  126.     destPtr[2] = (unsigned char) GetRValue(pixel);
  127.     break;
  128. case 16:
  129.     /*
  130.      * Pixel is WORD: 5-5-5 (R-G-B)
  131.      */
  132.     (*(WORD*)destPtr) = 
  133. ((GetRValue(pixel) & 0xf8) << 7)
  134. | ((GetGValue(pixel) & 0xf8) <<2)
  135. | ((GetBValue(pixel) & 0xf8) >> 3);
  136.     break;
  137. case 8:
  138.     /*
  139.      * Pixel is 8-bit index into color table.
  140.      */
  141.     (*destPtr) = (unsigned char) pixel;
  142.     break;
  143. case 4:
  144.     /*
  145.      * Pixel is 4-bit index in MSBFirst order.
  146.      */
  147.     if (x%2) {
  148. (*destPtr) = (unsigned char) (((*destPtr) & 0xf0)
  149.     | (pixel & 0x0f));
  150.     } else {
  151. (*destPtr) = (unsigned char) (((*destPtr) & 0x0f)
  152.     | ((pixel << 4) & 0xf0));
  153.     }
  154.     break;
  155. case 1: {
  156.     /*
  157.      * Pixel is bit in MSBFirst order.
  158.      */
  159.     int mask = (0x80 >> (x%8));
  160.     if (pixel) {
  161. (*destPtr) |= mask;
  162.     } else {
  163. (*destPtr) &= ~mask;
  164.     }
  165. }
  166. break;
  167.     }
  168.     return 0;
  169. }
  170. /*
  171.  *----------------------------------------------------------------------
  172.  *
  173.  * XCreateImage --
  174.  *
  175.  * Allocates storage for a new XImage.
  176.  *
  177.  * Results:
  178.  * Returns a newly allocated XImage.
  179.  *
  180.  * Side effects:
  181.  * None.
  182.  *
  183.  *----------------------------------------------------------------------
  184.  */
  185. XImage *
  186. XCreateImage(display, visual, depth, format, offset, data, width, height,
  187. bitmap_pad, bytes_per_line)
  188.     Display* display;
  189.     Visual* visual;
  190.     unsigned int depth;
  191.     int format;
  192.     int offset;
  193.     char* data;
  194.     unsigned int width;
  195.     unsigned int height;
  196.     int bitmap_pad;
  197.     int bytes_per_line;
  198. {
  199.     XImage* imagePtr = (XImage *) ckalloc(sizeof(XImage));
  200.     imagePtr->width = width;
  201.     imagePtr->height = height;
  202.     imagePtr->xoffset = offset;
  203.     imagePtr->format = format;
  204.     imagePtr->data = data;
  205.     imagePtr->byte_order = LSBFirst;
  206.     imagePtr->bitmap_unit = 8;
  207.     imagePtr->bitmap_bit_order = LSBFirst;
  208.     imagePtr->bitmap_pad = bitmap_pad;
  209.     imagePtr->bits_per_pixel = depth;
  210.     imagePtr->depth = depth;
  211.     /*
  212.      * Under Windows, bitmap_pad must be on an LONG data-type boundary.
  213.      */
  214. #define LONGBITS    (sizeof(LONG) * 8)
  215.     bitmap_pad = (bitmap_pad + LONGBITS - 1) / LONGBITS * LONGBITS;
  216.     /*
  217.      * Round to the nearest bitmap_pad boundary.
  218.      */
  219.     if (bytes_per_line) {
  220. imagePtr->bytes_per_line = bytes_per_line;
  221.     } else {
  222. imagePtr->bytes_per_line = (((depth * width)
  223. + (bitmap_pad - 1)) >> 3) & ~((bitmap_pad >> 3) - 1);
  224.     }
  225.     imagePtr->red_mask = 0;
  226.     imagePtr->green_mask = 0;
  227.     imagePtr->blue_mask = 0;
  228.     imagePtr->f.put_pixel = PutPixel;
  229.     imagePtr->f.get_pixel = ImageGetPixel;
  230.     imagePtr->f.destroy_image = DestroyImage;
  231.     imagePtr->f.create_image = NULL;
  232.     imagePtr->f.sub_image = NULL;
  233.     imagePtr->f.add_pixel = NULL;
  234.     
  235.     return imagePtr;
  236. }
  237. /*
  238.  *----------------------------------------------------------------------
  239.  * XGetImageZPixmap --
  240.  *
  241.  * This function copies data from a pixmap or window into an
  242.  * XImage.  This handles the ZPixmap case only.
  243.  *
  244.  * Results:
  245.  * Returns a newly allocated image containing the data from the
  246.  * given rectangle of the given drawable.
  247.  *
  248.  * Side effects:
  249.  * None.
  250.  *
  251.  * This procedure is adapted from the XGetImage implementation in TkNT.
  252.  * That code is Copyright (c) 1994 Software Research Associates, Inc.
  253.  *
  254.  *----------------------------------------------------------------------
  255.  */
  256. static XImage *
  257. XGetImageZPixmap(display, d, x, y, width, height, plane_mask, format)
  258.     Display* display;
  259.     Drawable d;
  260.     int x;
  261.     int y;
  262.     unsigned int width;
  263.     unsigned int height;
  264.     unsigned long plane_mask;
  265.     int format;
  266. {
  267.     TkWinDrawable *twdPtr = (TkWinDrawable *)d;
  268.     XImage *ret_image;
  269.     HDC hdc, hdcMem;
  270.     HBITMAP hbmp, hbmpPrev;
  271.     BITMAPINFO *bmInfo = NULL;
  272.     HPALETTE hPal, hPalPrev1, hPalPrev2;
  273.     int size;
  274.     unsigned int n;
  275.     unsigned int depth;
  276.     unsigned char *data;
  277.     TkWinDCState state;
  278.     BOOL ret;
  279.     if (format != ZPixmap) {
  280. TkpDisplayWarning(
  281.     "XGetImageZPixmap: only ZPixmap types are implemented",
  282.     "XGetImageZPixmap Failure");
  283. return NULL;
  284.     }
  285.     hdc = TkWinGetDrawableDC(display, d, &state);
  286.     /* Need to do a Blt operation to copy into a new bitmap */
  287.     hbmp = CreateCompatibleBitmap(hdc, width, height);
  288.     hdcMem = CreateCompatibleDC(hdc);
  289.     hbmpPrev = SelectObject(hdcMem, hbmp);
  290.     hPal = state.palette;
  291.     if (hPal) {
  292.         hPalPrev1 = SelectPalette(hdcMem, hPal, FALSE);
  293.         n = RealizePalette(hdcMem);
  294.         if (n > 0) {
  295.             UpdateColors (hdcMem);
  296.         }
  297. hPalPrev2 = SelectPalette(hdc, hPal, FALSE);
  298.         n = RealizePalette(hdc);
  299.         if (n > 0) {
  300.             UpdateColors (hdc);
  301.         }
  302.     }
  303.     ret = BitBlt(hdcMem, 0, 0, width, height, hdc, x, y, SRCCOPY);
  304.     if (hPal) {
  305. SelectPalette(hdc, hPalPrev2, FALSE);
  306.     }
  307.     SelectObject(hdcMem, hbmpPrev);
  308.     TkWinReleaseDrawableDC(d, hdc, &state);
  309.     if (ret == FALSE) {
  310. goto cleanup;
  311.     }
  312.     if (twdPtr->type == TWD_WINDOW) {
  313. depth = Tk_Depth((Tk_Window) twdPtr->window.winPtr);
  314.     } else {
  315. depth = twdPtr->bitmap.depth;
  316.     }
  317.     size = sizeof(BITMAPINFO);
  318.     if (depth <= 8) {
  319. size += sizeof(unsigned short) * (1 << depth);
  320.     }
  321.     bmInfo = (BITMAPINFO *) ckalloc(size);
  322.     bmInfo->bmiHeader.biSize               = sizeof(BITMAPINFOHEADER);
  323.     bmInfo->bmiHeader.biWidth              = width;
  324.     bmInfo->bmiHeader.biHeight             = -(int) height;
  325.     bmInfo->bmiHeader.biPlanes             = 1;
  326.     bmInfo->bmiHeader.biBitCount           = depth;
  327.     bmInfo->bmiHeader.biCompression        = BI_RGB;
  328.     bmInfo->bmiHeader.biSizeImage          = 0;
  329.     bmInfo->bmiHeader.biXPelsPerMeter      = 0;
  330.     bmInfo->bmiHeader.biYPelsPerMeter      = 0;
  331.     bmInfo->bmiHeader.biClrUsed            = 0;
  332.     bmInfo->bmiHeader.biClrImportant       = 0;
  333.     if (depth == 1) {
  334. unsigned char *p, *pend;
  335. GetDIBits(hdcMem, hbmp, 0, height, NULL, bmInfo, DIB_PAL_COLORS);
  336. data = ckalloc(bmInfo->bmiHeader.biSizeImage);
  337. if (!data) {
  338.     /* printf("Failed to allocate data area for XImage.n"); */
  339.     ret_image = NULL;
  340.     goto cleanup;
  341. }
  342. ret_image = XCreateImage(display, NULL, depth, ZPixmap, 0, data,
  343. width, height, 32, ((width + 31) >> 3) & ~1);
  344. if (ret_image == NULL) {
  345.     ckfree(data);
  346.     goto cleanup;
  347. }
  348. /* Get the BITMAP info into the Image. */
  349. if (GetDIBits(hdcMem, hbmp, 0, height, data, bmInfo,
  350. DIB_PAL_COLORS) == 0) {
  351.     ckfree((char *) ret_image->data);
  352.     ckfree((char *) ret_image);
  353.     ret_image = NULL;
  354.     goto cleanup;
  355. }
  356. p = data;
  357. pend = data + bmInfo->bmiHeader.biSizeImage;
  358. while (p < pend) {
  359.     *p = ~*p;
  360.     p++;
  361. }
  362.     } else if (depth == 8) {
  363. unsigned short *palette;
  364. unsigned int i;
  365. unsigned char *p;
  366. GetDIBits(hdcMem, hbmp, 0, height, NULL, bmInfo, DIB_PAL_COLORS);
  367. data = ckalloc(bmInfo->bmiHeader.biSizeImage);
  368. if (!data) {
  369.     /* printf("Failed to allocate data area for XImage.n"); */
  370.     ret_image = NULL;
  371.     goto cleanup;
  372. }
  373. ret_image = XCreateImage(display, NULL, 8, ZPixmap, 0, data,
  374. width, height, 8, width);
  375. if (ret_image == NULL) {
  376.     ckfree((char *) data);
  377.     goto cleanup;
  378. }
  379. /* Get the BITMAP info into the Image. */
  380. if (GetDIBits(hdcMem, hbmp, 0, height, data, bmInfo,
  381. DIB_PAL_COLORS) == 0) {
  382.     ckfree((char *) ret_image->data);
  383.     ckfree((char *) ret_image);
  384.     ret_image = NULL;
  385.     goto cleanup;
  386. }
  387. p = data;
  388. palette = (unsigned short *) bmInfo->bmiColors;
  389. for (i = 0; i < bmInfo->bmiHeader.biSizeImage; i++, p++) {
  390.     *p = (unsigned char) palette[*p];
  391. }
  392.     } else if (depth == 16) {
  393. GetDIBits(hdcMem, hbmp, 0, height, NULL, bmInfo, DIB_RGB_COLORS);
  394. data = ckalloc(bmInfo->bmiHeader.biSizeImage);
  395. if (!data) {
  396.     /* printf("Failed to allocate data area for XImage.n"); */
  397.     ret_image = NULL;
  398.     goto cleanup;
  399. }
  400. ret_image = XCreateImage(display, NULL, 16, ZPixmap, 0, data,
  401. width, height, 16, 0 /* will be calc'ed from bitmap_pad */);
  402. if (ret_image == NULL) {
  403.     ckfree((char *) data);
  404.     goto cleanup;
  405. }
  406. /* Get the BITMAP info directly into the Image. */
  407. if (GetDIBits(hdcMem, hbmp, 0, height, ret_image->data, bmInfo,
  408.     DIB_RGB_COLORS) == 0) {
  409.     ckfree((char *) ret_image->data);
  410.     ckfree((char *) ret_image);
  411.     ret_image = NULL;
  412.     goto cleanup;
  413. }
  414.     } else {
  415. GetDIBits(hdcMem, hbmp, 0, height, NULL, bmInfo, DIB_RGB_COLORS);
  416. data = ckalloc(width * height * 4);
  417. if (!data) {
  418.     /* printf("Failed to allocate data area for XImage.n"); */
  419.     ret_image = NULL;
  420.     goto cleanup;
  421. }
  422. ret_image = XCreateImage(display, NULL, 32, ZPixmap, 0, data,
  423. width, height, 0, width * 4);
  424. if (ret_image == NULL) {
  425.     ckfree((char *) data);
  426.     goto cleanup;
  427. }
  428. if (depth <= 24) {
  429.     /*
  430.      * This used to handle 16 and 24 bpp, but now just handles 24.
  431.      * It can likely be optimized for that. -- hobbs
  432.      */
  433.     unsigned char *smallBitData, *smallBitBase, *bigBitData;
  434.     unsigned int byte_width, h, w;
  435.     byte_width = ((width * 3 + 3) & ~3);
  436.     smallBitBase = ckalloc(byte_width * height);
  437.     if (!smallBitBase) {
  438. ckfree((char *) ret_image->data);
  439. ckfree((char *) ret_image);
  440. ret_image = NULL;
  441. goto cleanup;
  442.     }
  443.     smallBitData = smallBitBase;
  444.     /* Get the BITMAP info into the Image. */
  445.     if (GetDIBits(hdcMem, hbmp, 0, height, smallBitData, bmInfo,
  446. DIB_RGB_COLORS) == 0) {
  447. ckfree((char *) ret_image->data);
  448. ckfree((char *) ret_image);
  449. ckfree((char *) smallBitBase);
  450. ret_image = NULL;
  451. goto cleanup;
  452.     }
  453.     /* Copy the 24 Bit Pixmap to a 32-Bit one. */
  454.     for (h = 0; h < height; h++) {
  455. bigBitData   = ret_image->data + h * ret_image->bytes_per_line;
  456. smallBitData = smallBitBase + h * byte_width;
  457. for (w = 0; w < width; w++) {
  458.     *bigBitData++ = ((*smallBitData++));
  459.     *bigBitData++ = ((*smallBitData++));
  460.     *bigBitData++ = ((*smallBitData++));
  461.     *bigBitData++ = 0;
  462. }
  463.     }
  464.     /* Free the Device contexts, and the Bitmap */
  465.     ckfree((char *) smallBitBase);
  466. } else {
  467.     /* Get the BITMAP info directly into the Image. */
  468.     if (GetDIBits(hdcMem, hbmp, 0, height, ret_image->data, bmInfo,
  469.     DIB_RGB_COLORS) == 0) {
  470. ckfree((char *) ret_image->data);
  471. ckfree((char *) ret_image);
  472. ret_image = NULL;
  473. goto cleanup;
  474.     }
  475. }
  476.     }
  477.   cleanup:
  478.     if (bmInfo) {
  479. ckfree((char *) bmInfo);
  480.     }
  481.     if (hPal) {
  482. SelectPalette(hdcMem, hPalPrev1, FALSE);
  483.     }
  484.     DeleteDC(hdcMem);
  485.     DeleteObject(hbmp);
  486.     return ret_image;
  487. }
  488. /*
  489.  *----------------------------------------------------------------------
  490.  *
  491.  * XGetImage --
  492.  *
  493.  * This function copies data from a pixmap or window into an
  494.  * XImage.
  495.  *
  496.  * Results:
  497.  * Returns a newly allocated image containing the data from the
  498.  * given rectangle of the given drawable.
  499.  *
  500.  * Side effects:
  501.  * None.
  502.  *
  503.  *----------------------------------------------------------------------
  504.  */
  505. XImage *
  506. XGetImage(display, d, x, y, width, height, plane_mask, format)
  507.     Display* display;
  508.     Drawable d;
  509.     int x;
  510.     int y;
  511.     unsigned int width;
  512.     unsigned int height;
  513.     unsigned long plane_mask;
  514.     int format;
  515. {
  516.     TkWinDrawable *twdPtr = (TkWinDrawable *)d;
  517.     XImage *imagePtr;
  518.     HDC dc;
  519.     display->request++;
  520.     if (twdPtr == NULL) {
  521. /*
  522.  * Avoid unmapped windows or bad drawables
  523.  */
  524. return NULL;
  525.     }
  526.     if (twdPtr->type != TWD_BITMAP) {
  527. /*
  528.  * This handles TWD_WINDOW or TWD_WINDC, always creating a 32bit
  529.  * image.  If the window being copied isn't visible (unmapped or
  530.  * obscured), we quietly stop copying (no user error).
  531.  * The user will see black where the widget should be.
  532.  * This branch is likely followed in favor of XGetImageZPixmap as
  533.  * postscript printed widgets require RGB data.
  534.  */
  535. TkWinDCState state;
  536. unsigned int xx, yy, size;
  537. COLORREF pixel;
  538. dc = TkWinGetDrawableDC(display, d, &state);
  539. imagePtr = XCreateImage(display, NULL, 32,
  540. format, 0, NULL, width, height, 32, 0);
  541. size = imagePtr->bytes_per_line * imagePtr->height;
  542. imagePtr->data = ckalloc(size);
  543. ZeroMemory(imagePtr->data, size);
  544. for (yy = 0; yy < height; yy++) {
  545.     for (xx = 0; xx < width; xx++) {
  546. pixel = GetPixel(dc, x+(int)xx, y+(int)yy);
  547. if (pixel == CLR_INVALID) {
  548.     break;
  549. }
  550. PutPixel(imagePtr, xx, yy, pixel);
  551.     }
  552. }
  553. TkWinReleaseDrawableDC(d, dc, &state);
  554.     } else if (format == ZPixmap) {
  555. /*
  556.  * This actually handles most TWD_WINDOW requests, but it varies
  557.  * from the above in that it really does a screen capture of
  558.  * an area, which is consistent with the Unix behavior, but does
  559.  * not appear to handle all bit depths correctly. -- hobbs
  560.  */
  561. imagePtr = XGetImageZPixmap(display, d, x, y,
  562. width, height, plane_mask, format);
  563.     } else {
  564. char *errMsg = NULL;
  565. char infoBuf[sizeof(BITMAPINFO) + sizeof(RGBQUAD)];
  566. BITMAPINFO *infoPtr = (BITMAPINFO*)infoBuf;
  567. if (twdPtr->bitmap.handle == NULL) {
  568.     errMsg = "XGetImage: not implemented for empty bitmap handles";
  569. } else if (format != XYPixmap) {
  570.     errMsg = "XGetImage: not implemented for format != XYPixmap";
  571. } else if (plane_mask != 1) {
  572.     errMsg = "XGetImage: not implemented for plane_mask != 1";
  573. }
  574. if (errMsg != NULL) {
  575.     /*
  576.      * Do a soft warning for the unsupported XGetImage types.
  577.      */
  578.     TkpDisplayWarning(errMsg, "XGetImage Failure");
  579.     return NULL;
  580. }
  581. imagePtr = XCreateImage(display, NULL, 1, XYBitmap, 0, NULL,
  582. width, height, 32, 0);
  583. imagePtr->data = ckalloc(imagePtr->bytes_per_line * imagePtr->height);
  584. dc = GetDC(NULL);
  585. GetDIBits(dc, twdPtr->bitmap.handle, 0, height, NULL,
  586. infoPtr, DIB_RGB_COLORS);
  587. infoPtr->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  588. infoPtr->bmiHeader.biWidth = width;
  589. infoPtr->bmiHeader.biHeight = -(LONG)height;
  590. infoPtr->bmiHeader.biPlanes = 1;
  591. infoPtr->bmiHeader.biBitCount = 1;
  592. infoPtr->bmiHeader.biCompression = BI_RGB;
  593. infoPtr->bmiHeader.biSizeImage          = 0;
  594. infoPtr->bmiHeader.biXPelsPerMeter = 0;
  595. infoPtr->bmiHeader.biYPelsPerMeter = 0;
  596. infoPtr->bmiHeader.biClrUsed = 0;
  597. infoPtr->bmiHeader.biClrImportant = 0;
  598. GetDIBits(dc, twdPtr->bitmap.handle, 0, height, imagePtr->data,
  599. infoPtr, DIB_RGB_COLORS);
  600. ReleaseDC(NULL, dc);
  601.     }
  602.     return imagePtr;
  603. }