The R Project SVN R

Rev

Rev 76910 | 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;
76910 kalibera 105
    GAbyte *pixel8;
45017 ripley 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);
76910 kalibera 156
    GAbyte *pixel8 = getpixels(img);
55646 ripley 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
    */
76910 kalibera 172
    GAbyte *block = array(size, GAbyte);
55646 ripley 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];
76910 kalibera 188
	GAbyte *data = (GAbyte *) (& 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 */
76910 kalibera 196
    GAbyte *data = (GAbyte *) (&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
	}
87180 kalibera 214
    else if (height && width)
215
	memcpy(data, pixel32, 4*height*width);
4394 ripley 216
 
55647 ripley 217
    /* Create the bitmap from the DIB data.
218
       Could also use CreateDIBsection */
4394 ripley 219
 
55646 ripley 220
    HDC screendc = GetDC(0);
55647 ripley 221
    HBITMAP hb = CreateDIBitmap(screendc, &bmi->bmiHeader, CBM_INIT,
55646 ripley 222
				data, bmi, DIB_RGB_COLORS);
223
    ReleaseDC(0, screendc);
4394 ripley 224
 
45017 ripley 225
    /* tidy up */
226
    discard(block);
4394 ripley 227
 
45017 ripley 228
    /* create the bitmap */
55646 ripley 229
    bitmap obj = new_object(BitmapObject, hb, get_bitmap_base());
55647 ripley 230
    if (!obj) {
45017 ripley 231
	DeleteObject(hb);
232
	return NULL;
233
    }
55646 ripley 234
    obj->rect = rect(0, 0, width, height);
45017 ripley 235
    obj->depth = depth;
236
    obj->die = private_delbitmap;
4394 ripley 237
 
45017 ripley 238
    return obj;
4394 ripley 239
}
240
 
42641 ripley 241
#ifdef UNUSED
4394 ripley 242
/*
243
 *  The loadicon function returns a HBITMAP of an ICON from resources.
244
 */
41793 ripley 245
static bitmap loadicon(const char *name)
4394 ripley 246
{
45017 ripley 247
    HICON i;
248
    HDC dc;
249
    HBITMAP old;
250
    bitmap obj;
4394 ripley 251
 
45017 ripley 252
    if (this_instance == 0)
253
	return NULL;
254
    if ((i = LoadIcon(this_instance, name)) == 0)
255
	return NULL;
256
    if ((obj = newbitmap(32, 32, 0)) == NULL)
257
	return NULL;
4394 ripley 258
 
45017 ripley 259
    dc = CreateCompatibleDC(0);
260
    old = SelectObject(dc, (HBITMAP)obj->handle);
261
    DrawIcon(dc, 0, 0, i);
262
    SelectObject(dc, old);
263
    DeleteDC(dc);
264
    DestroyIcon(i);
4394 ripley 265
 
45017 ripley 266
    return obj;
4394 ripley 267
}
268
 
269
/*
270
 *  The loadpict function returns BITMAP resources.
271
 */
41793 ripley 272
static bitmap loadpict(const char *name)
4394 ripley 273
{
45017 ripley 274
    BITMAP bm;
275
    HBITMAP hb;
276
    bitmap obj;
4394 ripley 277
 
45017 ripley 278
    if (this_instance == 0)
279
	return NULL;
280
    hb = LoadBitmap(this_instance, name);
281
    GetObject(hb, sizeof(BITMAP), (LPSTR) &bm);
4394 ripley 282
 
45017 ripley 283
    obj = new_object(BitmapObject, hb, get_bitmap_base());
284
    if (obj) {
285
	obj->rect = rect(0, 0, bm.bmWidth, bm.bmHeight);
286
	obj->depth = (bm.bmPlanes * bm.bmBitsPixel);
287
	obj->die = private_delbitmap;
288
    }
289
    return obj;
4394 ripley 290
}
291
 
292
/*
293
 *  The loadbitmap function finds and returns bitmaps from resources,
294
 *  or from an image file.
295
 */
41793 ripley 296
bitmap loadbitmap(const char *name)
4394 ripley 297
{
45017 ripley 298
    bitmap obj;
4394 ripley 299
 
45017 ripley 300
    if ((obj = loadpict(name)) != NULL)
301
	return obj;
302
    if ((obj = loadicon(name)) != NULL)
303
	return obj;
304
    if ((obj = imagetobitmap(loadimage(name))) != NULL)
305
	return obj;
306
    return NULL;
4394 ripley 307
}
308
 
309
/*
310
 *  The following functions are obsolete from version 2.4.
311
 */
312
 
