gdiplus: Added GdipBitmapLockBits.

This commit is contained in:
Evan Stade 2007-08-07 18:41:55 -07:00 committed by Alexandre Julliard
parent 5fb1c16276
commit 7a9a30d95c
7 changed files with 197 additions and 2 deletions

View File

@ -41,10 +41,10 @@
@ stub GdipBitmapGetHistogram
@ stub GdipBitmapGetHistogramSize
@ stdcall GdipBitmapGetPixel(ptr long long ptr)
@ stub GdipBitmapLockBits
@ stdcall GdipBitmapLockBits(ptr ptr long long ptr)
@ stub GdipBitmapSetPixel
@ stub GdipBitmapSetResolution
@ stub GdipBitmapUnlockBits
@ stdcall GdipBitmapUnlockBits(ptr ptr)
@ stub GdipClearPathMarkers
@ stub GdipCloneBitmapArea
@ stub GdipCloneBitmapAreaI

View File

@ -143,6 +143,9 @@ struct GpBitmap{
INT width;
INT height;
PixelFormat format;
ImageLockMode lockmode;
INT numlocks;
BYTE *bitmapbits; /* pointer to the buffer we passed in BitmapLockBits */
};
struct GpImageAttributes{

View File

@ -88,6 +88,147 @@ GpStatus WINGDIPAPI GdipBitmapGetPixel(GpBitmap* bitmap, INT x, INT y,
return NotImplemented;
}
/* This function returns a pointer to an array of pixels that represents the
* bitmap. The *entire* bitmap is locked according to the lock mode specified by
* flags. It is correct behavior that a user who calls this function with write
* privileges can write to the whole bitmap (not just the area in rect).
*
* FIXME: only used portion of format is bits per pixel. */
GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect,
UINT flags, PixelFormat format, BitmapData* lockeddata)
{
BOOL bm_is_selected;
INT stride, bitspp = PIXELFORMATBPP(format);
OLE_HANDLE hbm;
HDC hdc;
HBITMAP old = NULL;
BITMAPINFO bmi;
BYTE *buff = NULL;
UINT abs_height;
TRACE("%p %p %d %d %p\n", bitmap, rect, flags, format, lockeddata);
if(!lockeddata || !bitmap || !rect)
return InvalidParameter;
if(rect->X < 0 || rect->Y < 0 || (rect->X + rect->Width > bitmap->width) ||
(rect->Y + rect->Height > bitmap->height) || !flags)
return InvalidParameter;
if(flags & ImageLockModeUserInputBuf)
return NotImplemented;
if((bitmap->lockmode & ImageLockModeWrite) || (bitmap->lockmode &&
(flags & ImageLockModeWrite)))
return WrongState;
IPicture_get_Handle(bitmap->image.picture, &hbm);
IPicture_get_CurDC(bitmap->image.picture, &hdc);
bm_is_selected = (hdc != 0);
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biBitCount = 0;
if(!bm_is_selected){
hdc = GetDC(0);
old = SelectObject(hdc, (HBITMAP)hbm);
}
/* fill out bmi */
GetDIBits(hdc, (HBITMAP)hbm, 0, 0, NULL, &bmi, DIB_RGB_COLORS);
abs_height = abs(bmi.bmiHeader.biHeight);
stride = bmi.bmiHeader.biWidth * bitspp / 8;
stride = (stride + 3) & ~3;
buff = GdipAlloc(stride * abs_height);
if(!buff) return OutOfMemory;
bmi.bmiHeader.biBitCount = bitspp;
GetDIBits(hdc, (HBITMAP)hbm, 0, abs_height, buff, &bmi, DIB_RGB_COLORS);
if(!bm_is_selected){
SelectObject(hdc, old);
ReleaseDC(0, hdc);
}
lockeddata->Width = rect->Width;
lockeddata->Height = rect->Height;
lockeddata->PixelFormat = format;
lockeddata->Reserved = flags;
if(bmi.bmiHeader.biHeight > 0){
lockeddata->Stride = -stride;
lockeddata->Scan0 = buff + (bitspp / 8) * rect->X +
stride * (abs_height - 1 - rect->Y);
}
else{
lockeddata->Stride = stride;
lockeddata->Scan0 = buff + (bitspp / 8) * rect->X + stride * rect->Y;
}
bitmap->lockmode = flags;
bitmap->numlocks++;
if(flags & ImageLockModeWrite)
bitmap->bitmapbits = buff;
return Ok;
}
GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap* bitmap,
BitmapData* lockeddata)
{
OLE_HANDLE hbm;
HDC hdc;
HBITMAP old = NULL;
BOOL bm_is_selected;
BITMAPINFO bmi;
if(!bitmap || !lockeddata)
return InvalidParameter;
if(!bitmap->lockmode)
return WrongState;
if(lockeddata->Reserved & ImageLockModeUserInputBuf)
return NotImplemented;
if(lockeddata->Reserved & ImageLockModeRead){
if(!(--bitmap->numlocks))
bitmap->lockmode = 0;
GdipFree(lockeddata->Scan0);
return Ok;
}
IPicture_get_Handle(bitmap->image.picture, &hbm);
IPicture_get_CurDC(bitmap->image.picture, &hdc);
bm_is_selected = (hdc != 0);
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biBitCount = 0;
if(!bm_is_selected){
hdc = GetDC(0);
old = SelectObject(hdc, (HBITMAP)hbm);
}
GetDIBits(hdc, (HBITMAP)hbm, 0, 0, NULL, &bmi, DIB_RGB_COLORS);
bmi.bmiHeader.biBitCount = PIXELFORMATBPP(lockeddata->PixelFormat);
SetDIBits(hdc, (HBITMAP)hbm, 0, abs(bmi.bmiHeader.biHeight),
bitmap->bitmapbits, &bmi, DIB_RGB_COLORS);
if(!bm_is_selected){
SelectObject(hdc, old);
ReleaseDC(0, hdc);
}
GdipFree(bitmap->bitmapbits);
return Ok;
}
GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
PixelFormat format, BYTE* scan0, GpBitmap** bitmap)
{

View File

@ -164,6 +164,8 @@ GpStatus WINGDIPAPI GdipCreateCustomLineCap(GpPath*,GpPath*,GpLineCap,REAL,
GpStatus WINGDIPAPI GdipDeleteCustomLineCap(GpCustomLineCap*);
GpStatus WINGDIPAPI GdipBitmapGetPixel(GpBitmap*,INT,INT,ARGB*);
GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap*,GDIPCONST GpRect*,UINT,
PixelFormat,BitmapData*);
GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT,INT,INT,PixelFormat,BYTE*,
GpBitmap**);
GpStatus WINGDIPAPI GdipCreateBitmapFromStream(IStream*,GpBitmap**);

