dibdrv: Store image size
[wine/dibdrv.git] / dlls / winedib.drv / bitmap.c
blobc65c348f45850aa073cb8fbf5aa5ff638c79830d
1 /*
2 * DIB driver bitmap objects
4 * Copyright 2007 Jesse Allen
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
23 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wine/debug.h"
28 #include "dibdrv.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
32 DIBFORMAT BITMAP_GetFormat( WORD depth, DWORD compression )
34 switch (depth)
36 case 1:
37 if (compression == BI_RGB)
38 return DIBFMT_DIB1;
39 break;
40 case 4:
41 if (compression == BI_RLE4)
42 WARN("RLE compression not supported yet!\n");
43 else if (compression == BI_RGB)
44 return DIBFMT_DIB4;
45 break;
46 case 8:
47 if (compression == BI_RLE8)
48 WARN("RLE compression not supported yet!\n");
49 else if (compression == BI_RGB)
50 return DIBFMT_DIB8;
51 break;
52 case 16:
53 if (compression == BI_BITFIELDS)
54 return DIBFMT_DIB16;
55 else if (compression == BI_RGB)
56 return DIBFMT_X1B5G5R5;
57 break;
58 case 24:
59 if (compression == BI_RGB)
60 return DIBFMT_DIB24;
61 break;
62 case 32:
63 if (compression == BI_BITFIELDS)
64 return DIBFMT_DIB32;
65 else if (compression == BI_RGB)
66 return DIBFMT_X8B8G8R8;
67 break;
69 ERR("unsupported dib format: depth=%d, compression=%d\n", depth, compression);
70 return DIBFMT_UNKNOWN;
73 const DIBFUNCS *BITMAP_GetDIBFuncs( DIBFORMAT format )
75 switch(format)
77 case DIBFMT_DIB1: return &DIB1_funcs;
78 case DIBFMT_DIB4: return &DIB4_funcs;
79 case DIBFMT_DIB8: return &DIB8_funcs;
80 case DIBFMT_X1B5G5R5:
81 case DIBFMT_DIB16: return &DIB16_funcs;
82 case DIBFMT_DIB24: return &DIB24_funcs;
83 case DIBFMT_X8B8G8R8:
84 case DIBFMT_DIB32: return &DIB32_funcs;
85 case DIBFMT_UNKNOWN:
86 default:
87 ERR("no support for format %d!\n", format);
89 return NULL;
92 const DIBCONVERT *BITMAP_GetDIBConversions( DIBFORMAT format )
94 switch(format)
96 case DIBFMT_DIB1: return &DIB1_convs;
97 case DIBFMT_DIB4: return &DIB4_convs;
98 case DIBFMT_DIB8: return &DIB8_convs;
99 case DIBFMT_X1B5G5R5:
100 case DIBFMT_DIB16: return &DIB16_convs;
101 case DIBFMT_DIB24: return &DIB24_convs;
102 case DIBFMT_X8B8G8R8:
103 case DIBFMT_DIB32: return &DIB32_convs;
104 case DIBFMT_UNKNOWN:
105 default:
106 ERR("no support for format %d!\n", format);
108 return NULL;
111 void BITMAP_CalcBitfields( DIBDRVBITMAP *bmp, WORD depth )
113 int i, x;
114 for (i = 0; i < 3; i++)
116 x = 0;
117 while (!((bmp->bitfields[i] >> x) & 1) && (x < depth))
118 x++;
119 bmp->bf_pos[i] = x;
120 while (((bmp->bitfields[i] >> x) & 1) && (x < depth))
121 x++;
122 bmp->bf_size[i] = x - bmp->bf_pos[i];
123 if (bmp->bf_size[i] > 8) bmp->bf_pos[i] += 8;
124 bmp->bf_shift[i] = bmp->bf_size[i] < 8 ? 8 - bmp->bf_size[i] : 0;
128 /* BITMAP_Alloc: Alloc DIBDRVBITMAP and initialize to passed-in values. Note: caller is
129 * responsible for proper handling of the color table.
131 DIBDRVBITMAP *BITMAP_Alloc( DIBFORMAT format, void *bits, INT width, INT height, INT widthbytes,
132 INT size, RGBQUAD *color_table, UINT nb_colors, DWORD *bitfields )
134 DIBDRVBITMAP *bmp = HeapAlloc( GetProcessHeap(), 0, sizeof(DIBDRVBITMAP) );
135 if (!bmp) return NULL;
137 TRACE("%d %p %d %d %d %p %u %p\n", format, bits, width, height, widthbytes, color_table,
138 nb_colors, bitfields);
140 bmp->format = format;
141 bmp->bits = bits;
142 bmp->width = width;
143 bmp->height = height;
144 bmp->widthbytes = widthbytes;
145 bmp->size = size;
146 bmp->color_table = color_table;
147 bmp->nb_colors = nb_colors;
149 if (format == DIBFMT_DIB16 || format == DIBFMT_DIB32)
151 bmp->bitfields[0] = bitfields[0];
152 bmp->bitfields[1] = bitfields[1];
153 bmp->bitfields[2] = bitfields[2];
154 BITMAP_CalcBitfields( bmp, format == DIBFMT_DIB16 ? 16 : 32 );
156 else if (format == DIBFMT_X1B5G5R5)
158 bmp->bitfields[0] = 0x7c00;
159 bmp->bitfields[1] = 0x3e0;
160 bmp->bitfields[2] = 0x1f;
161 BITMAP_CalcBitfields( bmp, 16 );
163 else if (format == DIBFMT_X8B8G8R8)
165 bmp->bitfields[0] = 0xff0000;
166 bmp->bitfields[1] = 0xff00;
167 bmp->bitfields[2] = 0xff;
168 BITMAP_CalcBitfields( bmp, 32 );
171 return bmp;
174 /***********************************************************************
175 * BITMAP_GetDIBWidthBytes
177 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
178 * Copied from gdi32.
180 int BITMAP_GetDIBWidthBytes( int width, int depth )
182 int words;
184 switch(depth)
186 case 1: words = (width + 31) / 32; break;
187 case 4: words = (width + 7) / 8; break;
188 case 8: words = (width + 3) / 4; break;
189 case 15:
190 case 16: words = (width + 1) / 2; break;
191 case 24: words = (width * 3 + 3)/4; break;
193 default:
194 WARN("(%d): Unsupported depth\n", depth );
195 /* fall through */
196 case 32:
197 words = width;
199 return 4 * words;
202 DIBDRVBITMAP *BITMAP_CreateFromBmi( const BITMAPINFO *bmi, void *bits )
204 DIBFORMAT fmt = BITMAP_GetFormat( bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression );
205 if (!fmt) return NULL;
206 return BITMAP_Alloc( fmt, bits, bmi->bmiHeader.biWidth,
207 bmi->bmiHeader.biHeight,
208 BITMAP_GetDIBWidthBytes( bmi->bmiHeader.biWidth,
209 bmi->bmiHeader.biBitCount ),
210 bmi->bmiHeader.biSizeImage,
211 (RGBQUAD *)bmi->bmiColors,
212 bmi->bmiHeader.biClrUsed,
213 (DWORD *)bmi->bmiColors );
216 DIBDRVBITMAP *BITMAP_CreateFromHBitmap( HBITMAP hbitmap, RGBQUAD *ct, UINT nb_colors )
218 DIBFORMAT fmt;
219 DIBSECTION dib;
220 if (!GetObjectW( hbitmap, sizeof(dib), &dib )) return NULL;
222 /* If we get an hbitmap from any GDI call this can mean a few things:
223 * 1) We got a bitmap that is really a DIB, so it's dependent on the DIB engine. This occurs
224 * during SelectBitmap for example, so we can use it then.
225 * 2) We may have gotten a bitmap that was really intended for an actual device, like
226 * winex11. If this does indeed ever happen, we will have to punt back.
227 * 3) The application really committed a fatal error and got DCs mixed up. We will simply have
228 * to fail.
229 * So we must perform a check whether this is a DDB no matter what we think it might be.
231 if (!dib.dsBm.bmBits)
233 /* When this is a DDB, we don't handle it right now so we will print
234 * an error to inform the user, and fail.
236 ERR("hbitmap is actually a DDB and there is no way to handle this yet\n");
237 return NULL;
240 fmt = BITMAP_GetFormat( dib.dsBmih.biBitCount, dib.dsBmih.biCompression );
241 if (!fmt) return NULL;
243 return BITMAP_Alloc( fmt, dib.dsBm.bmBits, dib.dsBmih.biWidth, dib.dsBmih.biHeight,
244 dib.dsBm.bmWidthBytes, dib.dsBmih.biSizeImage, ct, nb_colors,
245 dib.dsBitfields );
248 /***********************************************************************
249 * DIBDRV_SelectBitmap
251 HBITMAP DIBDRV_SelectBitmap( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, RGBQUAD *color_table,
252 UINT nb_colors )
254 DIBDRVBITMAP *bmp;
255 RGBQUAD *ct;
256 TRACE("%p, %p\n", physDev, hbitmap);
258 if (nb_colors)
260 /* make a copy of the color table */
261 ct = HeapAlloc( GetProcessHeap(), 0, sizeof(RGBQUAD)*nb_colors );
262 if (!ct) return 0;
263 memcpy( ct, color_table, sizeof(RGBQUAD)*nb_colors );
265 else ct = NULL;
267 bmp = BITMAP_CreateFromHBitmap( hbitmap, ct, nb_colors );
268 if (!bmp)
270 HeapFree( GetProcessHeap(), 0, ct );
271 return 0;
274 /* Since we have a valid DIB, we can now write over the old one */
275 physDev->hbitmap = hbitmap;
276 if (physDev->bmp)
278 if (physDev->bmp->color_table)
279 HeapFree( GetProcessHeap(), 0, physDev->bmp->color_table );
280 HeapFree( GetProcessHeap(), 0, physDev->bmp );
282 physDev->bmp = bmp;
283 physDev->funcs = BITMAP_GetDIBFuncs( bmp->format );
284 physDev->convs = BITMAP_GetDIBConversions( bmp->format );
286 return hbitmap;
289 /****************************************************************************
290 * DIBDRV_CreateBitmap
292 BOOL DIBDRV_CreateBitmap( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, LPVOID bmBits )
294 FIXME("stub\n");
295 return TRUE;
298 /***********************************************************************
299 * DIBDRV_DeleteBitmap
301 BOOL DIBDRV_DeleteBitmap( HBITMAP hbitmap )
303 FIXME("stub\n");
304 return TRUE;
307 /***********************************************************************
308 * DIBDRV_GetBitmapBits
310 LONG DIBDRV_GetBitmapBits( HBITMAP hbitmap, void *buffer, LONG count )
312 FIXME("stub\n");
313 return 0;
316 /******************************************************************************
317 * DIBDRV_SetBitmapBits
319 LONG DIBDRV_SetBitmapBits( HBITMAP hbitmap, const void *bits, LONG count )
321 FIXME("stub\n");
322 return 0;