The R Project SVN R

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4394 ripley 1
/*
2
 * GraphApp - Cross-Platform Graphics Programming Library.
3
 *
4
 * File: bitmaps.c -- functions for creating a detroying bitmaps.
5
 * Platform: Windows  Version: 2.40  Date: 1998/05/05
6
 *
7
 * Version: 1.00  Changes: Original version by Lachlan Patrick.
8
 * Version: 2.00  Changes: New object class system implemented.
9
 * Version: 2.15  Changes: Improved bitmap data formats.
10
 * Version: 2.30  Changes: Now uses bitmap_base.
11
 * Version: 2.40  Changes: Fast image to bitmap conversion.
12
 */
13
 
14
/* Copyright (C) 1993-1998 Lachlan Patrick
15
 
16
   This file is part of GraphApp, a cross-platform C graphics library.
17
 
18
   GraphApp is free software; you can redistribute it and/or modify it
19
   under the terms of the GNU Library General Public License.
20
   GraphApp is distributed in the hope that it will be useful, but
21
   WITHOUT ANY WARRANTY.
22
 
23
   See the file COPYLIB.TXT for details.
24
*/
25
 
26
#include "internal.h"
27
 
28
/*
29
 *  Internal bitmap deletion function.
30
 */
31
static void private_delbitmap(bitmap obj)
32
{
33
	if (obj->handle)
34
		DeleteObject((HBITMAP) obj->handle);
35
}
36
 
37
/*
38
 *  Create/return the base bitmap object.
39
 */
40
static object get_bitmap_base(void)
41
{
42
	static object bitmap_base = NULL;
43
 
44
	if (! bitmap_base)
45
		bitmap_base = new_object(BaseObject, 0, NULL);
46
	return bitmap_base;
47
}
48
 
49
/*
50
 *  Create a white bitmap.
51
 */
52
bitmap newbitmap(int width, int height, int depth)
53
{
54
	BITMAP bm;
55
	HBITMAP hb, old;
56
	HDC dc, screendc;
57
	bitmap obj;
58
 
59
	screendc = GetDC(0); /* get screen dc */
60
 
61
	if (depth == 1) /* monochrome bitmap required */
62
	{
63
		hb = CreateBitmap(width, height, 1, 1, 0);
64
	}
65
	else /* colour bitmap required */
66
	{
67
		hb = CreateCompatibleBitmap(screendc, width, height);
68
	}
69
 
70
	if (! hb) {
71
		ReleaseDC(0, screendc);
72
		return NULL;
73
	}
74
 
75
	dc = CreateCompatibleDC(screendc);
76
	old = SelectObject(dc, hb);
77
	PatBlt(dc, 0, 0, width, height, WHITENESS);
78
	SelectObject(dc, old);
79
	DeleteDC(dc);
80
 
81
	ReleaseDC(0, screendc);
82
 
83
	GetObject(hb, sizeof(BITMAP), (LPSTR) &bm);
84
 
85
	obj = new_object(BitmapObject, hb, get_bitmap_base());
86
	if (! obj) {
87
		DeleteObject(hb);
88
		return NULL;
89
	}
90
	obj->rect = rect(0,0,width,height);
91
	obj->depth = (bm.bmPlanes * bm.bmBitsPixel);
92
	obj->die = private_delbitmap;
93
 
94
	return obj;
95
}
96
 
97
/*
98
 *  Check an image to see if there are any transparent pixels.
99
 *  Return 1 as soon as a transparent pixel is found, 0 if none are.
100
 */
101
PROTECTED
102
int has_transparent_pixels(image img)
103
{
104
	long i, width, height, total;
105
	rgb *palette;
106
	byte *pixel8;
107
	rgb *pixel32;
108
	rgb col;
109
 
110
	if (! img)
111
		return 0;
112
 
113
	width = getwidth(img);
114
	height = getheight(img);
115
	total = width * height;
116
 
117
	palette = getpalette(img);
118
 
119
	pixel8 = getpixels(img);
120
	pixel32 = (rgb *) pixel8;
121
 
122
	if (getdepth(img) == 8) {
123
		for (i=0; i < total; i++) {
124
			col = pixel8[i];
125
			col = palette[col];
126
			if (getalpha(col) > 0x7F)
127
				return 1;
128
		}
129
	}
130
	else {
131
		for (i=0; i < total; i++) {
132
			col = pixel32[i];
133
			if (getalpha(col) > 0x7F)
134
				return 1;
135
		}
136
	}
137
 
138
	return 0;
139
}
140
 
141
/*
142
 *  Create a bitmap version of an image.
143
 */
