dibdrv: Store image size
[wine/dibdrv.git] / dlls / winedib.drv / dib_render.c
blobcf5132f9f0e4e31537a890d13c7f2a9233375130
1 /*
2 * DIBDRV depth specific DIB rendering functions
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 "dib_render.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
32 /* DIB_GetColorTableEntry: Return color components of the requested color table entry. */
33 void DIB_GetColorTableEntry( DIBDRVBITMAP *bmp, BYTE i, BYTE *r, BYTE *g, BYTE *b )
35 *r = bmp->color_table[i].rgbRed;
36 *g = bmp->color_table[i].rgbGreen;
37 *b = bmp->color_table[i].rgbBlue;
40 /* DIB_GetNearestIndex: Return closest matching color table entry. */
41 INT DIB_GetNearestIndex( DIBDRVBITMAP *bmp, BYTE r, BYTE g, BYTE b )
43 INT i, diff, bestdiff = -1, ret = 0;
44 for (i = 0; i < bmp->nb_colors; i++)
46 diff = (bmp->color_table[i].rgbBlue - b)*(bmp->color_table[i].rgbBlue - b) +
47 (bmp->color_table[i].rgbGreen - g)*(bmp->color_table[i].rgbGreen - g) +
48 (bmp->color_table[i].rgbRed - r)*(bmp->color_table[i].rgbRed - r);
49 if (!diff)
50 return i;
51 if (bestdiff == -1 || diff < bestdiff)
53 ret = i;
54 bestdiff = diff;
57 return ret;
60 /* DIB16_EncodeColor: helper to encode a pixel for a 16 bpp DIB. */
61 WORD DIB16_EncodeColor( DIBDRVBITMAP *bmp, BYTE r, BYTE g, BYTE b )
63 return (r >> bmp->bf_shift[0]) << bmp->bf_pos[0] |
64 (g >> bmp->bf_shift[1]) << bmp->bf_pos[1] |
65 (b >> bmp->bf_shift[2]) << bmp->bf_pos[2];
68 /* DIB32_EncodeColor: helper to encode a pixel for a 32 bpp DIB. */
69 DWORD DIB32_EncodeColor( DIBDRVBITMAP *bmp, BYTE r, BYTE g, BYTE b )
71 return ((r >> bmp->bf_shift[0]) << bmp->bf_pos[0]) |
72 ((g >> bmp->bf_shift[1]) << bmp->bf_pos[1]) |
73 ((b >> bmp->bf_shift[2]) << bmp->bf_pos[2]);
76 /* Public Functions
78 * AdvancePosition(): Move drawing location relative to current position by the requested number
79 * of pixels. It is the caller's responsibility to traverse scan lines correctly, as this does
80 * not check for that.
82 * Copy(): Copy the requested number of pixels from source DIB to destination DIB performing format
83 * conversions as necessary. Since this requires two images, call the Copy() member of the
84 * destination image, pass the source conversion function table, and copy translates the call into
85 * the appropriate conversion routine. The caller is responsible to traverse scan lines
86 * correctly.
88 * MoveXY(): Move drawing location using X,Y coordinates. Stores address with whatever shifting
89 * required to correct value. Returns a BOOL where FALSE means an attempt to move out of range.
91 * ReadColor(): Read pixel and translate into color components.
93 * SelectColor(): Store a color encoded for the DIB.
95 * SetPixel(): Optimized SetPixel for GDI by writing a COLORREF directly.
97 * WriteColor(): Write a number of pixels with stored color.
100 void DIB1_AdvancePosition( DIBDRVBITMAP *bmp, int n )
102 bmp->shift -= n;
103 while (bmp->shift < 0)
105 bmp->addr = (BYTE*)bmp->addr + 1;
106 bmp->shift += 8;
110 void DIB1_Copy( DIBDRVBITMAP *dst, DIBDRVBITMAP *src, int num_pixels, const DIBCONVERT *convs )
112 convs->ConvertToDIB1( dst, src, num_pixels );
115 void DIB1_MoveXY( DIBDRVBITMAP *bmp, INT x, INT y )
117 unsigned int r = (unsigned int)bmp->bits + y*bmp->widthbytes + x/8; /* 1 byte per 8 pixels */
118 bmp->shift = 7 - x % 8; /* maximum shift within unsigned char: 7 */
119 bmp->addr = (void *)r;
122 void DIB1_ReadColor( DIBDRVBITMAP *bmp, BYTE *r, BYTE *g, BYTE *b )
124 DIB_GetColorTableEntry( bmp, (*(BYTE *)bmp->addr >> bmp->shift) & 1, r, g, b );
127 /* DIB1_SelectColor ----> DIB8_SelectColor */
129 void DIB1_SetPixel( DIBDRVBITMAP *bmp, COLORREF c )
131 BYTE *p = bmp->addr;
132 *p = DIB_GetNearestIndex( bmp, GetRValue( c ), GetGValue( c ), GetBValue( c ) ) ?
133 *p | 1 << bmp->shift : *p & ~(1 << bmp->shift);
136 void DIB1_WriteColor( DIBDRVBITMAP *bmp, int num_pixels )
138 int i;
139 for (i = 0; i < num_pixels; i++)
141 BYTE *p = bmp->addr;
142 *p = bmp->color8 ? *p | 1 << bmp->shift : *p & ~(1 << bmp->shift);
143 DIB1_AdvancePosition( bmp, 1 );
147 void DIB4_AdvancePosition( DIBDRVBITMAP *bmp, int n )
149 bmp->shift -= n;
150 while (bmp->shift < 0)
152 bmp->addr = (BYTE*)bmp->addr + 1;
153 bmp->shift += 2;
157 void DIB4_Copy( DIBDRVBITMAP *dst, DIBDRVBITMAP *src, int num_pixels, const DIBCONVERT *convs )
159 convs->ConvertToDIB4( dst, src, num_pixels );
162 void DIB4_MoveXY( DIBDRVBITMAP *bmp, INT x, INT y )
164 unsigned int r = (unsigned int)bmp->bits + y*bmp->widthbytes + x/2; /* 1 byte per 2 pixels */
165 bmp->shift = x % 2; /* If true, we need the first 4 bits */
166 bmp->addr = (void *)r;
169 void DIB4_ReadColor( DIBDRVBITMAP *bmp, BYTE *r, BYTE *g, BYTE *b )
171 DIB_GetColorTableEntry( bmp,
172 bmp->shift ? *(BYTE *)bmp->addr & 0xf : *(BYTE *)bmp->addr >> 4,
173 r, g, b );
176 /* DIB4_SelectColor ----> DIB8_SelectColor */
178 void DIB4_SetPixel( DIBDRVBITMAP *bmp, COLORREF c )
180 BYTE *p = bmp->addr;
181 *p = bmp->shift ?
182 (*p & 0xf0) |
183 DIB_GetNearestIndex( bmp, GetRValue( c ), GetGValue( c ), GetBValue( c ) ) :
184 (*p & 0xf ) |
185 (DIB_GetNearestIndex( bmp, GetRValue( c ), GetGValue( c ), GetBValue( c ) ) << 4);
188 void DIB4_WriteColor( DIBDRVBITMAP *bmp, int num_pixels )
190 int i;
191 for (i = 0; i < num_pixels; i++)
193 BYTE *p = bmp->addr;
194 *p = bmp->shift ? (*p & 0xf0)|bmp->color8 : (*p & 0xf)|(bmp->color8 << 4);
195 DIB4_AdvancePosition( bmp, 1 );
199 void DIB8_AdvancePosition( DIBDRVBITMAP *bmp, int n )
201 bmp->addr = (BYTE*)bmp->addr + n;
204 void DIB8_Copy( DIBDRVBITMAP *dst, DIBDRVBITMAP *src, int num_pixels, const DIBCONVERT *convs )
206 convs->ConvertToDIB8( dst, src, num_pixels );
209 void DIB8_MoveXY( DIBDRVBITMAP *bmp, INT x, INT y )
211 unsigned int r = (unsigned int)bmp->bits + y*bmp->widthbytes + x; /* 1 byte per 1 pixel */
212 bmp->addr = (void *)r;
215 void DIB8_ReadColor( DIBDRVBITMAP *bmp, BYTE *r, BYTE *g, BYTE *b )
217 DIB_GetColorTableEntry( bmp, *(BYTE *)bmp->addr, r, g, b );
220 void DIB8_SelectColor( DIBDRVBITMAP *bmp, COLORREF c )
222 bmp->color8 = DIB_GetNearestIndex( bmp, GetRValue( c ), GetGValue( c ), GetBValue( c ) );
225 void DIB8_SetPixel( DIBDRVBITMAP *bmp, COLORREF c )
227 *(BYTE *)bmp->addr = DIB_GetNearestIndex( bmp,
228 GetRValue( c ), GetGValue( c ), GetBValue( c ) );
231 void DIB8_WriteColor( DIBDRVBITMAP *bmp, int num_pixels )
233 int i;
234 for (i = 0; i < num_pixels; i++)
236 *(BYTE *)bmp->addr = bmp->color8;
237 DIB8_AdvancePosition( bmp, 1 );
241 void DIB16_AdvancePosition( DIBDRVBITMAP *bmp, int n )
243 bmp->addr = (WORD*)bmp->addr + n;
246 void DIB16_Copy( DIBDRVBITMAP *dst, DIBDRVBITMAP *src, int num_pixels, const DIBCONVERT *convs )
248 convs->ConvertToDIB16( dst, src, num_pixels );
251 void DIB16_MoveXY( DIBDRVBITMAP *bmp, INT x, INT y )
253 unsigned int addr = (unsigned int)bmp->bits + y*bmp->widthbytes + x*2; /* 2 bytes per pixel */
254 bmp->addr = (void *)addr;
257 void DIB16_ReadColor( DIBDRVBITMAP *bmp, BYTE *r, BYTE *g, BYTE *b )
259 WORD *p = bmp->addr;
260 *r = (*p & bmp->bitfields[0]) >> bmp->bf_pos[0] << bmp->bf_shift[0];
261 *g = (*p & bmp->bitfields[1]) >> bmp->bf_pos[1] << bmp->bf_shift[1];
262 *b = (*p & bmp->bitfields[2]) >> bmp->bf_pos[2] << bmp->bf_shift[2];
263 if (bmp->bf_size[0] < 8) *r |= *r >> bmp->bf_size[0];
264 if (bmp->bf_size[1] < 8) *g |= *g >> bmp->bf_size[1];
265 if (bmp->bf_size[2] < 8) *b |= *b >> bmp->bf_size[2];
268 void DIB16_SelectColor( DIBDRVBITMAP *bmp, COLORREF c )
270 bmp->color16 = DIB16_EncodeColor( bmp, GetRValue( c ), GetGValue( c ), GetBValue( c ) );
273 void DIB16_SetPixel( DIBDRVBITMAP *bmp, COLORREF c )
275 *(WORD *)bmp->addr = DIB16_EncodeColor( bmp, GetRValue( c ), GetGValue( c ), GetBValue( c ) );
278 void DIB16_WriteColor( DIBDRVBITMAP *bmp, int num_pixels )
280 int i;
281 for (i = 0; i < num_pixels; i++)
283 *(WORD *)bmp->addr = bmp->color16;
284 DIB16_AdvancePosition( bmp, 1 );
288 void DIB24_AdvancePosition( DIBDRVBITMAP *bmp, int n )
290 bmp->addr = (RGBTRIPLE*)bmp->addr + n;
293 void DIB24_Copy( DIBDRVBITMAP *dst, DIBDRVBITMAP *src, int num_pixels, const DIBCONVERT *convs )
295 convs->ConvertToDIB24( dst, src, num_pixels );
298 void DIB24_MoveXY( DIBDRVBITMAP *bmp, INT x, INT y )
300 unsigned int addr = (unsigned int)bmp->bits + y*bmp->widthbytes + x*3; /* 3 bytes per pixel */
301 bmp->addr = (void *)addr;
304 void DIB24_ReadColor( DIBDRVBITMAP *bmp, BYTE *r, BYTE *g, BYTE *b )
306 RGBTRIPLE *p = bmp->addr;
307 *r = p->rgbtRed;
308 *g = p->rgbtGreen;
309 *b = p->rgbtBlue;
312 void DIB24_SelectColor( DIBDRVBITMAP *bmp, COLORREF c )
314 bmp->color24.rgbtRed = GetRValue( c );
315 bmp->color24.rgbtGreen = GetGValue( c );
316 bmp->color24.rgbtBlue = GetBValue( c );
319 void DIB24_SetPixel( DIBDRVBITMAP *bmp, COLORREF c )
321 RGBTRIPLE *p = bmp->addr;
322 p->rgbtRed = GetRValue( c );
323 p->rgbtGreen = GetGValue( c );
324 p->rgbtBlue = GetBValue( c );
327 void DIB24_WriteColor( DIBDRVBITMAP *bmp, int num_pixels )
329 int i;
330 for (i = 0; i < num_pixels; i++)
332 RGBTRIPLE *p = bmp->addr;
333 p->rgbtRed = bmp->color24.rgbtRed;
334 p->rgbtGreen = bmp->color24.rgbtGreen;
335 p->rgbtBlue = bmp->color24.rgbtBlue;
336 DIB24_AdvancePosition( bmp, 1 );
340 void DIB32_AdvancePosition( DIBDRVBITMAP *bmp, int n )
342 bmp->addr = (DWORD*)bmp->addr + n;
345 void DIB32_Copy( DIBDRVBITMAP *dst, DIBDRVBITMAP *src, int num_pixels, const DIBCONVERT *convs )
347 convs->ConvertToDIB32( dst, src, num_pixels );
350 void DIB32_MoveXY( DIBDRVBITMAP *bmp, INT x, INT y )
352 unsigned int addr = (unsigned int)bmp->bits + y*bmp->widthbytes + x*4; /* 4 bytes per pixel */
353 bmp->addr = (void *)addr;
356 void DIB32_ReadColor( DIBDRVBITMAP *bmp, BYTE *r, BYTE *g, BYTE *b )
358 DWORD *p = bmp->addr;
359 *r = (*p & bmp->bitfields[0]) >> bmp->bf_pos[0] << bmp->bf_shift[0];
360 *g = (*p & bmp->bitfields[1]) >> bmp->bf_pos[1] << bmp->bf_shift[1];
361 *b = (*p & bmp->bitfields[2]) >> bmp->bf_pos[2] << bmp->bf_shift[2];
362 if (bmp->bf_size[0] < 8) *r |= *r >> bmp->bf_size[0];
363 if (bmp->bf_size[1] < 8) *g |= *g >> bmp->bf_size[1];
364 if (bmp->bf_size[2] < 8) *b |= *b >> bmp->bf_size[2];
367 void DIB32_SelectColor( DIBDRVBITMAP *bmp, COLORREF c )
369 bmp->color32 = DIB32_EncodeColor( bmp, GetRValue( c ), GetGValue( c ), GetBValue( c ) );
372 void DIB32_SetPixel( DIBDRVBITMAP *bmp, COLORREF c )
374 *(DWORD *)bmp->addr = DIB32_EncodeColor( bmp, GetRValue( c ), GetGValue( c ), GetBValue( c ) );
377 void DIB32_WriteColor( DIBDRVBITMAP *bmp, int num_pixels )
379 int i;
380 for (i = 0; i < num_pixels; i++)
382 *(DWORD *)bmp->addr = bmp->color32;
383 DIB32_AdvancePosition( bmp, 1 );
387 const DIBFUNCS DIB1_funcs =
389 &DIB1_AdvancePosition,
390 &DIB1_Copy,
391 &DIB1_MoveXY,
392 &DIB1_ReadColor,
393 &DIB8_SelectColor,
394 &DIB1_SetPixel,
395 &DIB1_WriteColor
398 const DIBFUNCS DIB4_funcs =
400 &DIB4_AdvancePosition,
401 &DIB4_Copy,
402 &DIB4_MoveXY,
403 &DIB4_ReadColor,
404 &DIB8_SelectColor,
405 &DIB4_SetPixel,
406 &DIB4_WriteColor
409 const DIBFUNCS DIB8_funcs =
411 &DIB8_AdvancePosition,
412 &DIB8_Copy,
413 &DIB8_MoveXY,
414 &DIB8_ReadColor,
415 &DIB8_SelectColor,
416 &DIB8_SetPixel,
417 &DIB8_WriteColor
420 const DIBFUNCS DIB16_funcs =
422 &DIB16_AdvancePosition,
423 &DIB16_Copy,
424 &DIB16_MoveXY,
425 &DIB16_ReadColor,
426 &DIB16_SelectColor,
427 &DIB16_SetPixel,
428 &DIB16_WriteColor
431 const DIBFUNCS DIB24_funcs =
433 &DIB24_AdvancePosition,
434 &DIB24_Copy,
435 &DIB24_MoveXY,
436 &DIB24_ReadColor,
437 &DIB24_SelectColor,
438 &DIB24_SetPixel,
439 &DIB24_WriteColor
442 const DIBFUNCS DIB32_funcs =
444 &DIB32_AdvancePosition,
445 &DIB32_Copy,
446 &DIB32_MoveXY,
447 &DIB32_ReadColor,
448 &DIB32_SelectColor,
449 &DIB32_SetPixel,
450 &DIB32_WriteColor