⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dibobj.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
  RGBQUAD *lpRGB;

  DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
	bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
	bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");

  effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
  bm.bmType = 0;
  bm.bmWidth = bi->biWidth;
  bm.bmHeight = effHeight;
  bm.bmWidthBytes = ovr_pitch ? ovr_pitch : (ULONG) DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);

  bm.bmPlanes = bi->biPlanes;
  bm.bmBitsPixel = bi->biBitCount;
  bm.bmBits = NULL;

  // Get storage location for DIB bits.  Only use biSizeImage if it's valid and
  // we're dealing with a compressed bitmap.  Otherwise, use width * height.
  totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
    ? bi->biSizeImage : (ULONG) (bm.bmWidthBytes * effHeight);

  if (section)
  {
/*    bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS,
			      0L, offset, totalSize); */
    DbgPrint("DIB_CreateDIBSection: Cannot yet handle section DIBs\n");
    SetLastWin32Error(ERROR_CALL_NOT_IMPLEMENTED);
    return 0;
  }
  else if (ovr_pitch && offset)
    bm.bmBits = (LPVOID) offset;
  else {
    offset = 0;
    bm.bmBits = EngAllocUserMem(totalSize, 0);
  }

  if(usage == DIB_PAL_COLORS)
    lpRGB = DIB_MapPaletteColors(dc, bmi);
  else
    lpRGB = bmi->bmiColors;

  // Allocate Memory for DIB and fill structure
  if (bm.bmBits)
  {
    dib = ExAllocatePoolWithTag(PagedPool, sizeof(DIBSECTION), TAG_DIB);
    if (dib != NULL) RtlZeroMemory(dib, sizeof(DIBSECTION));
  }

  if (dib)
  {
    dib->dsBm = bm;
    dib->dsBmih = *bi;
    dib->dsBmih.biSizeImage = totalSize;

    /* Set dsBitfields values */
    if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
    {
      dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
    }
    else switch(bi->biBitCount)
    {
      case 16:
        dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)lpRGB : 0x7c00;
        dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 1) : 0x03e0;
        dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 2) : 0x001f;        break;

      case 24:
        dib->dsBitfields[0] = 0xff0000;
        dib->dsBitfields[1] = 0x00ff00;
        dib->dsBitfields[2] = 0x0000ff;
        break;

      case 32:
        dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)lpRGB : 0xff0000;
        dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 1) : 0x00ff00;
        dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 2) : 0x0000ff;
        break;
    }
    dib->dshSection = section;
    dib->dsOffset = offset;
  }

  // Create Device Dependent Bitmap and add DIB pointer
  if (dib)
  {
    Size.cx = bm.bmWidth;
    Size.cy = abs(bm.bmHeight);
    res = IntCreateBitmap(Size, bm.bmWidthBytes,
                          BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
                          BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
                          (bi->biHeight < 0 ? BMF_TOPDOWN : 0),
                          bm.bmBits);
    if (! res)
      {
        if (lpRGB != bmi->bmiColors)
          {
            ExFreePool(lpRGB);
          }
        SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
	return NULL;
      }
    bmp = BITMAPOBJ_LockBitmap(res);
    if (NULL == bmp)
      {
        if (lpRGB != bmi->bmiColors)
          {
            ExFreePool(lpRGB);
          }
	SetLastWin32Error(ERROR_INVALID_HANDLE);
	NtGdiDeleteObject(bmp);
	return NULL;
      }
    bmp->dib = (DIBSECTION *) dib;
    bmp->flFlags = BITMAPOBJ_IS_APIBITMAP;

    /* WINE NOTE: WINE makes use of a colormap, which is a color translation table between the DIB and the X physical
                  device. Obviously, this is left out of the ReactOS implementation. Instead, we call
                  NtGdiSetDIBColorTable. */
    if(bi->biBitCount == 1) { Entries = 2; } else
    if(bi->biBitCount == 4) { Entries = 16; } else
    if(bi->biBitCount == 8) { Entries = 256; }

    if (Entries)
      bmp->hDIBPalette = PALETTE_AllocPaletteIndexedRGB(Entries, lpRGB);
    else
      bmp->hDIBPalette = PALETTE_AllocPalette(PAL_BITFIELDS, 0, NULL,
                                              dib->dsBitfields[0],
                                              dib->dsBitfields[1],
                                              dib->dsBitfields[2]);
  }

  // Clean up in case of errors
  if (!res || !bmp || !dib || !bm.bmBits)
  {
    DPRINT("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n", res, bmp, dib, bm.bmBits);
/*      if (bm.bmBits)
      {
      if (section)
        UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL;
      else if (!offset)
      VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
    } */

    if (dib) { ExFreePool(dib); dib = NULL; }
    if (bmp) { bmp = NULL; }
    if (res) { BITMAPOBJ_FreeBitmap(res); res = 0; }
  }

  if (lpRGB != bmi->bmiColors)
    {
      ExFreePool(lpRGB);
    }

  if (bmp)
    {
      BITMAPOBJ_UnlockBitmap(bmp);
    }

  // Return BITMAP handle and storage location
  if (NULL != bm.bmBits && NULL != bits)
    {
      *bits = bm.bmBits;
    }

  return res;
}