144
bitmap imagetobitmap(image img)
145
{
146
	HBITMAP hb;
147
	HDC screendc;
148
	bitmap obj;
149
	int width, height, depth, palsize;
150
	unsigned long x, y, i, row_bytes;
151
	byte *block, *data, *pixel8;
152
	rgb *palette, *pixel32;
153
	rgb colour;
154
	unsigned long size;
155
	BITMAPINFO * bmi;
156
 
157
	if (! img)
158
		return NULL;
159
 
160
	/* remember some facts about the image */
161
	width = getwidth(img);
162
	height = getheight(img);
163
	depth = (getdepth(img) == 8) ? 8 : 24;
164
	palette = getpalette(img);
165
	palsize = getpalettesize(img);
166
	pixel8 = getpixels(img);
167
	pixel32 = (rgb *) pixel8;
168
 
169
	/* create DIB info in memory */
170
	size = sizeof(BITMAPINFOHEADER) + 4;
171
	if (depth == 8) {
172
		row_bytes = ((width + 3) / 4) * 4;
173
		size = size + (sizeof(RGBQUAD) * palsize);
174
		size = size + (row_bytes * height);
175
	} else {
176
		row_bytes = (((width * 3) + 3) / 4) * 4;
177
		size = size + (row_bytes * height);
178
	}
179
 
180
	/* create the block, align on LONG boundary */
181
	block = array(size, byte);
182
	i = ((long)block) % 4;
183
	bmi = (BITMAPINFO *) (block + (4 - i));
184
 
185
	/* assign header info */
186
	bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
187
	bmi->bmiHeader.biWidth = width;
188
	bmi->bmiHeader.biHeight = height;
189
	bmi->bmiHeader.biPlanes = 1;
190
	bmi->bmiHeader.biBitCount = depth;
191
	bmi->bmiHeader.biCompression = BI_RGB;
192
	bmi->bmiHeader.biClrUsed = palsize;
193
 
194
	/* assign colour table */
195
	for (i=0; i < palsize; i++) {
196
		colour  = palette[i];
197
		data = (byte *) (& bmi->bmiColors[i]);
198
		data[0] = getblue(colour);
199
		data[1] = getgreen(colour);
200
		data[2] = getred(colour);
201
		data[3] = 0;
202
	}
203
 
204
	/* assign the bitmap data itself */
205
	data = (byte *) (& bmi->bmiColors[palsize]);
206
 
207
	if (depth == 8)
208
	  for (y=0; y < height; y++) {
209
	    for (x=0; x < width; x++) {
210
		i = ((height - y - 1) * row_bytes) + x;
211
		data[i] = pixel8[y * width + x];
212
	    }
213
	  }
214
	else
215
	  for (y=0; y < height; y++) {
216
	    for (x=0; x < width; x++) {
217
		colour = pixel32[y * width + x];
218
		i = ((height - y - 1) * row_bytes) + (x * 3);
219
		data[i] = getblue(colour);
220
		data[i+1] = getgreen(colour);
221
		data[i+2] = getred(colour);
222
	    }
223
	  }
224
 
225
	/* create the bitmap from the DIB data */
226
 
227
	screendc = GetDC(0);	/* get screen dc */
228
	hb = CreateDIBitmap(screendc, & bmi->bmiHeader, CBM_INIT,
229
			data, bmi, DIB_RGB_COLORS);
230
	ReleaseDC(0, screendc);	/* release screen dc */
231
 
232
	/* tidy up */
233
	discard(block);
234
 
235
	/* create the bitmap */
236
	obj = new_object(BitmapObject, hb, get_bitmap_base());
237
	if (! obj) {
238
		DeleteObject(hb);
239
		return NULL;
240
	}
241
	obj->rect = rect(0,0,width,height);
242
	obj->depth = depth;
243
	obj->die = private_delbitmap;
244
 
245
	return obj;
246
}
247
 
248
/*
249
 *  The loadicon function returns a HBITMAP of an ICON from resources.
250
 */
251
static bitmap loadicon(char *name)
252
{
253
	HICON i;
254
	HDC dc;
255
	HBITMAP old;
256
	bitmap obj;
257
 
258
	if (this_instance == 0)
259
		return NULL;
260
	if ((i = LoadIcon(this_instance, name)) == 0)
261
		return NULL;
262
	if ((obj = newbitmap(32, 32, 0)) == NULL)
263
		return NULL;
264
 
265
	dc = CreateCompatibleDC(0);
266
	old = SelectObject(dc, (HBITMAP)obj->handle);
267
	DrawIcon(dc, 0, 0, i);
268
	SelectObject(dc, old);
269
	DeleteDC(dc);
270
	DestroyIcon(i);
271
 
272
	return obj;
273
}
274
 
275
/*
276
 *  The loadpict function returns BITMAP resources.
277
 */
278
static bitmap loadpict(char *name)
279
{
280
	BITMAP bm;
281
	HBITMAP hb;
282
	bitmap obj;
283
 
284
	if (this_instance == 0)
285
		return NULL;
286
	hb = LoadBitmap(this_instance, name);
287
	GetObject(hb, sizeof(BITMAP), (LPSTR) &bm);
288
 
289
	obj = new_object(BitmapObject, hb, get_bitmap_base());
290
	if (obj) {
291
		obj->rect = rect(0, 0, bm.bmWidth, bm.bmHeight);
292
		obj->depth = (bm.bmPlanes * bm.bmBitsPixel);
293
		obj->die = private_delbitmap;
294
	}
295
	return obj;
296
}
297
 
