/*------------------------------------------ DIBHELP.C -- DIB Section Helper Routines (c) Charles Petzold, 1998 ------------------------------------------*/ #include "stdafx.h" #include "hdib.h" // Function : DibHeaderSize // Descript : Returns the number of bytes of header // Return : long // Argument : HDIB lpDIB long DibHeaderSize(HDIB lpDIB) { // pointer to a Win 3.0-style DIB LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER)lpDIB; // pointer to an other-style DIB LPBITMAPCOREHEADER lpbmc = (LPBITMAPCOREHEADER)lpDIB; /* return the DIB width if it is a Win 3.0 DIB */ if (IS_WIN30_DIB(lpDIB)) { if (lpbmi->biCompression == BI_BITFIELDS) return (lpbmi->biSize + 12); return lpbmi->biSize; } /* it is an other-style DIB, so return its width */ return lpbmc->bcSize; } // Function : DibImage // Descript : Return address of the image // Return : LPSTR // Argument : HDIB lpDIB LPSTR DibImage(HDIB lpDIB) { return ((LPSTR)lpDIB + DibHeaderSize(lpDIB) + DibPaletteSize(lpDIB)); } // Function : DibImageSize // Descript : Returns the number of total bytes of the image // Return : long // Argument : HDIB lpDIB long DibImageSize(HDIB lpDIB) { /* return the DIB width if it is a Win 3.0 DIB */ if (IS_WIN30_DIB(lpDIB)) { long nSizeImage = ((LPBITMAPINFOHEADER)lpDIB)->biSizeImage; if (nSizeImage != 0) return nSizeImage; } return DibHeight(lpDIB) * DibRowLength(lpDIB); } // Function : DibHeight // Descript : Returns the bitmap pixel height // Return : void // Argument : void long DibHeight(HDIB lpDIB) { // pointer to a Win 3.0-style DIB LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER)lpDIB; // pointer to an other-style DIB LPBITMAPCOREHEADER lpbmc = (LPBITMAPCOREHEADER)lpDIB; /* return the DIB width if it is a Win 3.0 DIB */ if (IS_WIN30_DIB(lpDIB)) return lpbmi->biHeight; /* it is an other-style DIB, so return its height */ return (long) lpbmc->bcHeight; } // Function : DibWidth // Descript : Returns the bitmap pixel width // Return : long // Argument : HDIB lpDIB - address long DibWidth(HDIB lpDIB) { // pointer to a Win 3.0-style DIB LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER)lpDIB; // pointer to an other-style DIB LPBITMAPCOREHEADER lpbmc = (LPBITMAPCOREHEADER)lpDIB; /* return the DIB width if it is a Win 3.0 DIB */ if (IS_WIN30_DIB(lpDIB)) return lpbmi->biWidth; /* it is an other-style DIB, so return its width */ return (long) lpbmc->bcWidth; } // Function : DibBitCount // Descript : Returns the number of bits per pixel // Return : long // Argument : HDIB lpDIB long DibBitCount(HDIB lpDIB) { // pointer to a Win 3.0-style DIB LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER)lpDIB; // pointer to an other-style DIB LPBITMAPCOREHEADER lpbmc = (LPBITMAPCOREHEADER)lpDIB; /* return the DIB width if it is a Win 3.0 DIB */ if (IS_WIN30_DIB(lpDIB)) return lpbmi->biBitCount; /* it is an other-style DIB, so return its width */ return lpbmc->bcBitCount; } // Function : DibRowLength // Descript : Returns the number of bytes per row of pixels // Return : long // Argument : HDIB lpDIB long DibRowLength(HDIB lpDIB) { return ((DibWidth(lpDIB) * DibBitCount(lpDIB) + 31) & ~31) >> 3 ; } // Function : DibImageIndex // Descript : Return index of the image // Return : long // Argument : HDIB lpDIB // Argument : long x // Argument : long y long DibImageIndex(HDIB lpDIB, long x, long y) { return (y * DibRowLength(lpDIB) + ((x * DibBitCount(lpDIB)) >> 3)); } // Function : DibPalette // Descript : Return address of the palette // Return : LPSTR // Argument : HDIB lpDIB LPSTR DibPalette(HDIB lpDIB) { return ((LPSTR)lpDIB + DibHeaderSize(lpDIB)); } // Function : DibNumColors // Descript : Returns the number of used color // Return : long // Argument : HDIB lpDIB long DibNumColors(HDIB lpDIB) { long nBitCount; // DIB bit count /* If this is a Windows-style DIB, the number of colors in the * color table can be less than the number of bits per pixel * allows for (i.e. lpbi->biClrUsed can be set to some value). * If this is the case, return the appropriate value. */ if (IS_WIN30_DIB(lpDIB)) { long nClrUsed = ((LPBITMAPINFOHEADER)lpDIB)->biClrUsed; if (nClrUsed != 0) return nClrUsed; } /* Calculate the number of colors in the color table based on * the number of bits per pixel for the DIB. */ if (IS_WIN30_DIB(lpDIB)) nBitCount = ((LPBITMAPINFOHEADER)lpDIB)->biBitCount; else nBitCount = ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount; /* return number of colors based on bits per pixel */ if (nBitCount <= 8) return 1 << nBitCount; return 0; } // Function : DibPaletteSize // Descript : Returns number of total bytes of palette // Return : long // Argument : HDIB lpDIB long DibPaletteSize(HDIB lpDIB) { /* calculate the size required by the palette */ if (IS_WIN30_DIB (lpDIB)) return (::DibNumColors(lpDIB) * sizeof(RGBQUAD)); return (::DibNumColors(lpDIB) * sizeof(RGBTRIPLE)); } // Function : DibGetPaletteColor // Descript : Return one color of palette // Return : long // Argument : HDIB lpDIB // Argument : long index RGBQUAD DibGetPaletteColor(HDIB lpDIB, long index) { if (DibNumColors(lpDIB) <= index) { RGBQUAD color = {0, 0, 0, 0}; return color; } /* return the DIB width if it is a Win 3.0 DIB */ if (IS_WIN30_DIB (lpDIB)) { RGBQUAD *palette = (RGBQUAD *)DibPalette(lpDIB); return palette[index]; } /* it is an other-style DIB, so return its width */ RGBTRIPLE *palette = (RGBTRIPLE *)DibPalette(lpDIB); RGBQUAD color; color.rgbRed = palette[index].rgbtRed; color.rgbGreen = palette[index].rgbtGreen; color.rgbBlue = palette[index].rgbtBlue; return color; } // Function : DibSetPaletteColor // Descript : Set one color of palette // Return : BOOL // Argument : HDIB lpDIB // Argument : long index // Argument : RGBQUAD color BOOL DibSetPaletteColor(HDIB lpDIB, long index, RGBQUAD color) { if (DibNumColors(lpDIB) <= index) return FALSE; /* return the DIB width if it is a Win 3.0 DIB */ if (IS_WIN30_DIB (lpDIB)) { RGBQUAD *palette = (RGBQUAD *)DibPalette(lpDIB); palette[index] = color; return TRUE; } /* it is an other-style DIB, so return its width */ RGBTRIPLE *palette = (RGBTRIPLE *)DibPalette(lpDIB); palette[index].rgbtRed = color.rgbRed; palette[index].rgbtGreen = color.rgbGreen; palette[index].rgbtBlue = color.rgbBlue; return TRUE; } // Function : DibGetPaletteColor // Descript : Return index of palette // Return : WORD // Argument : HDIB lpDIB // Argument : RGBQUAD color WORD DibGetPaletteIndex(HDIB lpDIB, RGBQUAD color) { WORD wColors = (WORD)DibNumColors(lpDIB); /* return the DIB width if it is a Win 3.0 DIB */ if (IS_WIN30_DIB (lpDIB)) { RGBQUAD *palette = (RGBQUAD *)DibPalette(lpDIB); for (WORD i = 0; i < wColors; i++) { if (palette[i].rgbRed == color.rgbRed && palette[i].rgbGreen == color.rgbGreen && palette[i].rgbBlue == color.rgbBlue) return i; } return -1; } /* it is an other-style DIB, so return its width */ RGBTRIPLE *palette = (RGBTRIPLE *)DibPalette(lpDIB); for (WORD i = 0; i < wColors; i++) { if (palette[i].rgbtRed == color.rgbRed && palette[i].rgbtGreen == color.rgbGreen && palette[i].rgbtBlue == color.rgbBlue) return i; } return -1; } ////////////////////////////////////////////////////////////////////////////// // DIB Main // Function : DibCreate // Descript : Create DIB image 1, 4, 8, 16, 24, 32-bit // Return : HDIB // Argument : long width // Argument : long height // Argument : long depth HDIB DibCreate(long width, long height, long depth) { if (width < 1 || height < 1 || depth < 1 || depth > 32) return NULL; DWORD dwSizeImage = height * (DWORD)((width*depth/8 + 3) & ~3); long nClrUsed = 0; HDIB hImage; if (depth > 8) hImage = (HDIB) GlobalAlloc(GHND, sizeof(BITMAPINFOHEADER)+dwSizeImage); else { nClrUsed = 1 << depth; hImage = (HDIB) GlobalAlloc(GHND, sizeof(BITMAPINFOHEADER)+dwSizeImage + sizeof(RGBQUAD)*nClrUsed); } if (hImage == NULL) return NULL; LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER) GlobalLock(hImage); lpbi->biSize = sizeof(BITMAPINFOHEADER) ; lpbi->biWidth = width; lpbi->biHeight = height; lpbi->biPlanes = 1; lpbi->biBitCount = (WORD) depth; lpbi->biCompression = BI_RGB; lpbi->biSizeImage = dwSizeImage; lpbi->biXPelsPerMeter = 0; lpbi->biYPelsPerMeter = 0; lpbi->biClrUsed = nClrUsed; lpbi->biClrImportant = 0; if (depth <= 8) { long nStep = 256 >> depth; RGBQUAD * lpPal = (RGBQUAD *) ::DibPalette(lpbi); for (long i = 0; i < nClrUsed; i++) { lpPal[i].rgbRed = (BYTE)(i * nStep); lpPal[i].rgbGreen = (BYTE)(i * nStep); lpPal[i].rgbBlue = (BYTE)(i * nStep); lpPal[i].rgbReserved = 0x00; } } GlobalUnlock(hImage); return hImage; } // Function : DibGetPixel // Descript : Obtains a pixel value at (x, y) // Return : void // Argument : HDIB lpDIB // Argument : long x // Argument : long y // Argument : RGBQUAD *color void DibGetPixelColor(HDIB lpDIB, long x, long y, RGBQUAD *color) { // À̹ÌÁö ¹üÀ§¿¡ Àִ°¡? long dx = DibWidth(lpDIB); long dy = DibHeight(lpDIB); if (x < 0 || x >= dx || y < 0 || y >= dy) return ; // À̹ÌÁö À§Ä¡ ã±â BYTE *address = (BYTE *)DibImage(lpDIB); long index = DibImageIndex(lpDIB, x, y); // »ö»ó °¡Á®¿À±â WORD colorCode; WORD colorIndex; unsigned long temp; switch (DibBitCount(lpDIB)) { case 1: colorIndex = 0x01 & (address[index] >> (7 - (x & 7))) ; *color = DibGetPaletteColor(lpDIB, colorIndex); break; case 4: colorIndex = 0x0F & (address[index] >> (x & 1 ? 0 : 4)) ; *color = DibGetPaletteColor(lpDIB, colorIndex); break; case 8: colorIndex = address[index]; *color = DibGetPaletteColor(lpDIB, colorIndex); break; case 16: colorCode = ((WORD)((BYTE)address[index + 1]) << 8) | (address[index] & 0x00ff); color->rgbBlue = (colorCode & 0x001f) << 3; color->rgbGreen = (colorCode & 0x03e0) >> 2; color->rgbRed = (colorCode & 0x7c00) >> 7; color->rgbReserved = 0; break; case 24: temp = 0x00FFFFFF & (* ((DWORD *)(address + index))); *color = * (RGBQUAD *) &temp; break; case 32: *color = * ((RGBQUAD *) (address + index + 4)); break; } } // Function : DibSetPixelColor // Descript : Sets a pixel value at (x, y) // Return : BOOL // Argument : HDIB lpDIB BOOL DibSetPixelColor(HDIB lpDIB, long x, long y, RGBQUAD color) { // À̹ÌÁö ¹üÀ§¿¡ Àִ°¡? long dx = DibWidth(lpDIB); long dy = DibHeight(lpDIB); if (x < 0 || x >= dx || y < 0 || y >= dy) return FALSE; // À̹ÌÁö À§Ä¡ ã±â BYTE *address = (BYTE *)DibImage(lpDIB); long index = DibImageIndex(lpDIB, x, y); // »ö»ó ÀúÀåÇϱâ WORD wColorIndex; WORD wColorCode; switch (DibBitCount(lpDIB)) { case 1: wColorIndex = DibGetPaletteIndex(lpDIB, color); if (wColorIndex < 0) return FALSE; // ÇØ´ç »ö»ó ¾ø´Â °æ¿ì address[index] &= ~(1 << (7 - (x & 7))) ; address[index] |= (BYTE)wColorIndex << (7 - (x & 7)); break; case 4: wColorIndex = DibGetPaletteIndex(lpDIB, color); if (wColorIndex < 0) return FALSE; // ÇØ´ç »ö»ó ¾ø´Â °æ¿ì address[index] &= 0x0F << (x & 1 ? 4 : 0); address[index] |= (BYTE)wColorIndex << (x & 1 ? 0 : 4); break; case 8: wColorIndex = DibGetPaletteIndex(lpDIB, color); if (wColorIndex < 0) return FALSE; // ÇØ´ç »ö»ó ¾ø´Â °æ¿ì address[index] = (BYTE)wColorIndex; break; case 16: wColorCode = (WORD)(color.rgbBlue & 0x1f) | ((WORD)(color.rgbGreen & 0x1f) << 5) | ((WORD)(color.rgbRed & 0x3f) << 10); * (WORD *) (address + index) = wColorCode; break ; case 24: * (RGBTRIPLE *) (address + index) = * (RGBTRIPLE *) &color; break ; case 32: * (RGBQUAD *) (address + index) = color; break ; default: return FALSE ; } return TRUE ; } HDIB DDB2DIB(CBitmap &bmImage) { // Àüü È­¸é DC CDC ScrDC; ScrDC.CreateDC("DISPLAY", NULL, NULL, NULL); // Make DIB // 24-Bit per color DIB Setting BITMAP tBmp; bmImage.GetBitmap(&tBmp); // DIB ÃʱâÈ­ DWORD dwSizeImage = tBmp.bmHeight * DWORD((tBmp.bmWidth*3+3)&~3); HDIB hImage = (HDIB) GlobalAlloc(GHND, sizeof(BITMAPINFOHEADER)+dwSizeImage); if (hImage == NULL) return NULL; LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER) GlobalLock(hImage); lpbi->biSize = sizeof(BITMAPINFOHEADER); lpbi->biWidth = tBmp.bmWidth; lpbi->biHeight = tBmp.bmHeight; lpbi->biPlanes = 1; lpbi->biBitCount = 24; // À̹ÌÁö¸¦ °íÁ¤ÇÏ¿´´Ù. lpbi->biCompression = BI_RGB; lpbi->biSizeImage = dwSizeImage; lpbi->biXPelsPerMeter = 0 ; lpbi->biYPelsPerMeter = 0 ; lpbi->biClrUsed = 0 ; lpbi->biClrImportant = 0 ; LPBYTE lpImage = (LPBYTE)lpbi + sizeof(BITMAPINFOHEADER); // Get Image Data GetDIBits(ScrDC.m_hDC, (HBITMAP)bmImage, 0L, (DWORD)tBmp.bmHeight, (LPBYTE)lpImage, (LPBITMAPINFO)lpbi, DIB_RGB_COLORS); GlobalUnlock(hImage); return hImage; } //////////////////////////////////////////////////////////////////////////////