//--------------------------------------------------------------------------// //--------------------------------------------------------------------------// void CAGSymImage::LoadDIB(const BITMAPINFOHEADER* pHdr, const BYTE* pBits) { Free(); if (pHdr->biCompression == BI_RGB && (pHdr->biBitCount == 1 || pHdr->biBitCount == 4 || pHdr->biBitCount == 8 || pHdr->biBitCount == 24)) { BITMAPINFOHEADER bi; bi = *pHdr; bi.biCompression = BI_RGB; if (!bi.biSizeImage) bi.biSizeImage = DibSizeImage(&bi); if (!bi.biClrUsed) bi.biClrUsed = DibNumColors(&bi); if (m_pDIB = (BITMAPINFOHEADER*)malloc(DibSize(&bi))) { *m_pDIB = bi; if (bi.biClrUsed) memcpy((void*)DibColors(m_pDIB), (void*)DibColors(pHdr), DibPaletteSize(pHdr)); BYTE* pNewBits = (BYTE*)DibPtr(m_pDIB); const BYTE* pSrcBits; if (pBits) pSrcBits = pBits; else pSrcBits = (BYTE*)(DibColors(pHdr) + bi.biClrUsed); memcpy(pNewBits, pSrcBits, bi.biSizeImage); } } }
BOOL StartScan(DWORD *pdwLineSize) { /* * Preload our image into memory */ char szModulePath[_MAX_PATH]; char szCompletePath[_MAX_PATH]; char szFileLocation[_MAX_PATH]; char szDriveName[_MAX_DRIVE]; VERIFY(GetModuleFileName(hDSInst, szModulePath, _MAX_PATH)); _splitpath(szModulePath, szDriveName, szFileLocation, NULL, NULL); wsprintf(szCompletePath, "%s%s", szDriveName, szFileLocation); _giRowsCopied = 0; _gpHeader = NULL; _gpImageData = NULL; _gpCurrentLine = NULL; _gdwLineSize = 0l; if(_ghDIB) { GlobalFree(_ghDIB); _ghDIB = NULL; } if(GetCurrentXResolution()==100.0F) { /* * Easy, this is the format of our originals */ if(GetCurrentPixelType()==TWPT_GRAY) { strcat(szCompletePath, "twaingray.bmp"); _ghDIB = OpenDIB(szCompletePath); } else if(GetCurrentPixelType()==TWPT_RGB) { strcat(szCompletePath, "twainrgb.bmp"); _ghDIB = OpenDIB(szCompletePath); } else { strcat(szCompletePath, "twainbw.bmp"); _ghDIB = OpenDIB(szCompletePath); } _gpHeader = (BITMAPINFOHEADER*)GlobalLock(_ghDIB); if(_gpHeader) { _gpImageData = ((BYTE*)_gpHeader) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * DibNumColors(_gpHeader); _gdwLineSize = ((_gpHeader->biWidth * _gpHeader->biBitCount+31)/32)*4; _gpCurrentLine = _gpImageData + (_gdwLineSize * (_gpHeader->biHeight-1)); *pdwLineSize = _gdwLineSize; } } return _ghDIB?TRUE:FALSE; }
WORD PaletteSize (VOID FAR * pv) { LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)pv; WORD NumColors = DibNumColors(lpbi); if (lpbi->biSize == sizeof(BITMAPCOREHEADER)) return (WORD)(NumColors * sizeof(RGBTRIPLE)); else return (WORD)(NumColors * sizeof(RGBQUAD)); }
BOOL W32CheckDibColorIndices(LPBITMAPINFOHEADER lpbmi) { WORD i, nColors; LPWORD lpw = (LPWORD)DibColors(lpbmi); nColors = DibNumColors(lpbmi); if (lpbmi->biClrImportant) { nColors = min(nColors, (WORD)lpbmi->biClrImportant); } for (i = 0; i < nColors; ++i) { if (*lpw++ != i) { return FALSE; } } LOGDEBUG(LOG_ALWAYS, ("\nUndocumented Dib.Drv behaviour used\n")); return TRUE; }
HPALETTE CreateBIPalette (LPBITMAPINFOHEADER lpbi) { LOGPALETTE *pPal; HPALETTE hpal = NULL; WORD nNumColors; BYTE red; BYTE green; BYTE blue; WORD i; RGBQUAD FAR *pRgb; if (!lpbi) return NULL; if (lpbi->biSize != sizeof(BITMAPINFOHEADER)) return NULL; /* Get a pointer to the color table and the number of colors in it */ pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize); nNumColors = DibNumColors(lpbi); if (nNumColors) { /* Allocate for the logical palette structure */ pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY)); if (!pPal) return NULL; pPal->palNumEntries = nNumColors; pPal->palVersion = 0x300; /* Fill in the palette entries from the DIB color table and create a logical color palette. */ for (i = 0; i < nNumColors; i++) { pPal->palPalEntry[i].peRed = pRgb[i].rgbRed; pPal->palPalEntry[i].peGreen = pRgb[i].rgbGreen; pPal->palPalEntry[i].peBlue = pRgb[i].rgbBlue; pPal->palPalEntry[i].peFlags = (BYTE)0; } hpal = CreatePalette(pPal); LocalFree((HANDLE)pPal); } else if (lpbi->biBitCount == 24) { /* A 24 bitcount DIB has no color table entries so, set the number of to the maximum value (256). */ nNumColors = 256; pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY)); if (!pPal) return NULL; pPal->palNumEntries = nNumColors; pPal->palVersion = 0x300; red = green = blue = 0; for (i = 0; i < pPal->palNumEntries; i++) { pPal->palPalEntry[i].peRed = red; pPal->palPalEntry[i].peGreen = green; pPal->palPalEntry[i].peBlue = blue; pPal->palPalEntry[i].peFlags = (BYTE)0; if (!(red += 32)) if (!(green += 32)) blue += 64; } hpal = CreatePalette(pPal); LocalFree((HANDLE)pPal); } return hpal; }
BOOL CDib::Open(HWND hWnd, const char *pFileName, BOOL bOpenFromFile) { /* UINT fuLoad; if(bOpenFromFile==TRUE) fuLoad = LR_CREATEDIBSECTION|LR_LOADFROMFILE|LR_DEFAULTSIZE; else fuLoad = (bOpenFromFile?LR_CREATEDIBSECTION:0)|LR_LOADFROMFILE|LR_DEFAULTSIZE; */ m_hBitmap=(HBITMAP)::LoadImage( bOpenFromFile? NULL : (HINSTANCE)GetWindowLong(hWnd,GWL_HINSTANCE), pFileName, IMAGE_BITMAP, 0,0, //fuLoad); LR_CREATEDIBSECTION|(bOpenFromFile?LR_LOADFROMFILE:0)|LR_DEFAULTSIZE); if(m_hBitmap==NULL){ // SetErrors(CMERR_CANT_OPEN_FILE,pFileName); return FALSE; } BITMAP bm; BITMAPINFOHEADER bi; LPBITMAPINFOHEADER lpbi; // 24bit라서 팔레트 정보가 없을 것이므로 필요없으나... 확장을 위해 GetObject(m_hBitmap,sizeof(BITMAP),&bm); if(bm.bmHeight>=0)m_bTopDown=FALSE; else m_bTopDown=TRUE; bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = bm.bmWidth; bi.biHeight = bm.bmHeight; bi.biPlanes = 1; //bi.biBitCount = bm.bmPlanes * bm.bmBitsPixel; bi.biBitCount = 24; // 8bit 도 24bit로 읽어낸다. 따라서 Pal 정보가 없다. bi.biCompression = BI_RGB; bi.biSizeImage = 0; bi.biXPelsPerMeter = 0; bi.biYPelsPerMeter = 0; bi.biClrUsed = 0; bi.biClrImportant = 0; // 팔레트 개수 #define DibNumColors(lpbi) ((lpbi)->biClrUsed == 0 && (lpbi)->biBitCount <= 8 \ ? (WORD)(1 << (int)(lpbi)->biBitCount) \ : (WORD)(lpbi)->biClrUsed) // BITMAPINFO( BITMAPINFOHEADER+PAL ) 의 크기 DWORD nLen = bi.biSize + DibNumColors(&bi) * sizeof(RGBQUAD); lpbi=(LPBITMAPINFOHEADER)new char[nLen]; *lpbi=bi; HDC hDC=GetDC(hWnd); GetDIBits(hDC,m_hBitmap,0,bi.biHeight,NULL,(LPBITMAPINFO)lpbi,DIB_RGB_COLORS); ReleaseDC(hWnd,hDC); bi=*lpbi; // 드라이버가 biSizeImage를 채우지 않는 경우 if(bi.biSizeImage==0){ bi.biSizeImage=(DWORD)WIDTHBYTES(bm.bmWidth*bi.biBitCount)*bm.bmHeight; if(bi.biCompression!=BI_RGB) bi.biSizeImage=(bi.biSizeImage*3)/2; } delete[] lpbi; nLen=bi.biSize+DibNumColors(&bi)*sizeof(RGBQUAD)+bi.biSizeImage; //lpbi=(LPBITMAPINFOHEADER)new char[nLen]; m_pBitmapData=new BYTE[nLen]; if(m_pBitmapData==NULL){ //_RPT0(_CRT_WARN,"Memory Allocation Error"); // SetError(CMERR_OUT_OF_MEMORY); return FALSE; } *(LPBITMAPINFOHEADER)m_pBitmapData=bi; hDC=GetDC(hWnd); GetDIBits(hDC,m_hBitmap,0,bi.biHeight,DibPtr((LPBITMAPINFOHEADER)m_pBitmapData),(LPBITMAPINFO)m_pBitmapData,DIB_RGB_COLORS); ReleaseDC(hWnd,hDC); return TRUE; }
PDIB DibReadBitmapInfo(int fh) { DWORD off; HANDLE hbi = NULL; int size; int i; int nNumColors; RGBQUAD FAR *pRgb; BITMAPINFOHEADER bi; BITMAPCOREHEADER bc; BITMAPFILEHEADER bf; PDIB pdib; if (fh == -1) return NULL; off = lseek(fh,0L,SEEK_CUR); if (sizeof(bf) != read(fh,(LPSTR)&bf,sizeof(bf))) return FALSE; /* * do we have a RC HEADER? */ if (bf.bfType != BFT_BITMAP) { bf.bfOffBits = 0L; lseek(fh,off,SEEK_SET); } if (sizeof(bi) != read(fh,(LPSTR)&bi,sizeof(bi))) return FALSE; /* * what type of bitmap info is this? */ switch (size = (int)bi.biSize) { default: case sizeof(BITMAPINFOHEADER): break; case sizeof(BITMAPCOREHEADER): bc = *(BITMAPCOREHEADER*)&bi; bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = (DWORD)bc.bcWidth; bi.biHeight = (DWORD)bc.bcHeight; bi.biPlanes = (UINT)bc.bcPlanes; bi.biBitCount = (UINT)bc.bcBitCount; bi.biCompression = BI_RGB; bi.biSizeImage = 0; bi.biXPelsPerMeter = 0; bi.biYPelsPerMeter = 0; bi.biClrUsed = 0; bi.biClrImportant = 0; lseek(fh,(LONG)sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER),SEEK_CUR); break; } nNumColors = DibNumColors(&bi); if (bi.biSizeImage == 0) bi.biSizeImage = DibSizeImage(&bi); if (bi.biClrUsed == 0) bi.biClrUsed = DibNumColors(&bi); pdib = (PDIB) malloc((LONG)bi.biSize + nNumColors * sizeof(RGBQUAD)); if (!pdib) return NULL; *pdib = bi; pRgb = DibColors(pdib); if (nNumColors == 0) { printf("Bitmap has no palette (24 bit)\n", NUM_COLORS, nNumColors); return NULL; } if (nNumColors != NUM_COLORS) { printf("Expecting %d color bitmap; found %d colors\n", NUM_COLORS, nNumColors); return NULL; } if (size == sizeof(BITMAPCOREHEADER)) { /* * convert a old color table (3 byte entries) to a new * color table (4 byte entries) */ read(fh,(LPVOID)pRgb,nNumColors * sizeof(RGBTRIPLE)); for (i=nNumColors-1; i>=0; i--) { RGBQUAD rgb; rgb.rgbRed = ((RGBTRIPLE FAR *)pRgb)[i].rgbtRed; rgb.rgbBlue = ((RGBTRIPLE FAR *)pRgb)[i].rgbtBlue; rgb.rgbGreen = ((RGBTRIPLE FAR *)pRgb)[i].rgbtGreen; rgb.rgbReserved = (BYTE)0; pRgb[i] = rgb; } } else { read(fh,(LPVOID)pRgb,nNumColors * sizeof(RGBQUAD)); } if (bf.bfOffBits != 0L) lseek(fh,off + bf.bfOffBits,SEEK_SET); return pdib; }
HDIB DibConvert (HDIB hdibSrc, int iBitCountDst) { HDIB hdibDst ; HPALETTE hPalette ; int i, x, y, cx, cy, iBitCountSrc, cColors ; PALETTEENTRY pe ; RGBQUAD rgb ; WORD wNumEntries ; cx = DibWidth (hdibSrc) ; cy = DibHeight (hdibSrc) ; iBitCountSrc = DibBitCount (hdibSrc) ; if (iBitCountSrc == iBitCountDst) return NULL ; // DIB with color table to DIB with larger color table: if ((iBitCountSrc < iBitCountDst) && (iBitCountDst <= 8)) { cColors = DibNumColors (hdibSrc) ; hdibDst = DibCreate (cx, cy, iBitCountDst, cColors) ; for (i = 0 ; i < cColors ; i++) { DibGetColor (hdibSrc, i, &rgb) ; DibSetColor (hdibDst, i, &rgb) ; } for (x = 0 ; x < cx ; x++) for (y = 0 ; y < cy ; y++) { DibSetPixel (hdibDst, x, y, DibGetPixel (hdibSrc, x, y)) ; } } // Any DIB to DIB with no color table else if (iBitCountDst >= 16) { hdibDst = DibCreate (cx, cy, iBitCountDst, 0) ; for (x = 0 ; x < cx ; x++) for (y = 0 ; y < cy ; y++) { DibGetPixelColor (hdibSrc, x, y, &rgb) ; DibSetPixelColor (hdibDst, x, y, &rgb) ; } } // DIB with no color table to 8-bit DIB else if (iBitCountSrc >= 16 && iBitCountDst == 8) { hPalette = DibPalMedianCut (hdibSrc, 6) ; GetObject (hPalette, sizeof (WORD), &wNumEntries) ; hdibDst = DibCreate (cx, cy, 8, wNumEntries) ; for (i = 0 ; i < (int) wNumEntries ; i++) { GetPaletteEntries (hPalette, i, 1, &pe) ; rgb.rgbRed = pe.peRed ; rgb.rgbGreen = pe.peGreen ; rgb.rgbBlue = pe.peBlue ; rgb.rgbReserved = 0 ; DibSetColor (hdibDst, i, &rgb) ; } for (x = 0 ; x < cx ; x++) for (y = 0 ; y < cy ; y++) { DibGetPixelColor (hdibSrc, x, y, &rgb) ; DibSetPixel (hdibDst, x, y, GetNearestPaletteIndex (hPalette, RGB (rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue))) ; } DeleteObject (hPalette) ; } // Any DIB to monochrome DIB else if (iBitCountDst == 1) { hdibDst = DibCreate (cx, cy, 1, 0) ; hPalette = DibPalUniformGrays (2) ; for (i = 0 ; i < 2 ; i++) { GetPaletteEntries (hPalette, i, 1, &pe) ; rgb.rgbRed = pe.peRed ; rgb.rgbGreen = pe.peGreen ; rgb.rgbBlue = pe.peBlue ; rgb.rgbReserved = 0 ; DibSetColor (hdibDst, i, &rgb) ; } for (x = 0 ; x < cx ; x++) for (y = 0 ; y < cy ; y++) { DibGetPixelColor (hdibSrc, x, y, &rgb) ; DibSetPixel (hdibDst, x, y, GetNearestPaletteIndex (hPalette, RGB (rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue))) ; } DeleteObject (hPalette) ; } // All non-monochrome DIBs to 4-bit DIB else if (iBitCountSrc >= 8 && iBitCountDst == 4) { hdibDst = DibCreate (cx, cy, 4, 0) ; hPalette = DibPalVga () ; for (i = 0 ; i < 16 ; i++) { GetPaletteEntries (hPalette, i, 1, &pe) ; rgb.rgbRed = pe.peRed ; rgb.rgbGreen = pe.peGreen ; rgb.rgbBlue = pe.peBlue ; rgb.rgbReserved = 0 ; DibSetColor (hdibDst, i, &rgb) ; } for (x = 0 ; x < cx ; x++) for (y = 0 ; y < cy ; y++) { DibGetPixelColor (hdibSrc, x, y, &rgb) ; DibSetPixel (hdibDst, x, y, GetNearestPaletteIndex (hPalette, RGB (rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue))) ; } DeleteObject (hPalette) ; } // Should not be necessary else hdibDst = NULL ; return hdibDst ; }
bool CxImageBMP::Decode(CxFile * hFile) { if (hFile == NULL) return false; BITMAPFILEHEADER bf; DWORD off = hFile->Tell(); //<CSC> try { if (hFile->Read(&bf,min(14,sizeof(bf)),1)==0) throw "Not a BMP"; if (bf.bfType != BFT_BITMAP) { //do we have a RC HEADER? bf.bfOffBits = 0L; hFile->Seek(off,SEEK_SET); } if (!DibReadBitmapInfo(hFile,&head)) throw "Error reading BMP info"; DWORD dwCompression=head.biCompression; DWORD dwBitCount=head.biBitCount; //preserve for BI_BITFIELDS compression <Thomas Ernst> bool bIsOldBmp = head.biSize == sizeof(BITMAPCOREHEADER); head.biSize = sizeof(BITMAPINFOHEADER); bool bTopDownDib = head.biHeight<0; //<Flanders> check if it's a top-down bitmap if (bTopDownDib) head.biHeight=-head.biHeight; if (!Create(head.biWidth,head.biHeight,head.biBitCount,CXIMAGE_FORMAT_BMP)) throw "Can't allocate memory"; info.xDPI = (long) floor(head.biXPelsPerMeter * 254.0 / 10000.0 + 0.5); info.yDPI = (long) floor(head.biYPelsPerMeter * 254.0 / 10000.0 + 0.5); if (info.nEscape) throw "Cancelled"; // <vho> - cancel decoding RGBQUAD *pRgb = GetPalette(); if (pRgb){ if (bIsOldBmp){ // convert a old color table (3 byte entries) to a new // color table (4 byte entries) hFile->Read((void*)pRgb,DibNumColors(&head) * sizeof(RGBTRIPLE),1); for (int i=DibNumColors(&head)-1; i>=0; i--){ pRgb[i].rgbRed = ((RGBTRIPLE *)pRgb)[i].rgbtRed; pRgb[i].rgbBlue = ((RGBTRIPLE *)pRgb)[i].rgbtBlue; pRgb[i].rgbGreen = ((RGBTRIPLE *)pRgb)[i].rgbtGreen; pRgb[i].rgbReserved = (BYTE)0; } } else { hFile->Read((void*)pRgb,DibNumColors(&head) * sizeof(RGBQUAD),1); //force rgbReserved=0, to avoid problems with some WinXp bitmaps for (unsigned int i=0; i<head.biClrUsed; i++) pRgb[i].rgbReserved=0; } } if (info.nEscape) throw "Cancelled"; // <vho> - cancel decoding switch (dwBitCount) { case 32 : if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET); if (dwCompression == BI_BITFIELDS || dwCompression == BI_RGB){ long imagesize=4*head.biHeight*head.biWidth; BYTE* buff32=(BYTE*)malloc(imagesize); if (buff32){ hFile->Read(buff32, imagesize,1); // read in the pixels Bitfield2RGB(buff32,0,0,0,32); free(buff32); } else throw "can't allocate memory"; } else throw "unknown compression"; break; case 24 : if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET); if (dwCompression == BI_RGB){ hFile->Read(info.pImage, head.biSizeImage,1); // read in the pixels } else throw "unknown compression"; break; case 16 : { DWORD bfmask[3]; if (dwCompression == BI_BITFIELDS) { hFile->Read(bfmask, 12, 1); } else { bfmask[0]=0x7C00; bfmask[1]=0x3E0; bfmask[2]=0x1F; //RGB555 } // bf.bfOffBits required after the bitfield mask <Cui Ying Jie> if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET); // read in the pixels hFile->Read(info.pImage, head.biHeight*((head.biWidth+1)/2)*4,1); // transform into RGB Bitfield2RGB(info.pImage,(WORD)bfmask[0],(WORD)bfmask[1],(WORD)bfmask[2],16); break; } case 8 : case 4 : case 1 : if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET); switch (dwCompression) { case BI_RGB : hFile->Read(info.pImage, head.biSizeImage,1); // read in the pixels break; case BI_RLE4 : { BYTE status_byte = 0; BYTE second_byte = 0; int scanline = 0; int bits = 0; BOOL low_nibble = FALSE; CImageIterator iter(this); for (BOOL bContinue = TRUE; bContinue;) { hFile->Read(&status_byte, sizeof(BYTE), 1); switch (status_byte) { case RLE_COMMAND : hFile->Read(&status_byte, sizeof(BYTE), 1); switch (status_byte) { case RLE_ENDOFLINE : bits = 0; scanline++; low_nibble = FALSE; break; case RLE_ENDOFBITMAP : bContinue=FALSE; break; case RLE_DELTA : { // read the delta values BYTE delta_x; BYTE delta_y; hFile->Read(&delta_x, sizeof(BYTE), 1); hFile->Read(&delta_y, sizeof(BYTE), 1); // apply them bits += delta_x / 2; scanline += delta_y; break; } default : hFile->Read(&second_byte, sizeof(BYTE), 1); BYTE *sline = iter.GetRow(scanline); for (int i = 0; i < status_byte; i++) { if (low_nibble) { if ((DWORD)(sline+bits) < (DWORD)(info.pImage+head.biSizeImage)){ *(sline + bits) |= second_byte & 0x0F; } if (i != status_byte - 1) hFile->Read(&second_byte, sizeof(BYTE), 1); bits++; } else { if ((DWORD)(sline+bits) < (DWORD)(info.pImage+head.biSizeImage)){ *(sline + bits) = (BYTE)(second_byte & 0xF0); } } low_nibble = !low_nibble; } if (((status_byte / 2) & 1 )== 1) hFile->Read(&second_byte, sizeof(BYTE), 1); break; }; break; default : { BYTE *sline = iter.GetRow(scanline); hFile->Read(&second_byte, sizeof(BYTE), 1); for (unsigned i = 0; i < status_byte; i++) { if (low_nibble) { if ((DWORD)(sline+bits) < (DWORD)(info.pImage+head.biSizeImage)){ *(sline + bits) |= second_byte & 0x0F; } bits++; } else { if ((DWORD)(sline+bits) < (DWORD)(info.pImage+head.biSizeImage)){ *(sline + bits) = (BYTE)(second_byte & 0xF0); } } low_nibble = !low_nibble; } } break; }; } break; } case BI_RLE8 : { BYTE status_byte = 0; BYTE second_byte = 0; int scanline = 0; int bits = 0; CImageIterator iter(this); for (BOOL bContinue = TRUE; bContinue; ) { hFile->Read(&status_byte, sizeof(BYTE), 1); switch (status_byte) { case RLE_COMMAND : hFile->Read(&status_byte, sizeof(BYTE), 1); switch (status_byte) { case RLE_ENDOFLINE : bits = 0; scanline++; break; case RLE_ENDOFBITMAP : bContinue=FALSE; break; case RLE_DELTA : { // read the delta values BYTE delta_x; BYTE delta_y; hFile->Read(&delta_x, sizeof(BYTE), 1); hFile->Read(&delta_y, sizeof(BYTE), 1); // apply them bits += delta_x; scanline += delta_y; break; } default : hFile->Read((void *)(iter.GetRow(scanline) + bits), sizeof(BYTE) * status_byte, 1); // align run length to even number of bytes if ((status_byte & 1) == 1) hFile->Read(&second_byte, sizeof(BYTE), 1); bits += status_byte; break; }; break; default : BYTE *sline = iter.GetRow(scanline); hFile->Read(&second_byte, sizeof(BYTE), 1); for (unsigned i = 0; i < status_byte; i++) { *(sline + bits) = second_byte; bits++; } break; }; } break; } default : throw "compression type not supported"; } } if (bTopDownDib) Flip(); //<Flanders> } catch (char *message) { strncpy(info.szLastError,message,255); return false; } return true; }
HX_RESULT CHXDIBits::GetDIBits(HDC hDC, HBITMAP hBM, UCHAR*& pBits, BITMAPINFOHEADER*& pHeader) { HX_RESULT hr = HXR_OK; WORD wBits = 0; DWORD dwLen = 0; BITMAP bm; BITMAPINFOHEADER bi; LPBITMAPINFOHEADER lpbi = NULL; pBits = NULL; pHeader = NULL; if (!hDC || !hBM) { hr = HXR_FAILED; goto cleanup; } GetObject(hBM, sizeof(bm), &bm); wBits = (WORD)(bm.bmPlanes * bm.bmBitsPixel); bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = bm.bmWidth; bi.biHeight = bm.bmHeight; bi.biPlanes = 1; bi.biBitCount = wBits; bi.biCompression = BI_RGB; bi.biSizeImage = WIDTHBYTES(bm.bmWidth * wBits) * bm.bmHeight; bi.biXPelsPerMeter = 0; bi.biYPelsPerMeter = 0; bi.biClrUsed = 0; bi.biClrImportant = 0; dwLen = bi.biSize + DibNumColors(&bi) * sizeof(RGBQUAD) + bi.biSizeImage; if (!m_hDIB) { m_hDIB = GlobalAlloc(GMEM_MOVEABLE, dwLen); } else if (m_hDIB && (GlobalSize(m_hDIB) != dwLen)) { GlobalFree(m_hDIB); m_hDIB = GlobalAlloc(GMEM_MOVEABLE, dwLen); } lpbi = (LPBITMAPINFOHEADER)GlobalLock(m_hDIB); if (!lpbi) { // This is bad, it's not clear how callers of this class can // really handle a failure case. So, we need to make sure that // all our callers do handle this correctly. HX_ASSERT(lpbi); hr = HXR_FAILED; goto cleanup; } *lpbi = bi; ::GetDIBits(hDC, hBM, 0, (WORD)bi.biHeight, DibPtr(lpbi), (LPBITMAPINFO)lpbi, DIB_RGB_COLORS); bi = *lpbi; lpbi->biClrUsed = DibNumColors(lpbi); pBits = (UCHAR*)DibPtr(lpbi); pHeader = lpbi; GlobalUnlock(m_hDIB); cleanup: return hr; }
HDC W32HandleDibDrv (PVPVOID vpbmi16) { HDC hdcMem = NULL; HBITMAP hbm = NULL; PVOID pvBits, pvIntelBits; STACKBMI32 bmi32; LPBITMAPINFO lpbmi32; DWORD dwClrUsed,nSize,nAlignmentSpace; PBITMAPINFOHEADER16 pbmi16; INT nbmiSize,nBytesWritten; HANDLE hfile=NULL,hsec=NULL; ULONG RetVal,OriginalSelLimit,SelectorLimit,OriginalFlags; PARM16 Parm16; CHAR pchTempFile[MAX_PATH]; BOOL bRet = FALSE; PVPVOID vpBase16 = (PVPVOID) ((ULONG) vpbmi16 & 0xffff0000); if ((hdcMem = W32FindAndLockDibInfo((USHORT)HIWORD(vpbmi16))) != (HDC)NULL) { return hdcMem; } // First create a memory device context compatible to // the app's current screen if ((hdcMem = CreateCompatibleDC (NULL)) == NULL) { LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv CreateCompatibleDC failed\n")); return NULL; } // Copy bmi16 to bmi32. DIB.DRV only supports DIB_RGB_COLORS lpbmi32 = CopyBMI16ToBMI32( vpbmi16, (LPBITMAPINFO)&bmi32, (WORD) DIB_RGB_COLORS); // this hack for Director 4.0 does essentially what WFW does // if this bitmap is 0 sized, just return an hDC for something simple if(bmi32.bmiHeader.biSizeImage == 0 && (CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_DIBDRVIMAGESIZEZERO)) { LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv:Zero biSizeImage, returning memory DC!\n")); return hdcMem; } try { // Copy the wholething into a temp file. First get a temp file name if ((nSize = GetTempPath (MAX_PATH, pchTempFile)) == 0 || nSize >= MAX_PATH) goto hdd_err; if (GetTempFileName (pchTempFile, "DIB", 0, pchTempFile) == 0) goto hdd_err; if ((hfile = CreateFile (pchTempFile, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, (FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE), NULL)) == INVALID_HANDLE_VALUE) { LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv CreateFile failed\n")); goto hdd_err; } // call back to get the size of the global object // associated with vpbmi16 Parm16.WndProc.wParam = HIWORD(vpbmi16); CallBack16(RET_GETDIBSIZE, &Parm16, 0, (PVPVOID)&SelectorLimit); Parm16.WndProc.wParam = HIWORD(vpbmi16); if (SelectorLimit == 0xffffffff || SelectorLimit == 0) { LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv Invalid Selector %x\n",HIWORD(vpbmi16))); goto hdd_err; } SelectorLimit++; OriginalSelLimit = SelectorLimit; CallBack16(RET_GETDIBFLAGS, &Parm16, 0, (PVPVOID)&OriginalFlags); if (OriginalFlags == 0x4) { //GA_DGROUP LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv GA_DGROUP Not Handled\n")); goto hdd_err; } GETVDMPTR(vpBase16, SelectorLimit, pbmi16); nbmiSize = GetBMI16Size(vpbmi16, (WORD) DIB_RGB_COLORS, &dwClrUsed); // Under NT CreateDIBSection will fail if the offset to the bits // is not dword aligned. So we may have to add some space at the top // of the section to get the offset correctly aligned. nAlignmentSpace = (nbmiSize+LOWORD(vpbmi16)) % 4; if (nAlignmentSpace) { if (WriteFile (hfile, pbmi16, nAlignmentSpace, &nBytesWritten, NULL) == FALSE || nBytesWritten != (INT) nAlignmentSpace) goto hdd_err; } // // detect a clinical case of bitedit screwing around dib.drv // // code below is using dib macros declared in wdib.h // namely: // DibNumColors - yields max number of colors in dib // DibColors - yields pointer to a dib color table // // Function W32CheckDibColorIndices checks to see if DIB color // table looks like a number (defined usually by biClrImportant) // of WORD indices in a sequential order (0, 1, 2, ...) // if this is the case, app is trying to use undocumented feature // of DIB.DRV that turns color matching off in this case. // Since we cannot enforce that rule, we approximate it by filling // color table by a number of known (and always same) entries // When blitting occurs, no color matching will be performed (when // both target and destination are of this very nature). // For no reason at all we fill color table with vga colors. // Sequential indices could have worked just as well. // // Modifications are made to memory pointed to by lpbmi32 if (W32CheckDibColorIndices((LPBITMAPINFOHEADER)lpbmi32)) { INT i, nColors; LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER)lpbmi32; LPRGBQUAD lprgbq = (LPRGBQUAD)DibColors(lpbmi); nColors = DibNumColors(lpbmi); lpbmi->biClrImportant = nColors; switch (lpbmi->biBitCount) { case 1: lprgbq[0] = rgbVGA[0]; lprgbq[1] = rgbVGA[0x0f]; break; case 4: RtlCopyMemory(lprgbq, rgbVGA, sizeof(rgbVGA)); break; case 8: RtlCopyMemory(lprgbq, rgbVGA, 8*sizeof(RGBQUAD)); RtlCopyMemory(lprgbq+248, rgbVGA+8, 8*sizeof(RGBQUAD)); RtlCopyMemory(lprgbq+8, rgb4, 2*sizeof(RGBQUAD)); RtlCopyMemory(lprgbq+246, rgb4+2, 2*sizeof(RGBQUAD)); for (i = 10; i < 246; ++i) { lprgbq[i].rgbBlue = i; lprgbq[i].rgbGreen= 0; lprgbq[i].rgbRed = 0; lprgbq[i].rgbReserved = 0; } break; default: // this should never happen break; } } if (WriteFile (hfile, pbmi16, SelectorLimit, &nBytesWritten, NULL) == FALSE || nBytesWritten != (INT) SelectorLimit) goto hdd_err; if (SelectorLimit < 64*1024) { if (SetFilePointer (hfile, 64*1024+nAlignmentSpace, NULL, FILE_BEGIN) == -1) goto hdd_err; if (SetEndOfFile (hfile) == FALSE) goto hdd_err; SelectorLimit = 64*1024; } if ((hsec = CreateFileMapping (hfile, NULL, PAGE_READWRITE | SEC_COMMIT, 0, SelectorLimit+nAlignmentSpace, NULL)) == NULL) { LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv CreateFileMapping Failed\n")); goto hdd_err; } // Now create the DIB section if ((hbm = CreateDIBSection (hdcMem, lpbmi32, DIB_RGB_COLORS, &pvBits, hsec, nAlignmentSpace + LOWORD(vpbmi16) + nbmiSize )) == NULL) { LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv CreateDibSection Failed\n")); goto hdd_err; } FREEVDMPTR(pbmi16); if((pvBits = MapViewOfFile(hsec, FILE_MAP_WRITE, 0, 0, SelectorLimit+nAlignmentSpace)) == NULL) { LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv MapViewOfFile Failed\n")); goto hdd_err; } pvBits = (PVOID) ((ULONG)pvBits + nAlignmentSpace); SelectObject (hdcMem, hbm); GdiSetBatchLimit(1); #ifndef i386 if (!NT_SUCCESS(VdmAddVirtualMemory((ULONG)pvBits, (ULONG)SelectorLimit, (PULONG)&pvIntelBits))) { LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv VdmAddVirtualMemory failed\n")); goto hdd_err; } // On risc platforms, the intel base + the intel linear address // of the DIB section is not equal to the DIB section's process // address. This is because of the VdmAddVirtualMemory call // above. So here we zap the correct address into the flataddress // array. if (!VdmAddDescriptorMapping(HIWORD(vpbmi16), (USHORT) ((SelectorLimit+65535)/65536), (ULONG) pvIntelBits, (ULONG) pvBits)) { LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv VdmAddDescriptorMapping failed\n")); goto hdd_err; } #else pvIntelBits = pvBits; #endif // Finally set the selectors to the new DIB Parm16.WndProc.wParam = HIWORD(vpbmi16); Parm16.WndProc.lParam = (LONG)pvIntelBits; Parm16.WndProc.wMsg = 0x10; // GA_NOCOMPACT Parm16.WndProc.hwnd = 1; // set so it's not randomly 0 CallBack16(RET_SETDIBSEL, &Parm16, 0, (PVPVOID)&RetVal); if (!RetVal) { LOGDEBUG(LOG_ALWAYS,("\nWOW::W32HandleDibDrv Callback set_sel_for_dib failed\n")); goto hdd_err; } // Store all the relevant information so that DeleteDC could // free all the resources later. if (W32AddDibInfo(hdcMem, hfile, hsec, nAlignmentSpace, pvBits, pvIntelBits, hbm, OriginalSelLimit, (USHORT)OriginalFlags, (USHORT)((HIWORD(vpbmi16)))) == FALSE) goto hdd_err; // Finally spit out the dump for debugging LOGDEBUG(6,("\t\tWOW::W32HandleDibDrv hdc=%04x nAlignment=%04x\n\t\tNewDib=%x OldDib=%04x:%04x DibSize=%x DibFlags=%x\n",hdcMem,nAlignmentSpace,pvBits,HIWORD(vpbmi16),LOWORD(vpbmi16),OriginalSelLimit,(USHORT)OriginalFlags)); bRet = TRUE; hdd_err:; } finally { if (!bRet) { if (hdcMem) { DeleteDC (hdcMem); hdcMem = NULL; } if (hfile) CloseHandle (hfile); if (hsec) CloseHandle (hsec); if (hbm) CloseHandle (hbm); } } return hdcMem; }