--- mstools/samples/mandel/loadbmp.c 2018/08/09 18:20:41 1.1 +++ mstools/samples/mandel/loadbmp.c 2018/08/09 18:21:38 1.1.1.2 @@ -18,6 +18,62 @@ * #include "jtypes.h" * \**************************************************************************/ +/**************************************************************************\ +* +* +* Summary: In Win32, saving or loading a bitmap in DIB format is basically +* the same as in Win16. However, care must be taken in DWORD +* alignment, especially on the MIPS platform. +* +* SYMPTOMS Exception on loading or saving a bitmap on the MIPS platform. +* In NTSD, get the error message of "data mis-alignment." +* +* CAUSE Passed a Non-DWORD aligned actual parameter to, say, GetDIBits(). +* +* STATUS/RESOLUTION +* +* The DIB file format contains the BITMAPFILEHEADER then followed +* immediately by the BITMAPINFOHEADER. Notice that the BITMAPFILEHEADER is +* not DWORD aligned. Thus, the structure that follows it, the +* BITMAPINFOHEADER is not on a DWORD boundary. If a pointer to this DWORD +* mis-aligned structure is passed to the 6th argument of GetDIBits(), an +* exception will occur. +* +* The remedy is to copy the data in the structure over to a DWORD +* aligned memory and passes the pointer to the latter structure to the +* function instead. See below for detail. +* +* +* ========================================================================= +* +* +* Summary: When saving a bitmap in DIB format in file, the GDI function is +* used to retrieve the bitmap information. Though the general use +* of this function and the technics for saving a bitmap in DIB +* format are largely unchanged, this article provide more details +* in the use of the Win32 version of the GetDIBits() api. +* +* +* The function can be used to retrieve the following information: +* 1. Just retrieving the data in the BitmapInfoHeader, no color table and +* no bits. +* +* 2. Retrieving the data in the BitmapInfoHeader and the color table. +* +* 3. Retrieving all the data, BitmapInfoHeader, color table and the bits. +* +* The 5th and the 6th parameters of the function are used to tell the +* graphics engine what exactly the appllication wants it to return. If the +* 5th parameteris NULL, then no bits will be returned. If the biBitCount +* is 0 in the 6th parameter, then no color table will be returned. In +* addition, the biSize field of the BitmapInfoHeader must be set to either +* the size of BitmapInfoHeader or BitmapCoreHeader for the function to work. +* See the following for details. +* +* +* +\**************************************************************************/ +//#define STRICT #include #include "jtypes.h" @@ -47,6 +103,12 @@ BOOL LoadBitmapFile(HDC hDC, PINFO pInfo LPBITMAPINFO pbmi; PBYTE pjTmp; ULONG sizBMI; + INT iNumClr; +#ifdef LATER + RGBQUAD *pRGBQuad; + RGBTRIPLE *pRGBTriple; + INT iEntry, i; +#endif bSuccess = TRUE; @@ -86,21 +148,55 @@ BOOL LoadBitmapFile(HDC hDC, PINFO pInfo goto ErrExit3; } - pbmh = (LPBITMAPINFOHEADER)((PBYTE)pMapFile + sizeof(BITMAPFILEHEADER)); - +#ifndef LATER // - // Use the size to determine if it is a BitmapCoreHeader or - // BitmapInfoHeader + // The file header doesn't end on DWORD boundary... // - if (pbmh->biSize == sizeof(BITMAPCOREHEADER)) - { - sizBMI = sizeof(BITMAPCOREHEADER)+sizeof(RGBTRIPLE)* - ((((LPBITMAPCOREHEADER)pbmh)->bcBitCount == 24) ? 0 : (1 << ((LPBITMAPCOREHEADER)pbmh)->bcBitCount)); - } - else // BITMAPINFOHEADER + pbmh = (LPBITMAPINFOHEADER)((PBYTE)pMapFile + sizeof(BITMAPFILEHEADER)); + { - sizBMI = sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)* - ((pbmh->biBitCount == 24) ? 0 : (1 << pbmh->biBitCount)); + BITMAPCOREHEADER bmch, *pbmch; + BITMAPINFOHEADER bmih, *pbmih; + PBYTE pjTmp; + ULONG ulSiz; + + pbmch = &bmch; + pbmih = &bmih; + + pjTmp = (PBYTE)pbmh; + ulSiz = sizeof(BITMAPCOREHEADER); + while (ulSiz--) { + *(((PBYTE)pbmch)++) = *(((PBYTE)pjTmp)++); + } + + pjTmp = (PBYTE)pbmh; + ulSiz = sizeof(BITMAPINFOHEADER); + while (ulSiz--) { + *(((PBYTE)pbmih)++) = *(((PBYTE)pjTmp)++); + } + + // + // Use the size to determine if it is a BitmapCoreHeader or + // BitmapInfoHeader + // + if (bmch.bcSize == sizeof(BITMAPCOREHEADER)) + { + WORD wBitCount; + + wBitCount = bmch.bcBitCount; + iNumClr = ((wBitCount == 24) ? 0 : (1 << wBitCount)); + sizBMI = sizeof(BITMAPCOREHEADER)+sizeof(RGBTRIPLE)*iNumClr; + } + else // BITMAPINFOHEADER + { + WORD wBitCount; + + wBitCount = bmih.biBitCount; + iNumClr = ((wBitCount == 24) ? 0 : (1 << wBitCount)); + sizBMI = sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*iNumClr; + } + + } if ((pbmi = (LPBITMAPINFO) LocalAlloc(LMEM_FIXED,sizBMI)) == NULL) { @@ -113,6 +209,7 @@ BOOL LoadBitmapFile(HDC hDC, PINFO pInfo // Make sure we pass in a DWORD aligned BitmapInfo to CreateDIBitmap // Otherwise, exception on the MIPS platform // CR!!! Equivalent to memcpy + // WARNING! This is not handling the RGBTRIPLE case correctly // pjTmp = (PBYTE)pbmi; @@ -120,9 +217,66 @@ BOOL LoadBitmapFile(HDC hDC, PINFO pInfo { *(((PBYTE)pjTmp)++) = *(((PBYTE)pbmh)++); } +#else + pbmh = (LPBITMAPINFOHEADER)((PBYTE)pMapFile + sizeof(BITMAPFILEHEADER)); + + if (pbmh->biSize == sizeof(BITMAPCOREHEADER)) + { + + DebugBreak(); + + iEntry = ((((LPBITMAPCOREHEADER)pbmh)->bcBitCount == 24) + ? 0 + : (1 << ((LPBITMAPCOREHEADER)pbmh)->bcBitCount)); + + sizBMI = sizeof(BITMAPCOREHEADER)+sizeof(RGBQUAD)*iEntry; + + if ((pbmi = (LPBITMAPINFO) LocalAlloc(LMEM_FIXED,sizBMI)) == NULL) { + MessageBox(ghwndMain, "Fail in Memory Allocation!", "Error", MB_OK); + bSuccess = FALSE; + goto ErrExit3; + } + + pjTmp = (PBYTE)pbmi; + + sizBMI = sizeof(BITMAPCOREHEADER); + while(sizBMI--) + { + *(((PBYTE)pjTmp)++) = *(((PBYTE)pbmh)++); + } + + ((PBYTE)pjTmp)--; + ((PBYTE)pbmh)--; + + pRGBQuad = (RGBQUAD *)pbmh; + pRGBTriple = (RGBTRIPLE *)pjTmp; + + for (i=0; i < iEntry; i++, pRGBTriple++, pRGBQuad++) + { + pRGBQuad->rgbBlue = pRGBTriple->rgbtBlue; + pRGBQuad->rgbGreen = pRGBTriple->rgbtGreen; + pRGBQuad->rgbRed = pRGBTriple->rgbtRed; + pRGBQuad->rgbReserved = 0x0; + } + + + } + else // BITMAPINFOHEADER + { + sizBMI = sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)* + ((pbmh->biBitCount == 24) ? 0 : (1 << pbmh->biBitCount)); + + while(sizBMI--) + { + *(((PBYTE)pjTmp)++) = *(((PBYTE)pbmh)++); + } + + } +#endif pMapFile = (PBYTE)pMapFile + ((BITMAPFILEHEADER *)pMapFile)->bfOffBits; + if ((pInfo->hBmpSaved = CreateDIBitmap(hDC, (LPBITMAPINFOHEADER)pbmi, CBM_INIT, pMapFile, pbmi, DIB_RGB_COLORS)) == NULL) { ErrorOut("Fail in creating DIB bitmap from file!");