Beispiel #1
0
//--------------------------------------------------------------------------//
//--------------------------------------------------------------------------//
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);
		}
	}
}
Beispiel #2
0
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;
}
Beispiel #3
0
HGLOBAL CPng::PNGToDIB(png_structp png_ptr, png_infop info_ptr)
{
	//Read the image
	png_read_info(png_ptr, info_ptr);

	int nBitDepth = 0;
	int nColorType = 0;
	png_uint_32 width = 0;
	png_uint_32 height = 0;
	png_get_IHDR(png_ptr, info_ptr, &width, &height, &nBitDepth, &nColorType, NULL, NULL, NULL);

	IMAGE img;
	img.width = (LONG)width;
	img.height = (LONG)height;

	//Determine the type of format
	if (nColorType==PNG_COLOR_TYPE_RGB || nColorType==PNG_COLOR_TYPE_RGB_ALPHA)
	{
		img.pixdepth = 24;		// nBitDepth 8, 16
		img.palnum   = 0;
	}
	else
	{
		switch(nBitDepth) // bit depths 1, 2, 4, 8, 16
		{	
			case 2:  
				img.pixdepth = 4;		
				break;
			case 16: 
				img.pixdepth = 8;		
				break;
			default: 
				img.pixdepth = nBitDepth;
		}

		img.palnum = 1 << img.pixdepth;
	}

	//Allocate the image struct that will be used to transport file info
	if (!AllocImageStruct(&img))
	{
		longjmp(png_ptr->jmpbuf, 1);
	}

	//Not sure if we can take advantage of this info in a BMP, thus remove it.
	if (nColorType & PNG_COLOR_MASK_ALPHA)
		png_set_strip_alpha(png_ptr);

	//Set user transform function to deal with a Bitdepth of 2
	if (nBitDepth == 2)
	{
		png_set_user_transform_info(png_ptr, NULL, 4, 1);
		png_set_read_user_transform_fn(png_ptr, ConvertTo4BitsPerPix);
	}

	//Tell libpng to strip 16 bit/color files down to 8 bits/color
	if (nBitDepth == 16) 
		png_set_strip_16(png_ptr);

	if (nColorType==PNG_COLOR_TYPE_RGB || nColorType==PNG_COLOR_TYPE_RGB_ALPHA)
	{
		png_set_bgr(png_ptr);
	}

	png_read_update_info(png_ptr, info_ptr);

	//If palette, get it and fill our img struct
	if (img.palnum > 0)
	{
		if (nColorType == PNG_COLOR_TYPE_PALETTE)
		{
			png_colorp palette;
			int num_palette;
			png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
			if (num_palette > (int)img.palnum) 
				num_palette = img.palnum;

			memset(img.palette, 0, img.palnum * sizeof(png_color));
			memcpy(img.palette, palette, num_palette * sizeof(png_color));
		}
		else
		{
			int depth = (nBitDepth == 16)? 8 : nBitDepth ;
			png_build_grayscale_palette(depth, img.palette);
		}
	}

	png_read_image(png_ptr, img.rowptr);

	png_infop end_info = NULL;
	png_read_end(png_ptr, end_info);

	// Alloc the buffer to be big enough to hold all the bits
	DWORD dwLen = (DWORD)sizeof(BITMAPINFOHEADER) + (img.palnum * sizeof(RGBQUAD)) + img.imgbytes;

	// Allocate enough memory to hold the entire DIB
	HGLOBAL hMemory = ::GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, dwLen);
	if (!hMemory)
		return NULL;

	//Begin filling out DIB info
	BITMAPINFOHEADER* pDib = (BITMAPINFOHEADER*)::GlobalLock(hMemory);
	if (!pDib)
	{
		::GlobalFree(hMemory);
		return NULL;
	}

	::ZeroMemory(pDib, dwLen);
	pDib->biSize			= sizeof(BITMAPINFOHEADER);
	pDib->biWidth			= (DWORD)img.width; 
	pDib->biHeight			= (DWORD)img.height; 
	pDib->biPlanes			= 1;
	pDib->biCompression		= BI_RGB;
	pDib->biXPelsPerMeter	= 3937; // 100 pixels/inch
	pDib->biYPelsPerMeter	= 3937;
	pDib->biSizeImage		= img.imgbytes;
	pDib->biBitCount		= img.pixdepth; 
	pDib->biClrUsed			= img.palnum;

	if (pDib->biBitCount >= 16)
		pDib->biBitCount = 24;	

	if (pDib->biClrUsed)
	{
		RGBQUAD* pRgb = DibColors(pDib);
		BYTE rgbq[RGBQUAD_SIZE];
		PALETTE* pal;
		UINT nIndex;
		memset(rgbq, 0, sizeof(rgbq));
		for (pal = img.palette, nIndex = img.palnum ; nIndex > 0 ; nIndex--, pal++)
		{
			rgbq[RGBQ_RED]			= pal->red;
			rgbq[RGBQ_GREEN]		= pal->green;
			rgbq[RGBQ_BLUE]			= pal->blue;
			rgbq[RGBQ_RESERVED]		= 0;
			memcpy((LPVOID)pRgb, rgbq, sizeof(RGBQUAD));
			pRgb++;
		}
	}

	memcpy(DibPtr(pDib), img.bmpbits, DibSizeImage(pDib));

	FreeImageStruct(&img);

	::GlobalUnlock(hMemory);
	return hMemory;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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;
}