The R Project SVN R

Rev

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