[1/19] gdiplus: added GdipBitmapLockBits [try2]
Evan Stade
estade at gmail.com
Tue Aug 7 20:41:55 CDT 2007
Hi,
[try2] made the changes Julliard suggested
changelog:
*added GdipBitmapLockBits, GdipBitmapUnlockBits
*added a bunch of types
dlls/gdiplus/gdiplus.spec | 4 +
dlls/gdiplus/gdiplus_private.h | 3 +
dlls/gdiplus/image.c | 141 ++++++++++++++++++++++++++++++++++++++++
include/gdiplusflat.h | 2 +
include/gdiplusgpstubs.h | 1
include/gdiplusimaging.h | 31 +++++++++
include/gdiplustypes.h | 17 +++++
7 files changed, 197 insertions(+), 2 deletions(-)
--
Evan Stade
-------------- next part --------------
diff --git a/dlls/gdiplus/gdiplus.spec b/dlls/gdiplus/gdiplus.spec
index e0ea275..7e53322 100644
--- a/dlls/gdiplus/gdiplus.spec
+++ b/dlls/gdiplus/gdiplus.spec
@@ -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
diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index cea667f..79440a2 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -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{
diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c
index c050fd2..59690c5 100644
--- a/dlls/gdiplus/image.c
+++ b/dlls/gdiplus/image.c
@@ -88,6 +88,147 @@ GpStatus WINGDIPAPI GdipBitmapGetPixel(G
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)
{
diff --git a/include/gdiplusflat.h b/include/gdiplusflat.h
index 8c96a2c..3035f0d 100644
--- a/include/gdiplusflat.h
+++ b/include/gdiplusflat.h
@@ -164,6 +164,8 @@ GpStatus WINGDIPAPI GdipCreateCustomLine
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**);
diff --git a/include/gdiplusgpstubs.h b/include/gdiplusgpstubs.h
index 772edd9..423cd9e 100644
--- a/include/gdiplusgpstubs.h
+++ b/include/gdiplusgpstubs.h
@@ -67,5 +67,6 @@ typedef DashStyle GpDashStyle;
typedef MatrixOrder GpMatrixOrder;
typedef Point GpPoint;
typedef WrapMode GpWrapMode;
+typedef Rect GpRect;
#endif
diff --git a/include/gdiplusimaging.h b/include/gdiplusimaging.h
index c76aba5..28fe28b 100644
--- a/include/gdiplusimaging.h
+++ b/include/gdiplusimaging.h
@@ -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 */
diff --git a/include/gdiplustypes.h b/include/gdiplustypes.h
index c316073..96112ea 100644
--- a/include/gdiplustypes.h
+++ b/include/gdiplustypes.h
@@ -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 */
--
1.4.1
More information about the wine-patches
mailing list