Evan Stade : gdiplus: Added GdipBitmapLockBits.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Aug 8 08:59:38 CDT 2007


Module: wine
Branch: master
Commit: 7a9a30d95c5b26bc93ce1698098d85cd488b4f53
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=7a9a30d95c5b26bc93ce1698098d85cd488b4f53

Author: Evan Stade <estade at gmail.com>
Date:   Tue Aug  7 18:41:55 2007 -0700

gdiplus: Added GdipBitmapLockBits.

---

 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(-)

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(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)
 {
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 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**);
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 */




More information about the wine-cvs mailing list