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 */
90 if(ds
.dsBmih
.biBitCount
> 8)
93 if(ds
.dsBmih
.biCompression
== BI_BITFIELDS
)
98 colorUsed
= ds
.dsBmih
.biClrUsed
;
100 colorUsed
= 1 << ds
.dsBmih
.biBitCount
;
103 /* builds the needed BITMAPINFOHEADER */
104 bmi
= HeapAlloc( GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER
)+
105 sizeof(RGBQUAD
)*colorUsed
+ sizeof(DWORD
) * bitFields
);
108 ERR("HeapAlloc failed\n");
112 /* copy the header part */
113 memcpy( &bmi
->bmiHeader
, &ds
.dsBmih
, sizeof(BITMAPINFOHEADER
) );
115 /* gets the color table part, if any */
118 /* create a temporary DC, GetDIBColorTable() requests that
119 the DIB is selected in a DC.... */
120 if(!(tmpHdc
= CreateCompatibleDC(hdc
)))
122 ERR("Couldn't create the temporary HDC\n");
123 HeapFree(GetProcessHeap(), 0, bmi
);
126 /* selects the DIB into the temporary DC */
127 if( !(tmpBmp
= SelectObject(tmpHdc
, srcBmp
)))
129 ERR("Couldn't select source DIB into temporary DC\n");
131 HeapFree(GetProcessHeap(), 0, bmi
);
134 GetDIBColorTable(tmpHdc
, 0, colorUsed
, bmi
->bmiColors
);
135 SelectObject(tmpHdc
, tmpBmp
);
139 /* fill the bitfields part, if any */
141 memcpy(bmi
->bmiColors
, ds
.dsBitfields
, 3 * sizeof(DWORD
));
143 /* adjust dib size for SetDIBits, as it needs it to reverse top-down dibs
144 it must be set to the number of scanLines to transfer */
145 bmi
->bmiHeader
.biHeight
= topDown
? -scanLines
: scanLines
;
147 /* creates destination compatible bitmap */
148 tmpHdc
= GetDC(NULL
);
149 hBmp
= CreateCompatibleBitmap(tmpHdc
, dibWidth
, scanLines
);
150 ReleaseDC(NULL
, tmpHdc
);
153 ERR("CreateCompatibleBitmap failed\n");
154 HeapFree( GetProcessHeap(), 0, bmi
);
158 /* copies the requested scan lines from DIB to DDB */
159 /* FIXME : still no support for RLE packed DIBs */
160 res
= SetDIBits( hdc
, hBmp
, 0, scanLines
, bits
, bmi
, DIB_RGB_COLORS
);
161 HeapFree( GetProcessHeap(), 0, bmi
);
164 ERR("SetDIBits failed\n");
165 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; /* bitmap.bmBitsPixel; */
205 bi
->bmiHeader
.biCompression
= BI_RGB
;
206 bi
->bmiHeader
.biSizeImage
= 0;
208 /* Get the color table or the color masks */
209 /* NO NEED -- WE'RE REQUESTING A 32 bit DIB */
211 if (!GetDIBits(hdc
, srcBmp
, startScan
, scanLines
, NULL
, bi
, DIB_RGB_COLORS
))
213 ERR("Couldn't get the color table/masks\n");
214 HeapFree( GetProcessHeap(), 0, bi
);
219 /* Create bitmap and fill in bits */
220 hBmp
= CreateDIBSection(hdc
, bi
, DIB_RGB_COLORS
, &bits
, NULL
, 0);
223 ERR("Failed to create DIB section\n");
224 HeapFree( GetProcessHeap(), 0, bi
);
229 if(!GetDIBits(hdc
, srcBmp
, startScan
, scanLines
, bits
, bi
, DIB_RGB_COLORS
))
231 ERR("GetDIBits failed\n");
232 DeleteObject( hBmp
);
233 HeapFree( GetProcessHeap(), 0, bi
);
239 ERR("CreateDibSection couldn't allocate DIB bits\n");
240 DeleteObject( hBmp
);
241 HeapFree( GetProcessHeap(), 0, bi
);
244 HeapFree( GetProcessHeap(), 0, bi
);
248 /***********************************************************************
249 * BITBLT_ConvertDevDDBtoDIB
251 * Creates DIB that is compatible with the target hdc for a device (non memory) source DC */
252 HBITMAP
_DIBDRV_ConvertDevDDBtoDIB( HDC hdcSrc
, HDC hdcDst
, int xSrc
, int ySrc
, int width
, int height
)
257 /* at first, we create a compatible DC and a bitmap with needed sizes */
258 memHDC
= CreateCompatibleDC(hdcSrc
);
261 ERR("CreateCompatibleDC failed\n");
264 bmp
= CreateCompatibleBitmap(hdcSrc
, width
, height
);
267 ERR("CreateCompatibleBitmap failed\n");
272 /* select the newly created DDB into the temporary DC */
273 bmp
= SelectObject(memHDC
, bmp
);
276 ERR("Failed selecting DDB into temporary DC\n");
282 /* next, we blit pixels from device to the compatible bitmap */
283 if(!BitBlt(memHDC
, 0, 0, width
, height
, hdcSrc
, xSrc
, ySrc
, SRCCOPY
))
285 ERR("BitBlt failed\n");
291 /* select out the DDB from the temporary DC */
292 bmp
= SelectObject(memHDC
, bmp
);
296 ERR("Failed selecting DDB out temporary DC\n");
301 /*now we can convert the bitmap to a DIB */
302 dib
= _DIBDRV_ConvertDDBtoDIB( hdcDst
, bmp
, 0, height
);
304 FIXME("ConvertDDBtoDIB failed\n");
306 /* free resources and return the created dib */