/***********************************************************************
 *           DIB_GetDIBWidthBytes
 *
 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
 * 11/16/1999 (RJJ) lifted from wine
 */
INT FASTCALL DIB_GetDIBWidthBytes (INT width, INT depth)
{
  return ((width * depth + 31) & ~31) >> 3;
}

/***********************************************************************
 *           DIB_GetDIBImageBytes
 *
 * Return the number of bytes used to hold the image in a DIB bitmap.
 * 11/16/1999 (RJJ) lifted from wine
 */

INT STDCALL DIB_GetDIBImageBytes (INT  width, INT height, INT depth)
{
  return DIB_GetDIBWidthBytes( width, depth ) * (height < 0 ? -height : height);
}

/***********************************************************************
 *           DIB_BitmapInfoSize
 *
 * Return the size of the bitmap info structure including color table.
 * 11/16/1999 (RJJ) lifted from wine
 */

INT FASTCALL DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse)
{
  int colors;

  if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
  {
    BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
    colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
    return sizeof(BITMAPCOREHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
  }
  else  /* assume BITMAPINFOHEADER */
  {
    colors = info->bmiHeader.biClrUsed;
    if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount;
    return sizeof(BITMAPINFOHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
  }
}

/*
 * DIB_GetBitmapInfo is complete copy of wine cvs 2/9-2006 
 * from file dib.c from gdi32.dll or orginal version
 * did not calc the info right for some headers.  
 */

INT STDCALL 
DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, 
				  PLONG width, 
				  PLONG height, 
				  PWORD planes, 
				  PWORD bpp, 
				  PLONG compr, 
				  PLONG size )
{  

  if (header->biSize == sizeof(BITMAPCOREHEADER))
  {
     BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
     *width  = core->bcWidth;
     *height = core->bcHeight;
     *planes = core->bcPlanes;
     *bpp    = core->bcBitCount;
     *compr  = 0;
     *size   = 0;
     return 0;
  }

  if (header->biSize == sizeof(BITMAPINFOHEADER))
  {
     *width  = header->biWidth;
     *height = header->biHeight;
     *planes = header->biPlanes;
     *bpp    = header->biBitCount;
     *compr  = header->biCompression;
     *size   = header->biSizeImage;
     return 1;
  }

  if (header->biSize == sizeof(BITMAPV4HEADER))
  {
      BITMAPV4HEADER *v4hdr = (BITMAPV4HEADER *)header;
      *width  = v4hdr->bV4Width;
      *height = v4hdr->bV4Height;
      *planes = v4hdr->bV4Planes;
      *bpp    = v4hdr->bV4BitCount;
      *compr  = v4hdr->bV4V4Compression;
      *size   = v4hdr->bV4SizeImage;
      return 4;
  }

  if (header->biSize == sizeof(BITMAPV5HEADER))
  {
      BITMAPV5HEADER *v5hdr = (BITMAPV5HEADER *)header;
      *width  = v5hdr->bV5Width;
      *height = v5hdr->bV5Height;
      *planes = v5hdr->bV5Planes;
      *bpp    = v5hdr->bV5BitCount;
      *compr  = v5hdr->bV5Compression;
      *size   = v5hdr->bV5SizeImage;
      return 5;
  }
  DPRINT("(%ld): wrong size for header\n", header->biSize );
  return -1;
}

// Converts a Device Independent Bitmap (DIB) to a Device Dependant Bitmap (DDB)
// The specified Device Context (DC) defines what the DIB should be converted to
PBITMAPOBJ FASTCALL DIBtoDDB(HGLOBAL hPackedDIB, HDC hdc) // FIXME: This should be removed. All references to this function should
						 // change to NtGdiSetDIBits
{
  HBITMAP hBmp = 0;
  PBITMAPOBJ pBmp = NULL;
  DIBSECTION *dib;
  LPBYTE pbits = NULL;

  // Get a pointer to the packed DIB's data
  // pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
  dib = hPackedDIB;

  pbits = (LPBYTE)(dib + DIB_BitmapInfoSize((BITMAPINFO*)&dib->dsBmih, DIB_RGB_COLORS));

  // Create a DDB from the DIB
  hBmp = NtGdiCreateDIBitmap ( hdc, &dib->dsBmih, CBM_INIT,
    (LPVOID)pbits, (BITMAPINFO*)&dib->dsBmih, DIB_RGB_COLORS);

  // GlobalUnlock(hPackedDIB);

  // Retrieve the internal Pixmap from the DDB
  pBmp = BITMAPOBJ_LockBitmap(hBmp);

  return pBmp;
}

RGBQUAD * FASTCALL
DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi)
{
  RGBQUAD *lpRGB;
  ULONG nNumColors,i;
  USHORT *lpIndex;
  PPALGDI palGDI;

  palGDI = PALETTE_LockPalette(dc->w.hPalette);

  if (NULL == palGDI)
    {
//      RELEASEDCINFO(hDC);
      return NULL;
    }

  if (palGDI->Mode != PAL_INDEXED)
    {
      PALETTE_UnlockPalette(palGDI);
      palGDI = PALETTE_LockPalette(dc->PalIndexed);
      if (palGDI->Mode != PAL_INDEXED)
        {
          return NULL;
        }
    }

  nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
  if (lpbmi->bmiHeader.biClrUsed)
    {
      nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
    }

  lpRGB = (RGBQUAD *)ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD) * nNumColors, TAG_COLORMAP);
  if (lpRGB == NULL)
  {
     PALETTE_UnlockPalette(palGDI);
     return NULL;   
  }
  
  lpIndex = (USHORT *)&lpbmi->bmiColors[0];

  for (i = 0; i < nNumColors; i++)
    {
      lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
      lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
      lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
      lpIndex++;
    }