298
/*
299
 *  The loadbitmap function finds and returns bitmaps from resources,
300
 *  or from an image file.
301
 */
302
bitmap loadbitmap(char *name)
303
{
304
	bitmap obj;
305
 
306
	if ((obj = loadpict(name)) != NULL)
307
		return obj;
308
	if ((obj = loadicon(name)) != NULL)
309
		return obj;
310
	if ((obj = imagetobitmap(loadimage(name))) != NULL)
311
		return obj;
312
	return NULL;
313
}
314
 
315
/*
316
 *  The following functions are obsolete from version 2.4.
317
 */
318
 
319
void setbitmapdata(bitmap obj, unsigned char *data)
320
{
321
	rect r;
322
	int depth, size, row_bytes;
323
	int x, y;
324
	unsigned char *newdata = NULL;
325
 
326
	r = obj->rect;
327
	depth = obj->depth;
328
 
329
	/* Calculate source row bytes. */
330
	row_bytes = ((depth * r.width) + 7) / 8;
331
	/* Each row must be a multiple of 16 bits wide. */
332
	if (row_bytes % 2) {
333
		/* Odd number of bytes, must assign into new array. */
334
		size = (row_bytes+1) * r.height;
335
		newdata = array (size, byte);
336
		if (! newdata)
337
			return;
338
		for (y=0; y<r.height; y++) {
339
			for (x=0; x<row_bytes; x++) {
340
				newdata[y*(row_bytes+1)+x] =
341
					data[y*row_bytes+x];
342
			}
343
		}
344
		SetBitmapBits((HBITMAP)obj->handle, size,
345
				(LPSTR)newdata);
346
		discard(newdata);
347
	} else {
348
		/* Correct format already! */
349
		size = row_bytes * r.height;
350
		SetBitmapBits((HBITMAP)obj->handle, size, (LPSTR)data);
351
	}
352
}
353
 
354
void getbitmapdata(bitmap obj, unsigned char *data)
355
{
356
	rect r;
357
	int depth, size, row_bytes;
358
	int x, y;
359
	unsigned char *newdata = NULL;
360
 
361
	r = obj->rect;
362
	depth = obj->depth;
363
 
364
	/* Calculate destination row bytes. */
365
	row_bytes = ((depth * r.width) + 7) / 8;
366
	/* Each row must be a multiple of 16 bits wide. */
367
	if (row_bytes % 2) {
368
		/* Odd number of bytes, must assign into new array. */
369
		size = (row_bytes+1) * r.height;
370
		newdata = array (size, byte);
371
		if (! newdata)
372
			return;
373
		GetBitmapBits((HBITMAP)obj->handle, size,
374
				(LPSTR)newdata);
375
		for (y=0; y<r.height; y++) {
376
			for (x=0; x<row_bytes; x++) {
377
				data[y*row_bytes+x] =
378
					newdata[y*(row_bytes+1)+x];
379
			}
380
		}
381
		discard(newdata);
382
	} else {
383
		/* Correct format already! */
384
		size = row_bytes * r.height;
385
		GetBitmapBits((HBITMAP)obj->handle, size, (LPSTR)data);
386
	}
387
}
388
 
389
bitmap createbitmap(int width, int height, int depth, unsigned char *data)
390
{
391
	bitmap obj;
392
 
393
	if ((obj = newbitmap(width, height, depth)) == NULL)
394
		return NULL;
395
	if (data)
396
		setbitmapdata(obj, data);
397
	return obj;
398
}
399
 
26839 ripley 400
void getbitmapdata2(bitmap obj, unsigned char **data)
26234 ripley 401
{
402
	rect r = obj->rect;
403
	int depth = 32, size, ret;
404
	BITMAPINFO bmi;
405
 
406
	bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
407
	bmi.bmiHeader.biWidth = r.width;
408
	bmi.bmiHeader.biHeight = -r.height;
409
	bmi.bmiHeader.biPlanes = 1;
410
	bmi.bmiHeader.biBitCount = depth;
411
	bmi.bmiHeader.biCompression = BI_RGB;
412
	bmi.bmiHeader.biClrUsed = 0;
413
 
26839 ripley 414
	size = 4 * r.width * r.height;
26234 ripley 415
	*data = (unsigned char *) malloc(size);
416
	if(*data) {
417
	    ret = GetDIBits(get_context(obj), (HBITMAP)obj->handle, 
26839 ripley 418
			    0, r.height, (LPSTR)*data, &bmi, DIB_RGB_COLORS);
26234 ripley 419
	    if(!ret) {
420
		free(*data);
421
		*data = NULL;
422
	    }
423
	}
424
}
425