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
;
54 DIBDRVBITMAP
*physBitmap
;
56 /* gets DIBSECTION data from source DIB */
57 if(GetObjectW(srcBmp
, sizeof(DIBSECTION
), &ds
) != sizeof(DIBSECTION
))
59 ERR("Couldn't get DIBSECTION data\n");
64 dibWidth
= ds
.dsBmih
.biWidth
;
65 dibHeight
= ds
.dsBmih
.biHeight
;
66 bits
= ds
.dsBm
.bmBits
;
67 stride
= ((dibWidth
* ds
.dsBmih
.biBitCount
+31) &~31) / 8;
69 /* get physical bitmap -- needed for topdown flag */
70 if( (physBitmap
= _BITMAPLIST_Get(srcBmp
)) == NULL
)
72 ERR("Couldn't retrieve physical bitmap\n");
75 topDown
= physBitmap
->topdown
;
77 /* adjust bits to point at needed starting stripe */
80 bits
= (BYTE
*)bits
+ startScan
* stride
;
82 bits
= (BYTE
*)bits
+ (dibHeight
- startScan
- scanLines
) * stride
;
84 /* if requested part is out of source bitmap, returns 0 */
85 if(startScan
>= dibHeight
)
87 if(startScan
+ scanLines
>= dibHeight
)
88 scanLines
= dibHeight
- startScan
;
90 /* gets the size of DIB palette and bitfields, if any */
93 if(ds
.dsBmih
.biCompression
== BI_BITFIELDS
)
95 else if(ds
.dsBmih
.biBitCount
<= 8)
97 colorUsed
= ds
.dsBmih
.biClrUsed
;
99 colorUsed
= 1 << ds
.dsBmih
.biBitCount
;
102 /* builds the needed BITMAPINFOHEADER */
103 bmi
= HeapAlloc( GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER
)+
104 sizeof(RGBQUAD
)*colorUsed
+ sizeof(DWORD
) * bitFields
);
107 ERR("HeapAlloc failed\n");
111 /* copy the header part */
112 memcpy( &bmi
->bmiHeader
, &ds
.dsBmih
, sizeof(BITMAPINFOHEADER
) );
114 /* gets the color table part, if any */
117 /* create a temporary DC, GetDIBColorTable() requests that
118 the DIB is selected in a DC.... */
119 if(!(tmpHdc
= CreateCompatibleDC(hdc
)))
121 ERR("Couldn't create the temporary HDC\n");
122 HeapFree(GetProcessHeap(), 0, bmi
);
125 /* selects the DIB into the temporary DC */
126 if( !(tmpBmp
= SelectObject(tmpHdc
, srcBmp
)))
128 ERR("Couldn't select source DIB into temporary DC\n");
130 HeapFree(GetProcessHeap(), 0, bmi
);
133 if(!GetDIBColorTable(tmpHdc
, 0, colorUsed
, bmi
->bmiColors
))
134 ERR("GetDIBColorTable failed\n");
135 SelectObject(tmpHdc
, tmpBmp
);
140 /* fill the bitfields part, if any */
142 memcpy(bmi
->bmiColors
, ds
.dsBitfields
, 3 * sizeof(DWORD
));
144 /* adjust dib size for SetDIBits, as it needs it to reverse top-down dibs
145 it must be set to the number of scanLines to transfer */
146 bmi
->bmiHeader
.biHeight
= topDown
? -scanLines
: scanLines
;
148 /* creates destination compatible bitmap */
149 tmpHdc
= GetDC(NULL
);
150 hBmp
= CreateCompatibleBitmap(tmpHdc
, dibWidth
, scanLines
);
151 ReleaseDC(NULL
, tmpHdc
);
154 ERR("CreateCompatibleBitmap failed\n");
155 HeapFree( GetProcessHeap(), 0, bmi
);
159 /* copies the requested scan lines from DIB to DDB */
160 /* FIXME : still no support for RLE packed DIBs */
161 res
= SetDIBits( hdc
, hBmp
, 0, scanLines
, bits
, bmi
, DIB_RGB_COLORS
);
162 HeapFree( GetProcessHeap(), 0, bmi
);
165 ERR("SetDIBits failed\n");
166 DeleteObject( hBmp
);
173 /***********************************************************************
174 * Creates DIB that is compatible with the target hdc.
175 * startScan and scanLines specify the portion of DDB to convert
176 * in order to avoid unneeded conversion of large DDBs on blitting
178 * NOTE : the srcBmp DDB MUST NOT be selected in any DC */
179 HBITMAP
_DIBDRV_ConvertDDBtoDIB( HDC hdc
, HBITMAP srcBmp
, int startScan
, int scanLines
)
186 if (!GetObjectW( srcBmp
, sizeof(bitmap
), &bitmap
))
188 ERR("Couldn't retrieve source bitmap\n");
192 if(startScan
+ scanLines
>= bitmap
.bmHeight
)
193 scanLines
= bitmap
.bmHeight
- startScan
;
195 bi
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
) /* + 256 * sizeof(RGBQUAD) */);
198 ERR("HeapAlloc failed\n");
202 bi
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
203 bi
->bmiHeader
.biWidth
= bitmap
.bmWidth
;
204 bi
->bmiHeader
.biHeight
= scanLines
;
205 bi
->bmiHeader
.biPlanes
= bitmap
.bmPlanes
;
206 bi
->bmiHeader
.biBitCount
= 32;
207 bi
->bmiHeader
.biCompression
= BI_RGB
;
208 bi
->bmiHeader
.biSizeImage
= 0;
210 /* No need to get the color table or the color masks
211 as we're requesting a 32 bit rgba DIB */
213 /* Create bitmap and fill in bits */
214 hBmp
= CreateDIBSection(hdc
, bi
, DIB_RGB_COLORS
, &bits
, NULL
, 0);
217 ERR("Failed to create DIB section\n");
218 HeapFree( GetProcessHeap(), 0, bi
);
223 if(!GetDIBits(hdc
, srcBmp
, startScan
, scanLines
, bits
, bi
, DIB_RGB_COLORS
))
225 ERR("GetDIBits failed\n");
226 DeleteObject( hBmp
);
227 HeapFree( GetProcessHeap(), 0, bi
);
233 ERR("CreateDibSection couldn't allocate DIB bits\n");
234 DeleteObject( hBmp
);
235 HeapFree( GetProcessHeap(), 0, bi
);
238 HeapFree( GetProcessHeap(), 0, bi
);
242 /***********************************************************************
243 * BITBLT_ConvertDevDDBtoDIB
245 * Creates DIB that is compatible with the target hdc for a device (non memory) source DC */
246 HBITMAP
_DIBDRV_ConvertDevDDBtoDIB( HDC hdcSrc
, HDC hdcDst
, int xSrc
, int ySrc
, int width
, int height
)
251 /* at first, we create a compatible DC and a bitmap with needed sizes */
252 memHDC
= CreateCompatibleDC(hdcSrc
);
255 ERR("CreateCompatibleDC failed\n");
258 bmp
= CreateCompatibleBitmap(hdcSrc
, width
, height
);
261 ERR("CreateCompatibleBitmap failed\n");
266 /* select the newly created DDB into the temporary DC */
267 bmp
= SelectObject(memHDC
, bmp
);
270 ERR("Failed selecting DDB into temporary DC\n");
276 /* next, we blit pixels from device to the compatible bitmap */
277 if(!BitBlt(memHDC
, 0, 0, width
, height
, hdcSrc
, xSrc
, ySrc
, SRCCOPY
))
279 ERR("BitBlt failed\n");
285 /* select out the DDB from the temporary DC */
286 bmp
= SelectObject(memHDC
, bmp
);
290 ERR("Failed selecting DDB out temporary DC\n");
295 /*now we can convert the bitmap to a DIB */
296 dib
= _DIBDRV_ConvertDDBtoDIB( hdcDst
, bmp
, 0, height
);
298 FIXME("ConvertDDBtoDIB failed\n");
300 /* free resources and return the created dib */