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