313
void setbitmapdata(bitmap obj, unsigned char *data)
314
{
45017 ripley 315
    rect r;
316
    int depth, size, row_bytes;
317
    int x, y;
318
    unsigned char *newdata = NULL;
4394 ripley 319
 
45017 ripley 320
    r = obj->rect;
321
    depth = obj->depth;
4394 ripley 322
 
45017 ripley 323
    /* Calculate source row bytes. */
324
    row_bytes = ((depth * r.width) + 7) / 8;
325
    /* Each row must be a multiple of 16 bits wide. */
326
    if (row_bytes % 2) {
327
	/* Odd number of bytes, must assign into new array. */
328
	size = (row_bytes+1) * r.height;
76910 kalibera 329
	newdata = array (size, GAbyte);
45017 ripley 330
	if (! newdata)
331
	    return;
332
	for (y=0; y<r.height; y++) {
333
	    for (x=0; x<row_bytes; x++) {
334
		newdata[y*(row_bytes+1)+x] =
335
		    data[y*row_bytes+x];
336
	    }
4394 ripley 337
	}
45017 ripley 338
	SetBitmapBits((HBITMAP)obj->handle, size,
339
		      (LPSTR)newdata);
340
	discard(newdata);
341
    } else {
342
	/* Correct format already! */
343
	size = row_bytes * r.height;
344
	SetBitmapBits((HBITMAP)obj->handle, size, (LPSTR)data);
345
    }
4394 ripley 346
}
347
 
348
void getbitmapdata(bitmap obj, unsigned char *data)
349
{
45017 ripley 350
    rect r;
351
    int depth, size, row_bytes;
352
    int x, y;
353
    unsigned char *newdata = NULL;
4394 ripley 354
 
45017 ripley 355
    r = obj->rect;
356
    depth = obj->depth;
4394 ripley 357
 
45017 ripley 358
    /* Calculate destination row bytes. */
359
    row_bytes = ((depth * r.width) + 7) / 8;
360
    /* Each row must be a multiple of 16 bits wide. */
361
    if (row_bytes % 2) {
362
	/* Odd number of bytes, must assign into new array. */
363
	size = (row_bytes+1) * r.height;
76910 kalibera 364
	newdata = array (size, GAbyte);
45017 ripley 365
	if (! newdata)
366
	    return;
367
	GetBitmapBits((HBITMAP)obj->handle, size,
368
		      (LPSTR)newdata);
369
	for (y=0; y<r.height; y++) {
370
	    for (x=0; x<row_bytes; x++) {
371
		data[y*row_bytes+x] =
372
		    newdata[y*(row_bytes+1)+x];
373
	    }
4394 ripley 374
	}
45017 ripley 375
	discard(newdata);
376
    } else {
377
	/* Correct format already! */
378
	size = row_bytes * r.height;
379
	GetBitmapBits((HBITMAP)obj->handle, size, (LPSTR)data);
380
    }
4394 ripley 381
}
382
 
383
bitmap createbitmap(int width, int height, int depth, unsigned char *data)
384
{
45017 ripley 385
    bitmap obj;
4394 ripley 386
 
45017 ripley 387
    if ((obj = newbitmap(width, height, depth)) == NULL)
388
	return NULL;
389
    if (data)
390
	setbitmapdata(obj, data);
391
    return obj;
4394 ripley 392
}
42641 ripley 393
#endif
4394 ripley 394
 
26839 ripley 395
void getbitmapdata2(bitmap obj, unsigned char **data)
26234 ripley 396
{
45017 ripley 397
    rect r = obj->rect;
398
    int depth = 32, size, ret;
399
    BITMAPINFO bmi;
26234 ripley 400
 
45017 ripley 401
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
402
    bmi.bmiHeader.biWidth = r.width;
403
    bmi.bmiHeader.biHeight = -r.height;
404
    bmi.bmiHeader.biPlanes = 1;
405
    bmi.bmiHeader.biBitCount = depth;
406
    bmi.bmiHeader.biCompression = BI_RGB;
407
    bmi.bmiHeader.biClrUsed = 0;
26234 ripley 408
 
45017 ripley 409
    size = 4 * r.width * r.height;
410
    *data = (unsigned char *) malloc(size);
411
    if(*data) {
412
	ret = GetDIBits(get_context(obj), (HBITMAP)obj->handle, 
413
			0, r.height, (LPSTR)*data, &bmi, DIB_RGB_COLORS);
414
	if(!ret) {
415
	    free(*data);
416
	    *data = NULL;
26234 ripley 417
	}
45017 ripley 418
    }
26234 ripley 419
}
420