//    RELEASEDCINFO(hDC);
  PALETTE_UnlockPalette(palGDI);

  return lpRGB;
}

HPALETTE FASTCALL
BuildDIBPalette (CONST BITMAPINFO *bmi, PINT paletteType)
{
  BYTE bits;
  ULONG ColorCount;
  PALETTEENTRY *palEntries = NULL;
  HPALETTE hPal;
  ULONG RedMask, GreenMask, BlueMask;

  // Determine Bits Per Pixel
  bits = bmi->bmiHeader.biBitCount;

  // Determine paletteType from Bits Per Pixel
  if (bits <= 8)
    {
      *paletteType = PAL_INDEXED;
      RedMask = GreenMask = BlueMask = 0;
    }
  else if(bits < 24)
    {
      *paletteType = PAL_BITFIELDS;
      RedMask = 0xf800;
      GreenMask = 0x07e0;
      BlueMask = 0x001f;
    }
  else
    {
      *paletteType = PAL_BGR;
      RedMask = 0xff0000;
      GreenMask = 0x00ff00;
      BlueMask = 0x0000ff;
    }

  if (bmi->bmiHeader.biClrUsed == 0)
    {
      ColorCount = 1 << bmi->bmiHeader.biBitCount;
    }
  else
    {
      ColorCount = bmi->bmiHeader.biClrUsed;
    }

  if (PAL_INDEXED == *paletteType)
    {
      hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)bmi->bmiColors);
    }
  else
    {
      hPal = PALETTE_AllocPalette(*paletteType, ColorCount,
                                  (ULONG*) palEntries,
                                  RedMask, GreenMask, BlueMask );
    }

  return hPal;
}

/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -