2 * DIB Engine conversion routines
3 * Converts DDB <--> DIB
5 * Copyright 2009 Massimo Del Fedele
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/port.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv
);
31 /***********************************************************************
32 * Creates DDB that is compatible with source hdc.
33 * hdc is the HDC on where the DIB MUST be selected in
34 * srcBmp is the source DIB
35 * startScan and scanLines specify the portion of DIB to convert
36 * in order to avoid unneeded conversion of large DIBs on blitting
38 * NOTE : the srcBmp DIB MUST NOT be selected in any DC */
39 HBITMAP
_DIBDRV_ConvertDIBtoDDB( HDC hdc
, HBITMAP srcBmp
, int startScan
, int scanLines
)
45 int dibWidth
, dibHeight
;
55 /* gets DIBSECTION data from source DIB */
56 if(GetObjectW(srcBmp
, sizeof(DIBSECTION
), &ds
) != sizeof(DIBSECTION
))
58 ERR("Couldn't get DIBSECTION data\n");
63 dibWidth
= ds
.dsBmih
.biWidth
;
64 dibHeight
= ds
.dsBmih
.biHeight
;
65 bits
= ds
.dsBm
.bmBits
;
66 stride
= ((dibWidth
* ds
.dsBmih
.biBitCount
+31) &~31) / 8;
68 /* adjust bits to point at needed starting stripe */
73 dibHeight
= -dibHeight
;
74 bits
= (BYTE
*)bits
+ startScan
* stride
;
79 bits
= (BYTE
*)bits
+ (dibHeight
- startScan
- scanLines
) * stride
;
82 /* if requested part is out of source bitmap, returns 0 */
83 if(startScan
>= dibHeight
)
85 if(startScan
+ scanLines
>= dibHeight
)
86 scanLines
= dibHeight
- startScan
;
88 /* gets the size of DIB palette and bitfields, if any */
91 if(ds
.dsBmih
.biCompression
== BI_BITFIELDS
)
93 else if(ds
.dsBmih
.biBitCount
<= 8)
95 colorUsed
= ds
.dsBmih
.biClrUsed
;
97 colorUsed
= 1 << ds
.dsBmih
.biBitCount
;
100 /* builds the needed BITMAPINFOHEADER */
101 bmi
= HeapAlloc( GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER
)+
102 sizeof(RGBQUAD
)*colorUsed
+ sizeof(DWORD
) * bitFields
);
105 ERR("HeapAlloc failed\n");
109 /* copy the header part */
110 memcpy( &bmi
->bmiHeader
, &ds
.dsBmih
, sizeof(BITMAPINFOHEADER
) );
112 /* gets the color table part, if any */
115 /* create a temporary DC, GetDIBColorTable() requests that
116 the DIB is selected in a DC.... */
117 if(!(tmpHdc
= CreateCompatibleDC(hdc
)))
119 ERR("Couldn't create the temporary HDC\n");
120 HeapFree(GetProcessHeap(), 0, bmi
);
123 /* selects the DIB into the temporary DC */
124 if( !(tmpBmp
= SelectObject(tmpHdc
, srcBmp
)))
126 ERR("Couldn't select source DIB into temporary DC\n");
128 HeapFree(GetProcessHeap(), 0, bmi
);
131 if(!GetDIBColorTable(tmpHdc
, 0, colorUsed
, bmi
->bmiColors
))
132 ERR("GetDIBColorTable failed\n");
133 SelectObject(tmpHdc
, tmpBmp
);
138 /* fill the bitfields part, if any */
140 memcpy(bmi
->bmiColors
, ds
.dsBitfields
, 3 * sizeof(DWORD
));
142 /* adjust dib size for SetDIBits, as it needs it to reverse top-down dibs
143 it must be set to the number of scanLines to transfer */
144 bmi
->bmiHeader
.biHeight
= topDown
? -scanLines
: scanLines
;
146 /* creates destination compatible bitmap */
147 tmpHdc
= GetDC(NULL
);
148 hBmp
= CreateCompatibleBitmap(tmpHdc
, dibWidth
, scanLines
);
149 ReleaseDC(NULL
, tmpHdc
);
152 ERR("CreateCompatibleBitmap failed\n");
153 HeapFree( GetProcessHeap(), 0, bmi
);
157 /* copies the requested scan lines from DIB to DDB */
158 /* FIXME : still no support for RLE packed DIBs */
159 res
= SetDIBits( hdc
, hBmp
, 0, scanLines
, bits
, bmi
, DIB_RGB_COLORS
);
160 HeapFree( GetProcessHeap(), 0, bmi
);
163 ERR("SetDIBits failed\n");
164 DeleteObject( hBmp
);
171 /***********************************************************************
172 * Creates DIB that is compatible with the target hdc.
173 * startScan and scanLines specify the portion of DDB to convert
174 * in order to avoid unneeded conversion of large DDBs on blitting
176 * NOTE : the srcBmp DDB MUST NOT be selected in any DC */
177 HBITMAP
_DIBDRV_ConvertDDBtoDIB( HDC hdc
, HBITMAP srcBmp
, int startScan
, int scanLines
)
184 if (!GetObjectW( srcBmp
, sizeof(bitmap
), &bitmap
))
186 ERR("Couldn't retrieve source bitmap\n");
190 if(startScan
+ scanLines
>= bitmap
.bmHeight
)
191 scanLines
= bitmap
.bmHeight
- startScan
;
193 bi
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
) /* + 256 * sizeof(RGBQUAD) */);
196 ERR("HeapAlloc failed\n");
200 bi
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
201 bi
->bmiHeader
.biWidth
= bitmap
.bmWidth
;
202 bi
->bmiHeader
.biHeight
= scanLines
;
203 bi
->bmiHeader
.biPlanes
= bitmap
.bmPlanes
;
204 bi
->bmiHeader
.biBitCount
= 32;
205 bi
->bmiHeader
.biCompression
= BI_RGB
;
206 bi
->bmiHeader
.biSizeImage
= 0;
208 /* No need to get the color table or the color masks
209 as we're requesting a 32 bit rgba DIB */
211 /* Create bitmap and fill in bits */
212 hBmp
= CreateDIBSection(hdc
, bi
, DIB_RGB_COLORS
, &bits
, NULL
, 0);
215 ERR("Failed to create DIB section\n");
216 HeapFree( GetProcessHeap(), 0, bi
);
221 if(!GetDIBits(hdc
, srcBmp
, startScan
, scanLines
, bits
, bi
, DIB_RGB_COLORS
))
223 ERR("GetDIBits failed\n");
224 DeleteObject( hBmp
);
225 HeapFree( GetProcessHeap(), 0, bi
);
231 ERR("CreateDibSection couldn't allocate DIB bits\n");
232 DeleteObject( hBmp
);
233 HeapFree( GetProcessHeap(), 0, bi
);
236 HeapFree( GetProcessHeap(), 0, bi
);
240 /***********************************************************************
241 * BITBLT_ConvertDevDDBtoDIB
243 * Creates DIB that is compatible with the target hdc for a device (non memory) source DC */
244 HBITMAP
_DIBDRV_ConvertDevDDBtoDIB( HDC hdcSrc
, HDC hdcDst
, int xSrc
, int ySrc
, int width
, int height
)
249 /* at first, we create a compatible DC and a bitmap with needed sizes */
250 memHDC
= CreateCompatibleDC(hdcSrc
);
253 ERR("CreateCompatibleDC failed\n");
256 bmp
= CreateCompatibleBitmap(hdcSrc
, width
, height
);
259 ERR("CreateCompatibleBitmap failed\n");
264 /* select the newly created DDB into the temporary DC */
265 bmp
= SelectObject(memHDC
, bmp
);
268 ERR("Failed selecting DDB into temporary DC\n");
274 /* next, we blit pixels from device to the compatible bitmap */
275 if(!BitBlt(memHDC
, 0, 0, width
, height
, hdcSrc
, xSrc
, ySrc
, SRCCOPY
))
277 ERR("BitBlt failed\n");
283 /* select out the DDB from the temporary DC */
284 bmp
= SelectObject(memHDC
, bmp
);
288 ERR("Failed selecting DDB out temporary DC\n");
293 /*now we can convert the bitmap to a DIB */
294 dib
= _DIBDRV_ConvertDDBtoDIB( hdcDst
, bmp
, 0, height
);
296 FIXME("ConvertDDBtoDIB failed\n");
298 /* free resources and return the created dib */