2 // "$Id: fl_draw_image_win32.cxx 8294 2011-01-20 12:55:50Z manolo $"
4 // WIN32 image drawing code for the Fast Light Tool Kit (FLTK).
6 // Copyright 1998-2010 by Bill Spitzak and others.
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
28 // I hope a simple and portable method of drawing color and monochrome
29 // images. To keep this simple, only a single storage type is
30 // supported: 8 bit unsigned data, byte order RGB, and pixels are
31 // stored packed into rows with the origin at the top-left. It is
32 // possible to alter the size of pixels with the "delta" argument, to
33 // add alpha or other information per pixel. It is also possible to
34 // change the origin and direction of the image data by messing with
35 // the "delta" and "linedelta", making them negative, though this may
36 // defeat some of the shortcuts in translating the image for X.
38 // Unbelievably (since it conflicts with how most PC software works)
39 // Micro$oft picked a bottom-up and BGR storage format for their
40 // DIB images. I'm pretty certain there is a way around this, but
41 // I can't find any other than the brute-force method of drawing
42 // each line as a separate image. This may also need to be done
43 // if the delta is any amount other than 1, 3, or 4.
45 ////////////////////////////////////////////////////////////////
49 #include <FL/Fl_Printer.H>
50 #include <FL/fl_draw.H>
53 #define MAXBUFFER 0x40000 // 256k
57 // error-diffusion dither into the FLTK colormap
58 static void dither(uchar
* to
, const uchar
* from
, int w
, int delta
) {
59 static int ri
, gi
, bi
, dir
;
64 from
= from
+(w
-1)*delta
;
73 for (; w
--; from
+= d
, to
+= td
) {
74 r
+= from
[0]; if (r
< 0) r
= 0; else if (r
>255) r
= 255;
75 int rr
= r
*FL_NUM_RED
/256;
76 r
-= rr
*255/(FL_NUM_RED
-1);
77 g
+= from
[1]; if (g
< 0) g
= 0; else if (g
>255) g
= 255;
78 int gg
= g
*FL_NUM_GREEN
/256;
79 g
-= gg
*255/(FL_NUM_GREEN
-1);
80 b
+= from
[2]; if (b
< 0) b
= 0; else if (b
>255) b
= 255;
81 int bb
= b
*FL_NUM_BLUE
/256;
82 b
-= bb
*255/(FL_NUM_BLUE
-1);
83 *to
= uchar(FL_COLOR_CUBE
+(bb
*FL_NUM_RED
+rr
)*FL_NUM_GREEN
+gg
);
85 ri
= r
; gi
= g
; bi
= b
;
88 // error-diffusion dither into the FLTK colormap
89 static void monodither(uchar
* to
, const uchar
* from
, int w
, int delta
) {
95 from
= from
+(w
-1)*delta
;
104 for (; w
--; from
+= d
, to
+= td
) {
105 r
+= *from
; if (r
< 0) r
= 0; else if (r
>255) r
= 255;
106 int rr
= r
*FL_NUM_GRAY
/256;
107 r
-= rr
*255/(FL_NUM_GRAY
-1);
108 *to
= uchar(FL_GRAY_RAMP
+rr
);
113 #endif // USE_COLORMAP
115 static void innards(const uchar
*buf
, int X
, int Y
, int W
, int H
,
116 int delta
, int linedelta
, int depth
,
117 Fl_Draw_Image_Cb cb
, void* userdata
)
122 indexed
= (fl_palette
!= 0);
125 if (depth
==0) depth
= 3;
126 if (indexed
|| !fl_can_do_alpha_blending())
129 if (!linedelta
) linedelta
= W
*delta
;
132 fl_clip_box(X
,Y
,W
,H
,x
,y
,w
,h
);
133 if (w
<=0 || h
<=0) return;
134 if (buf
) buf
+= (x
-X
)*delta
+ (y
-Y
)*linedelta
;
136 static U32 bmibuffer
[256+12];
137 BITMAPINFO
&bmi
= *((BITMAPINFO
*)bmibuffer
);
138 if (!bmi
.bmiHeader
.biSize
) {
139 bmi
.bmiHeader
.biSize
= sizeof(bmi
)-4; // does it use this to determine type?
140 bmi
.bmiHeader
.biPlanes
= 1;
141 bmi
.bmiHeader
.biCompression
= BI_RGB
;
142 bmi
.bmiHeader
.biXPelsPerMeter
= 0;
143 bmi
.bmiHeader
.biYPelsPerMeter
= 0;
144 bmi
.bmiHeader
.biClrUsed
= 0;
145 bmi
.bmiHeader
.biClrImportant
= 0;
149 for (short i
=0; i
<256; i
++) {
150 *((short*)(bmi
.bmiColors
)+i
) = i
;
155 for (int i
=0; i
<256; i
++) {
156 bmi
.bmiColors
[i
].rgbBlue
= (uchar
)i
;
157 bmi
.bmiColors
[i
].rgbGreen
= (uchar
)i
;
158 bmi
.bmiColors
[i
].rgbRed
= (uchar
)i
;
159 bmi
.bmiColors
[i
].rgbReserved
= (uchar
)0; // must be zero
162 bmi
.bmiHeader
.biWidth
= w
;
164 bmi
.bmiHeader
.biBitCount
= indexed
? 8 : depth
*8;
165 int pixelsize
= indexed
? 1 : depth
;
167 bmi
.bmiHeader
.biBitCount
= depth
*8;
168 int pixelsize
= depth
;
170 if (depth
==2) { // special case: gray with alpha
171 bmi
.bmiHeader
.biBitCount
= 32;
174 int linesize
= (pixelsize
*w
+3)&~3;
177 static long buffer_size
;
179 {int size
= linesize
*h
;
180 // when printing, don't limit buffer size not to get a crash in StretchDIBits
181 if (size
> MAXBUFFER
&& Fl_Surface_Device::surface()->class_name() != Fl_Printer::class_id
) {
183 blocking
= MAXBUFFER
/linesize
;
185 if (size
> buffer_size
) {
188 buffer
= new U32
[(size
+3)/4];
190 bmi
.bmiHeader
.biHeight
= blocking
;
191 static U32
* line_buffer
;
194 static int line_buf_size
;
195 if (size
> line_buf_size
) {
196 delete[] line_buffer
;
197 line_buf_size
= size
;
198 line_buffer
= new U32
[(size
+3)/4];
201 for (int j
=0; j
<h
; ) {
203 for (k
= 0; j
<h
&& k
<blocking
; k
++, j
++) {
205 if (!buf
) { // run the converter:
206 cb(userdata
, x
-X
, y
-Y
+j
, w
, (uchar
*)line_buffer
);
207 from
= (uchar
*)line_buffer
;
212 uchar
*to
= (uchar
*)buffer
+(blocking
-k
-1)*linesize
;
216 monodither(to
, from
, w
, delta
);
218 dither(to
, from
, w
, delta
);
226 for (i
=w
; i
--; from
+= delta
) *to
++ = *from
;
229 for (i
=w
; i
--; from
+= delta
, to
+= 4) {
231 uchar gray
= (from
[0]*a
)>>8;
239 for (i
=w
; i
--; from
+= delta
, to
+= 3) {
247 for (i
=w
; i
--; from
+= delta
, to
+= 4) {
250 to
[0] = (from
[2]*a
)>>8;
251 to
[1] = (from
[1]*a
)>>8;
259 if(Fl_Surface_Device::surface()->class_name() == Fl_Printer::class_id
) {
260 // if print context, device and logical units are not equal, so SetDIBitsToDevice
261 // does not do the expected job, whereas StretchDIBits does it.
262 StretchDIBits(fl_gc
, x
, y
+j
-k
, w
, k
, 0, 0, w
, k
,
263 (LPSTR
)((uchar
*)buffer
+(blocking
-k
)*linesize
),
266 indexed
? DIB_PAL_COLORS
: DIB_RGB_COLORS
276 SetDIBitsToDevice(fl_gc
, x
, y
+j
-k
, w
, k
, 0, 0, 0, k
,
277 (LPSTR
)((uchar
*)buffer
+(blocking
-k
)*linesize
),
280 indexed
? DIB_PAL_COLORS
: DIB_RGB_COLORS
289 static int fl_abs(int v
) { return v
<0 ? -v
: v
; }
291 void Fl_GDI_Graphics_Driver::draw_image(const uchar
* buf
, int x
, int y
, int w
, int h
, int d
, int l
){
292 if (fl_abs(d
)&FL_IMAGE_WITH_ALPHA
) {
293 d
^= FL_IMAGE_WITH_ALPHA
;
294 innards(buf
,x
,y
,w
,h
,d
,l
,fl_abs(d
),0,0);
296 innards(buf
,x
,y
,w
,h
,d
,l
,(d
<3&&d
>-3),0,0);
300 void Fl_GDI_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb
, void* data
,
301 int x
, int y
, int w
, int h
,int d
) {
302 if (fl_abs(d
)&FL_IMAGE_WITH_ALPHA
) {
303 d
^= FL_IMAGE_WITH_ALPHA
;
304 innards(0,x
,y
,w
,h
,d
,0,(d
<3&&d
>-3),cb
,data
);
306 innards(0,x
,y
,w
,h
,d
,0,(d
<3&&d
>-3),cb
,data
);
310 void Fl_GDI_Graphics_Driver::draw_image_mono(const uchar
* buf
, int x
, int y
, int w
, int h
, int d
, int l
){
311 if (fl_abs(d
)&FL_IMAGE_WITH_ALPHA
) {
312 d
^= FL_IMAGE_WITH_ALPHA
;
313 innards(buf
,x
,y
,w
,h
,d
,l
,1,0,0);
315 innards(buf
,x
,y
,w
,h
,d
,l
,1,0,0);
319 void Fl_GDI_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb
, void* data
,
320 int x
, int y
, int w
, int h
,int d
) {
321 if (fl_abs(d
)&FL_IMAGE_WITH_ALPHA
) {
322 d
^= FL_IMAGE_WITH_ALPHA
;
323 innards(0,x
,y
,w
,h
,d
,0,1,cb
,data
);
325 innards(0,x
,y
,w
,h
,d
,0,1,cb
,data
);
329 void fl_rectf(int x
, int y
, int w
, int h
, uchar r
, uchar g
, uchar b
) {
331 // use the error diffusion dithering code to produce a much nicer block:
334 c
[0] = r
; c
[1] = g
; c
[2] = b
;
335 innards(c
,x
,y
,w
,h
,0,0,0,0,0);
344 // End of "$Id: fl_draw_image_win32.cxx 8294 2011-01-20 12:55:50Z manolo $".