static void *get_pixel_ptr( const BITMAPINFO *info, void *bits, int x, int y ) { const int width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight; const int bpp = info->bmiHeader.biBitCount; if (height > 0) return (char *)bits + (height - y - 1) * get_dib_stride( width, bpp ) + x * bpp / 8; else return (char *)bits + y * get_dib_stride( width, bpp ) + x * bpp / 8; }
/*********************************************************************** * GetBitmapBits [GDI32.@] * * Copies bitmap bits of bitmap to buffer. * * RETURNS * Success: Number of bytes copied * Failure: 0 */ LONG WINAPI GetBitmapBits( HBITMAP hbitmap, /* [in] Handle to bitmap */ LONG count, /* [in] Number of bytes to copy */ LPVOID bits) /* [out] Pointer to buffer to receive bits */ { char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; BITMAPINFO *info = (BITMAPINFO *)buffer; struct gdi_image_bits src_bits; struct bitblt_coords src; int dst_stride, max, ret; BITMAPOBJ *bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ); if (!bmp) return 0; dst_stride = get_bitmap_stride( bmp->dib.dsBm.bmWidth, bmp->dib.dsBm.bmBitsPixel ); ret = max = dst_stride * bmp->dib.dsBm.bmHeight; if (!bits) goto done; if (count > max) count = max; ret = count; src.visrect.left = 0; src.visrect.right = bmp->dib.dsBm.bmWidth; src.visrect.top = 0; src.visrect.bottom = (count + dst_stride - 1) / dst_stride; src.x = src.y = 0; src.width = src.visrect.right - src.visrect.left; src.height = src.visrect.bottom - src.visrect.top; if (!get_image_from_bitmap( bmp, info, &src_bits, &src )) { const char *src_ptr = src_bits.ptr; int src_stride = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount ); /* GetBitmapBits returns 16-bit aligned data */ if (info->bmiHeader.biHeight > 0) { src_ptr += (info->bmiHeader.biHeight - 1) * src_stride; src_stride = -src_stride; } src_ptr += src.visrect.top * src_stride; if (src_stride == dst_stride) memcpy( bits, src_ptr, count ); else while (count > 0) { memcpy( bits, src_ptr, min( count, dst_stride ) ); src_ptr += src_stride; bits = (char *)bits + dst_stride; count -= dst_stride; } if (src_bits.free) src_bits.free( &src_bits ); } else ret = 0; done: GDI_ReleaseObj( hbitmap ); return ret; }
/*********************************************************************** * create_surface_image * * Caller must hold the surface lock. On input, *rect is the requested * image rect, relative to the window whole_rect, a.k.a. visible_rect. * On output, it's been intersected with that part backed by the surface * and is the actual size of the returned image. copy_data indicates if * the caller will keep the returned image beyond the point where the * surface bits can be guaranteed to remain valid and unchanged. If so, * the bits are copied instead of merely referenced by the image. * * IMPORTANT: This function is called from non-Wine threads, so it * must not use Win32 or Wine functions, including debug * logging. */ CGImageRef create_surface_image(void *window_surface, CGRect *rect, int copy_data) { CGImageRef cgimage = NULL; struct macdrv_window_surface *surface = get_mac_surface(window_surface); int width, height; width = surface->header.rect.right - surface->header.rect.left; height = surface->header.rect.bottom - surface->header.rect.top; *rect = CGRectIntersection(cgrect_from_rect(surface->header.rect), *rect); if (!CGRectIsEmpty(*rect)) { CGRect visrect; CGColorSpaceRef colorspace; CGDataProviderRef provider; int bytes_per_row, offset, size; CGImageAlphaInfo alphaInfo; visrect = CGRectOffset(*rect, -surface->header.rect.left, -surface->header.rect.top); colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); bytes_per_row = get_dib_stride(width, 32); offset = CGRectGetMinX(visrect) * 4 + (height - CGRectGetMaxY(visrect)) * bytes_per_row; size = min(CGRectGetHeight(visrect) * bytes_per_row, surface->info.bmiHeader.biSizeImage - offset); if (copy_data) { CFDataRef data = CFDataCreate(NULL, (UInt8*)surface->bits + offset, size); provider = CGDataProviderCreateWithCFData(data); CFRelease(data); } else provider = CGDataProviderCreateWithData(NULL, surface->bits + offset, size, NULL); alphaInfo = surface->use_alpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst; cgimage = CGImageCreate(CGRectGetWidth(visrect), CGRectGetHeight(visrect), 8, 32, bytes_per_row, colorspace, alphaInfo | kCGBitmapByteOrder32Little, provider, NULL, FALSE, kCGRenderingIntentDefault); CGDataProviderRelease(provider); CGColorSpaceRelease(colorspace); } return cgimage; }
BOOL init_dib_info_from_bitmapobj(dib_info *dib, BITMAPOBJ *bmp) { if (!is_bitmapobj_dib( bmp )) { BITMAPINFO info; get_ddb_bitmapinfo( bmp, &info ); if (!bmp->dib.dsBm.bmBits) { int width_bytes = get_dib_stride( bmp->dib.dsBm.bmWidth, bmp->dib.dsBm.bmBitsPixel ); bmp->dib.dsBm.bmBits = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, bmp->dib.dsBm.bmHeight * width_bytes ); if (!bmp->dib.dsBm.bmBits) return FALSE; } init_dib_info_from_bitmapinfo( dib, &info, bmp->dib.dsBm.bmBits ); } else init_dib_info( dib, &bmp->dib.dsBmih, bmp->dib.dsBitfields, bmp->color_table, bmp->dib.dsBm.bmBits ); return TRUE; }
BOOL nulldrv_CopyBitmap( HBITMAP src, HBITMAP dst ) { BOOL ret = TRUE; BITMAPOBJ *src_bmp = GDI_GetObjPtr( src, OBJ_BITMAP ); if (!src_bmp) return FALSE; if (src_bmp->bitmap.bmBits) { BITMAPOBJ *dst_bmp = GDI_GetObjPtr( dst, OBJ_BITMAP ); int stride = get_dib_stride( dst_bmp->bitmap.bmWidth, dst_bmp->bitmap.bmBitsPixel ); dst_bmp->bitmap.bmBits = HeapAlloc( GetProcessHeap(), 0, dst_bmp->bitmap.bmHeight * stride ); if (dst_bmp->bitmap.bmBits) memcpy( dst_bmp->bitmap.bmBits, src_bmp->bitmap.bmBits, dst_bmp->bitmap.bmHeight * stride ); else ret = FALSE; GDI_ReleaseObj( dst ); } GDI_ReleaseObj( src ); return ret; }
BOOL init_dib_info_from_bitmapobj(dib_info *dib, BITMAPOBJ *bmp, enum dib_info_flags flags) { if (!bmp->dib) { char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; BITMAPINFO *info = (BITMAPINFO *)buffer; get_ddb_bitmapinfo( bmp, info ); if (!bmp->bitmap.bmBits) { int width_bytes = get_dib_stride( bmp->bitmap.bmWidth, bmp->bitmap.bmBitsPixel ); bmp->bitmap.bmBits = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, bmp->bitmap.bmHeight * width_bytes ); if (!bmp->bitmap.bmBits) return FALSE; } return init_dib_info_from_bitmapinfo( dib, info, bmp->bitmap.bmBits, flags | private_color_table ); } return init_dib_info( dib, &bmp->dib->dsBmih, bmp->dib->dsBitfields, bmp->color_table, bmp->nb_colors, bmp->dib->dsBm.bmBits, flags ); }
/****************************************************************************** * SetBitmapBits [GDI32.@] * * Sets bits of color data for a bitmap. * * RETURNS * Success: Number of bytes used in setting the bitmap bits * Failure: 0 */ LONG WINAPI SetBitmapBits( HBITMAP hbitmap, /* [in] Handle to bitmap */ LONG count, /* [in] Number of bytes in bitmap array */ LPCVOID bits) /* [in] Address of array with bitmap bits */ { char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; BITMAPINFO *info = (BITMAPINFO *)buffer; BITMAPOBJ *bmp; DWORD err; int i, src_stride, dst_stride; struct bitblt_coords src, dst; struct gdi_image_bits src_bits; HRGN clip = NULL; if (!bits) return 0; bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ); if (!bmp) return 0; if (count < 0) { WARN("(%d): Negative number of bytes passed???\n", count ); count = -count; } src_stride = get_bitmap_stride( bmp->dib.dsBm.bmWidth, bmp->dib.dsBm.bmBitsPixel ); count = min( count, src_stride * bmp->dib.dsBm.bmHeight ); dst_stride = get_dib_stride( bmp->dib.dsBm.bmWidth, bmp->dib.dsBm.bmBitsPixel ); src.visrect.left = src.x = 0; src.visrect.top = src.y = 0; src.visrect.right = src.width = bmp->dib.dsBm.bmWidth; src.visrect.bottom = src.height = (count + src_stride - 1 ) / src_stride; dst = src; if (count % src_stride) { HRGN last_row; int extra_pixels = ((count % src_stride) << 3) / bmp->dib.dsBm.bmBitsPixel; if ((count % src_stride << 3) % bmp->dib.dsBm.bmBitsPixel) FIXME( "Unhandled partial pixel\n" ); clip = CreateRectRgn( src.visrect.left, src.visrect.top, src.visrect.right, src.visrect.bottom - 1 ); last_row = CreateRectRgn( src.visrect.left, src.visrect.bottom - 1, src.visrect.left + extra_pixels, src.visrect.bottom ); CombineRgn( clip, clip, last_row, RGN_OR ); DeleteObject( last_row ); } TRACE("(%p, %d, %p) %dx%d %d bpp fetched height: %d\n", hbitmap, count, bits, bmp->dib.dsBm.bmWidth, bmp->dib.dsBm.bmHeight, bmp->dib.dsBm.bmBitsPixel, src.height ); if (src_stride == dst_stride) { src_bits.ptr = (void *)bits; src_bits.is_copy = FALSE; src_bits.free = NULL; } else { if (!(src_bits.ptr = HeapAlloc( GetProcessHeap(), 0, dst.height * dst_stride ))) { GDI_ReleaseObj( hbitmap ); return 0; } src_bits.is_copy = TRUE; src_bits.free = free_heap_bits; for (i = 0; i < count / src_stride; i++) memcpy( (char *)src_bits.ptr + i * dst_stride, (char *)bits + i * src_stride, src_stride ); if (count % src_stride) memcpy( (char *)src_bits.ptr + i * dst_stride, (char *)bits + i * src_stride, count % src_stride ); } /* query the color info */ info->bmiHeader.biSize = sizeof(info->bmiHeader); info->bmiHeader.biPlanes = 1; info->bmiHeader.biBitCount = bmp->dib.dsBm.bmBitsPixel; info->bmiHeader.biCompression = BI_RGB; info->bmiHeader.biXPelsPerMeter = 0; info->bmiHeader.biYPelsPerMeter = 0; info->bmiHeader.biClrUsed = 0; info->bmiHeader.biClrImportant = 0; info->bmiHeader.biWidth = 0; info->bmiHeader.biHeight = 0; info->bmiHeader.biSizeImage = 0; err = put_image_into_bitmap( bmp, 0, info, NULL, NULL, NULL ); if (!err || err == ERROR_BAD_FORMAT) { info->bmiHeader.biWidth = bmp->dib.dsBm.bmWidth; info->bmiHeader.biHeight = -dst.height; info->bmiHeader.biSizeImage = dst.height * dst_stride; err = put_image_into_bitmap( bmp, clip, info, &src_bits, &src, &dst ); } if (err) count = 0; if (clip) DeleteObject( clip ); if (src_bits.free) src_bits.free( &src_bits ); GDI_ReleaseObj( hbitmap ); return count; }
INT16 MFDRV_CreateBrushIndirect(PHYSDEV dev, HBRUSH hBrush ) { DWORD size; METARECORD *mr; LOGBRUSH logbrush; BOOL r; if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return -1; switch(logbrush.lbStyle) { case BS_SOLID: case BS_NULL: case BS_HATCHED: { LOGBRUSH16 lb16; lb16.lbStyle = logbrush.lbStyle; lb16.lbColor = logbrush.lbColor; lb16.lbHatch = logbrush.lbHatch; size = sizeof(METARECORD) + sizeof(LOGBRUSH16) - 2; mr = HeapAlloc( GetProcessHeap(), 0, size ); mr->rdSize = size / 2; mr->rdFunction = META_CREATEBRUSHINDIRECT; memcpy( mr->rdParm, &lb16, sizeof(LOGBRUSH16)); break; } case BS_PATTERN: { char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; BITMAPINFO *dst_info, *src_info = (BITMAPINFO *)buffer; struct gdi_image_bits bits; COLORREF cref; if (!get_bitmap_image( (HANDLE)logbrush.lbHatch, src_info, &bits )) goto done; if (src_info->bmiHeader.biBitCount != 1) { FIXME("Trying to store a colour pattern brush\n"); if (bits.free) bits.free( &bits ); goto done; } size = FIELD_OFFSET( METARECORD, rdParm[2] ) + FIELD_OFFSET( BITMAPINFO, bmiColors[2] ) + src_info->bmiHeader.biSizeImage; if (!(mr = HeapAlloc( GetProcessHeap(), 0, size ))) { if (bits.free) bits.free( &bits ); goto done; } mr->rdFunction = META_DIBCREATEPATTERNBRUSH; mr->rdSize = size / 2; mr->rdParm[0] = BS_PATTERN; mr->rdParm[1] = DIB_RGB_COLORS; dst_info = (BITMAPINFO *)(mr->rdParm + 2); dst_info->bmiHeader = src_info->bmiHeader; dst_info->bmiHeader.biClrUsed = 0; cref = GetTextColor( dev->hdc ); dst_info->bmiColors[0].rgbRed = GetRValue(cref); dst_info->bmiColors[0].rgbGreen = GetGValue(cref); dst_info->bmiColors[0].rgbBlue = GetBValue(cref); dst_info->bmiColors[0].rgbReserved = 0; cref = GetBkColor( dev->hdc ); dst_info->bmiColors[1].rgbRed = GetRValue(cref); dst_info->bmiColors[1].rgbGreen = GetGValue(cref); dst_info->bmiColors[1].rgbBlue = GetBValue(cref); dst_info->bmiColors[1].rgbReserved = 0; /* always return a bottom-up DIB */ if (dst_info->bmiHeader.biHeight < 0) { int i, width_bytes = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount ); char *dst_ptr = (char *)&dst_info->bmiColors[2]; dst_info->bmiHeader.biHeight = -dst_info->bmiHeader.biHeight; dst_ptr += (dst_info->bmiHeader.biHeight - 1) * width_bytes; for (i = 0; i < dst_info->bmiHeader.biHeight; i++, dst_ptr -= width_bytes) memcpy( dst_ptr, (char *)bits.ptr + i * width_bytes, width_bytes ); } else memcpy( &dst_info->bmiColors[2], bits.ptr, dst_info->bmiHeader.biSizeImage ); if (bits.free) bits.free( &bits ); break; } case BS_DIBPATTERN: { BITMAPINFO *info; DWORD bmSize, biSize; info = GlobalLock( (HGLOBAL)logbrush.lbHatch ); if (info->bmiHeader.biCompression) bmSize = info->bmiHeader.biSizeImage; else bmSize = get_dib_image_size( info ); biSize = bitmap_info_size(info, LOWORD(logbrush.lbColor)); size = sizeof(METARECORD) + biSize + bmSize + 2; mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); if (!mr) { GlobalUnlock( (HGLOBAL)logbrush.lbHatch ); goto done; } mr->rdFunction = META_DIBCREATEPATTERNBRUSH; mr->rdSize = size / 2; *(mr->rdParm) = logbrush.lbStyle; *(mr->rdParm + 1) = LOWORD(logbrush.lbColor); memcpy(mr->rdParm + 2, info, biSize + bmSize); GlobalUnlock( (HGLOBAL)logbrush.lbHatch ); break; } default: FIXME("Unkonwn brush style %x\n", logbrush.lbStyle); return 0; } r = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2); HeapFree(GetProcessHeap(), 0, mr); if( !r ) return -1; done: return MFDRV_AddHandle( dev, hBrush ); }
BOOL EMFDRV_StretchBlt( PHYSDEV devDst, struct bitblt_coords *dst, PHYSDEV devSrc, struct bitblt_coords *src, DWORD rop ) { BOOL ret; PEMRBITBLT pEMR; UINT emrSize; UINT bmiSize; UINT bitsSize; UINT size; BITMAP BM; WORD nBPP = 0; LPBITMAPINFOHEADER lpBmiH; HBITMAP hBitmap = NULL; DWORD emrType; if (devSrc->funcs == devDst->funcs) return FALSE; /* can't use a metafile DC as source */ if (src->log_width == dst->log_width && src->log_height == dst->log_height) { emrType = EMR_BITBLT; emrSize = sizeof(EMRBITBLT); } else { emrType = EMR_STRETCHBLT; emrSize = sizeof(EMRSTRETCHBLT); } hBitmap = GetCurrentObject(devSrc->hdc, OBJ_BITMAP); if(sizeof(BITMAP) != GetObjectW(hBitmap, sizeof(BITMAP), &BM)) return FALSE; nBPP = BM.bmPlanes * BM.bmBitsPixel; if(nBPP > 8) nBPP = 24; /* FIXME Can't get 16bpp to work for some reason */ bitsSize = get_dib_stride( BM.bmWidth, nBPP ) * BM.bmHeight; bmiSize = sizeof(BITMAPINFOHEADER) + (nBPP <= 8 ? 1 << nBPP : 0) * sizeof(RGBQUAD); size = emrSize + bmiSize + bitsSize; pEMR = HeapAlloc(GetProcessHeap(), 0, size); if (!pEMR) return FALSE; /* Initialize EMR */ pEMR->emr.iType = emrType; pEMR->emr.nSize = size; pEMR->rclBounds.left = dst->log_x; pEMR->rclBounds.top = dst->log_y; pEMR->rclBounds.right = dst->log_x + dst->log_width - 1; pEMR->rclBounds.bottom = dst->log_y + dst->log_height - 1; pEMR->xDest = dst->log_x; pEMR->yDest = dst->log_y; pEMR->cxDest = dst->log_width; pEMR->cyDest = dst->log_height; pEMR->dwRop = rop; pEMR->xSrc = src->log_x; pEMR->ySrc = src->log_y; GetTransform(devSrc->hdc, 0x204, &pEMR->xformSrc); pEMR->crBkColorSrc = GetBkColor(devSrc->hdc); pEMR->iUsageSrc = DIB_RGB_COLORS; pEMR->offBmiSrc = emrSize; pEMR->offBitsSrc = emrSize + bmiSize; pEMR->cbBmiSrc = bmiSize; pEMR->cbBitsSrc = bitsSize; if (emrType == EMR_STRETCHBLT) { PEMRSTRETCHBLT pEMRStretch = (PEMRSTRETCHBLT)pEMR; pEMRStretch->cxSrc = src->log_width; pEMRStretch->cySrc = src->log_height; } /* Initialize BITMAPINFO structure */ lpBmiH = (LPBITMAPINFOHEADER)((BYTE*)pEMR + pEMR->offBmiSrc); lpBmiH->biSize = sizeof(BITMAPINFOHEADER); lpBmiH->biWidth = BM.bmWidth; lpBmiH->biHeight = BM.bmHeight; lpBmiH->biPlanes = BM.bmPlanes; lpBmiH->biBitCount = nBPP; /* Assume the bitmap isn't compressed and set the BI_RGB flag. */ lpBmiH->biCompression = BI_RGB; lpBmiH->biSizeImage = bitsSize; lpBmiH->biYPelsPerMeter = 0; lpBmiH->biXPelsPerMeter = 0; lpBmiH->biClrUsed = nBPP <= 8 ? 1 << nBPP : 0; /* Set biClrImportant to 0, indicating that all of the device colors are important. */ lpBmiH->biClrImportant = 0; /* Initialize bitmap bits */ if (GetDIBits(devSrc->hdc, hBitmap, 0, (UINT)lpBmiH->biHeight, (BYTE*)pEMR + pEMR->offBitsSrc, (LPBITMAPINFO)lpBmiH, DIB_RGB_COLORS)) { ret = EMFDRV_WriteRecord(devDst, (EMR*)pEMR); if (ret) EMFDRV_UpdateBBox(devDst, &(pEMR->rclBounds)); } else ret = FALSE; HeapFree( GetProcessHeap(), 0, pEMR); return ret; }
static inline int get_dib_image_size(const BITMAPINFO *info) { return get_dib_stride(info->bmiHeader.biWidth, info->bmiHeader.biBitCount) * abs(info->bmiHeader.biHeight); }
INT16 MFDRV_CreateBrushIndirect(PHYSDEV dev, HBRUSH hBrush ) { DWORD size; METARECORD *mr; LOGBRUSH logbrush; BOOL r; if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return -1; switch(logbrush.lbStyle) { case BS_SOLID: case BS_NULL: case BS_HATCHED: { LOGBRUSH16 lb16; lb16.lbStyle = logbrush.lbStyle; lb16.lbColor = logbrush.lbColor; lb16.lbHatch = logbrush.lbHatch; size = sizeof(METARECORD) + sizeof(LOGBRUSH16) - 2; mr = HeapAlloc( GetProcessHeap(), 0, size ); mr->rdSize = size / 2; mr->rdFunction = META_CREATEBRUSHINDIRECT; memcpy( mr->rdParm, &lb16, sizeof(LOGBRUSH16)); break; } case BS_PATTERN: case BS_DIBPATTERN: { char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; BITMAPINFO *dst_info, *src_info = (BITMAPINFO *)buffer; DWORD info_size; char *dst_ptr; void *bits; UINT usage; if (!get_brush_bitmap_info( hBrush, src_info, &bits, &usage )) goto done; info_size = get_dib_info_size( src_info, usage ); size = FIELD_OFFSET( METARECORD, rdParm[2] ) + info_size + src_info->bmiHeader.biSizeImage; if (!(mr = HeapAlloc( GetProcessHeap(), 0, size ))) goto done; mr->rdFunction = META_DIBCREATEPATTERNBRUSH; mr->rdSize = size / 2; mr->rdParm[0] = logbrush.lbStyle; mr->rdParm[1] = usage; dst_info = (BITMAPINFO *)(mr->rdParm + 2); memcpy( dst_info, src_info, info_size ); if (dst_info->bmiHeader.biClrUsed == 1 << dst_info->bmiHeader.biBitCount) dst_info->bmiHeader.biClrUsed = 0; dst_ptr = (char *)dst_info + info_size; /* always return a bottom-up DIB */ if (dst_info->bmiHeader.biHeight < 0) { int i, width_bytes = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount ); dst_info->bmiHeader.biHeight = -dst_info->bmiHeader.biHeight; dst_ptr += (dst_info->bmiHeader.biHeight - 1) * width_bytes; for (i = 0; i < dst_info->bmiHeader.biHeight; i++, dst_ptr -= width_bytes) memcpy( dst_ptr, (char *)bits + i * width_bytes, width_bytes ); } else memcpy( dst_ptr, bits, src_info->bmiHeader.biSizeImage ); break; } default: FIXME("Unkonwn brush style %x\n", logbrush.lbStyle); return 0; } r = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2); HeapFree(GetProcessHeap(), 0, mr); if( !r ) return -1; done: return MFDRV_AddHandle( dev, hBrush ); }
BOOL init_dib_info(dib_info *dib, const BITMAPINFOHEADER *bi, const DWORD *bit_fields, RGBQUAD *color_table, int color_table_size, void *bits, enum dib_info_flags flags) { dib->bit_count = bi->biBitCount; dib->width = bi->biWidth; dib->height = bi->biHeight; dib->stride = get_dib_stride( dib->width, dib->bit_count ); dib->bits.ptr = bits; dib->bits.is_copy = FALSE; dib->bits.free = NULL; dib->bits.param = NULL; dib->flags = flags; if(dib->height < 0) /* top-down */ { dib->height = -dib->height; } else /* bottom-up */ { /* bits always points to the top-left corner and the stride is -ve */ dib->bits.ptr = (BYTE*)dib->bits.ptr + (dib->height - 1) * dib->stride; dib->stride = -dib->stride; } dib->funcs = &funcs_null; switch(dib->bit_count) { case 32: if(bi->biCompression == BI_RGB) bit_fields = bit_fields_888; init_bit_fields(dib, bit_fields); if(dib->red_mask == 0xff0000 && dib->green_mask == 0x00ff00 && dib->blue_mask == 0x0000ff) dib->funcs = &funcs_8888; else dib->funcs = &funcs_32; break; case 24: dib->funcs = &funcs_24; break; case 16: if(bi->biCompression == BI_RGB) bit_fields = bit_fields_555; init_bit_fields(dib, bit_fields); if(dib->red_mask == 0x7c00 && dib->green_mask == 0x03e0 && dib->blue_mask == 0x001f) dib->funcs = &funcs_555; else dib->funcs = &funcs_16; break; case 8: dib->funcs = &funcs_8; break; case 4: dib->funcs = &funcs_4; break; case 1: dib->funcs = &funcs_1; break; default: TRACE("bpp %d not supported, will forward to graphics driver.\n", dib->bit_count); return FALSE; } if(color_table) { if (flags & private_color_table) { dib->color_table = HeapAlloc(GetProcessHeap(), 0, color_table_size * sizeof(dib->color_table[0])); if(!dib->color_table) return FALSE; memcpy(dib->color_table, color_table, color_table_size * sizeof(color_table[0])); } else dib->color_table = color_table; dib->color_table_size = color_table_size; } else { dib->color_table = NULL; dib->color_table_size = 0; } return TRUE; }
static void init_dib_info(dib_info *dib, const BITMAPINFOHEADER *bi, const DWORD *bit_fields, const RGBQUAD *color_table, void *bits) { dib->bit_count = bi->biBitCount; dib->width = bi->biWidth; dib->height = bi->biHeight; dib->rect.left = 0; dib->rect.top = 0; dib->rect.right = bi->biWidth; dib->rect.bottom = abs( bi->biHeight ); dib->compression = bi->biCompression; dib->stride = get_dib_stride( dib->width, dib->bit_count ); dib->bits.ptr = bits; dib->bits.is_copy = FALSE; dib->bits.free = NULL; dib->bits.param = NULL; if(dib->height < 0) /* top-down */ { dib->height = -dib->height; } else /* bottom-up */ { /* bits always points to the top-left corner and the stride is -ve */ dib->bits.ptr = (BYTE*)dib->bits.ptr + (dib->height - 1) * dib->stride; dib->stride = -dib->stride; } dib->funcs = &funcs_null; switch(dib->bit_count) { case 32: if(bi->biCompression == BI_RGB) bit_fields = bit_fields_888; init_bit_fields(dib, bit_fields); if(dib->red_mask == 0xff0000 && dib->green_mask == 0x00ff00 && dib->blue_mask == 0x0000ff) dib->funcs = &funcs_8888; else dib->funcs = &funcs_32; break; case 24: dib->funcs = &funcs_24; break; case 16: if(bi->biCompression == BI_RGB) bit_fields = bit_fields_555; init_bit_fields(dib, bit_fields); if(dib->red_mask == 0x7c00 && dib->green_mask == 0x03e0 && dib->blue_mask == 0x001f) dib->funcs = &funcs_555; else dib->funcs = &funcs_16; break; case 8: dib->funcs = &funcs_8; break; case 4: dib->funcs = &funcs_4; break; case 1: dib->funcs = &funcs_1; break; } if (color_table && bi->biClrUsed) { dib->color_table = color_table; dib->color_table_size = bi->biClrUsed; } else { dib->color_table = NULL; dib->color_table_size = 0; } }