1 /*
2 * R : A Computer Language for Statistical Data Analysis
3 * Copyright (C) 1998--1999 Guido Masarotto
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, a copy is available at
17 * https://www.R-project.org/Licenses/
18 */
19
20 /*
21 bitmap -> image conversion
22 Very easy to write: routines here are the graphapp
23 image to image conversion routines with assignement
24 changed.
25 */
26
27 #include "ga.h"
28
29 /*
30 * Try to generate an 8-bit version.
31 * If there are less than 256 unique colours
32 * this routine will return the corresponding
33 * indexed 8-bit image.
34 * Returns NULL if more than 256 colours are found.
35 */
copy2image8(drawing dw)36 static image copy2image8 (drawing dw)
37 {
38 image new_img;
39 long x, y, w, h, j;
40 GAbyte * pixel8;
41 int cmapsize;
42 int low, high, mid;
43 rgb col;
44 rgb cmap[256];
45 point p;
46 w = getwidth(dw);
47 h = getheight(dw);
48 /* the first colour goes into the cmap automatically: */
49 cmapsize = 0; mid = 0;
50
51 for (y = 0; y < h; y++) {
52 p.y = y;
53 for (x = 0; x < w; x++) {
54 p.x = x;
55 col = ggetpixel(dw, p);
56 /* only allow one transparent colour in the cmap: */
57 if (col & 0xF0000000UL)
58 col = 0xFFFFFFFFUL; /* transparent */
59 else
60 col &= 0x00FFFFFFUL; /* opaque */
61 /* binary search the cmap: */
62 low = 0; high = cmapsize - 1;
63 while (low <= high) {
64 mid = (low + high)/2;
65 if (col < cmap[mid]) high = mid - 1;
66 else if (col > cmap[mid]) low = mid + 1;
67 else break;
68 }
69
70 if (high < low) {
71 /* didn't find colour in cmap, insert it: */
72 if (cmapsize >= 256)
73 return NULL;
74 for (j = cmapsize; j > low; j--)
75 cmap[j] = cmap[j-1];
76 cmap[low] = col;
77 cmapsize ++;
78 }
79 }
80 }
81
82 /* now create the 8-bit indexed image: */
83
84 new_img = newimage(w, h, 8);
85 if (! new_img)
86 return new_img;
87 setpalette(new_img, cmapsize, cmap);
88 /* now convert each 32-bit pixel into an 8-bit pixel: */
89
90 pixel8 = (GAbyte *) new_img->pixels;
91
92 for (y = 0; y < h; y++) {
93 p.y = y;
94 for (x = 0; x < w; x++) {
95 p.x = x;
96 col = ggetpixel(dw, p);
97 /* only allow one transparent colour in the cmap: */
98 if (col & 0xF0000000UL)
99 col = 0xFFFFFFFFUL; /* transparent */
100 else
101 col &= 0x00FFFFFFUL; /* opaque */
102 /* binary search the cmap (the colour must be there): */
103 low = 0; high = cmapsize - 1;
104 while (low <= high) {
105 mid = (low + high)/2;
106 if (col < cmap[mid]) high = mid - 1;
107 else if (col > cmap[mid]) low = mid + 1;
108 else break;
109 }
110
111 if (high < low) {
112 /* impossible situation */
113 delimage(new_img);
114 return NULL;
115 }
116 *(pixel8++) = mid;
117 }
118 }
119 return new_img;
120 }
121
122
123 /*
124 * Try to generate a 32-bit version.
125 * Return NULL if there is no memory left.
126 */
copy2image32(drawing dw)127 static image copy2image32 (drawing dw)
128 {
129 image new_img;
130 rgb *pixel32;
131 long x, y, w, h;
132 point p;
133 w = getwidth(dw);
134 h = getheight(dw);
135 new_img = newimage(w, h, 32);
136 if (! new_img)
137 return new_img;
138
139 pixel32 = (rgb *) new_img->pixels;
140 for (y = 0; y < h; y++) {
141 p.y = y;
142 for (x = 0; x < w; x++) {
143 p.x = x;
144 *(pixel32++) = ggetpixel(dw, p);
145 }
146 }
147 return new_img;
148 }
149
150
151
152 /*
153 * Try to generate an image (with depth 8 or 32) from drawing dw:
154 * Return NULL on failure.
155 */
bitmaptoimage(drawing dw)156 image bitmaptoimage (drawing dw)
157 {
158 image new_img;
159 rect r = ggetcliprect(dw);
160
161 gsetcliprect(dw, getrect(dw));
162 new_img = copy2image8(dw);
163 if (!new_img)
164 new_img = copy2image32(dw);
165 gsetcliprect(dw, r);
166 return new_img;
167 }
168