View File

@ -67,5 +67,6 @@ typedef DashStyle GpDashStyle;
typedef MatrixOrder GpMatrixOrder;
typedef Point GpPoint;
typedef WrapMode GpWrapMode;
typedef Rect GpRect;
#endif

View File

@ -19,6 +19,13 @@
#ifndef _GDIPLUSIMAGING_H
#define _GDIPLUSIMAGING_H
enum ImageLockMode
{
ImageLockModeRead = 1,
ImageLockModeWrite = 2,
ImageLockModeUserInputBuf = 4
};
#ifdef __cplusplus
class EncoderParameter
{
@ -35,8 +42,22 @@ public:
UINT Count;
EncoderParameter Parameter[1];
};
class BitmapData
{
public:
UINT Width;
UINT Height;
INT Stride;
PixelFormat PixelFormat;
VOID* Scan0;
UINT_PTR Reserved;
};
#else /* end of c++ typedefs */
typedef enum ImageLockMode ImageLockMode;
typedef struct EncoderParameter
{
GUID Guid;
@ -51,6 +72,16 @@ typedef struct EncoderParameters
EncoderParameter Parameter[1];
} EncoderParameters;
typedef struct BitmapData
{
UINT Width;
UINT Height;
INT Stride;
PixelFormat PixelFormat;
VOID* Scan0;
UINT_PTR Reserved; /* undocumented: stores the lock mode */
}BitmapData;
#endif /* end of c typedefs */
#endif /* _GDIPLUSIMAGING_H */

View File

@ -177,6 +177,15 @@ public:
REAL Height;
};
class Rect
{
public:
INT X;
INT Y;
INT Width;
INT Height;
};
#else /* end of c++ typedefs */
typedef struct Point
@ -206,6 +215,14 @@ typedef struct RectF
REAL Height;
} RectF;
typedef struct Rect
{
INT X;
INT Y;
INT Width;
INT Height;
} Rect;
typedef enum Status Status;
#endif /* end of c typedefs */