| /* | |
| * R : A Computer Language for Statistical Data Analysis | |
| * Copyright (C) 1998--1999 Guido Masarotto | |
| * | |
| * This program is free software; you can redistribute it and/or modify | |
| * it under the terms of the GNU General Public License as published by | |
| * the Free Software Foundation; either version 2 of the License, or | |
| * (at your option) any later version. | |
| * | |
| * This program is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| * GNU General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU General Public License | |
| * along with this program; if not, a copy is available at | |
| * https://www.R-project.org/Licenses/ | |
| */ | |
| /* | |
| bitmap -> image conversion | |
| Very easy to write: routines here are the graphapp | |
| image to image conversion routines with assignement | |
| changed. | |
| */ | |
| #include "ga.h" | |
| /* | |
| * Try to generate an 8-bit version. | |
| * If there are less than 256 unique colours | |
| * this routine will return the corresponding | |
| * indexed 8-bit image. | |
| * Returns NULL if more than 256 colours are found. | |
| */ | |
| static image copy2image8 (drawing dw) | |
| { | |
| image new_img; | |
| long x, y, w, h, j; | |
| byte * pixel8; | |
| int cmapsize; | |
| int low, high, mid; | |
| rgb col; | |
| rgb cmap[256]; | |
| point p; | |
| w = getwidth(dw); | |
| h = getheight(dw); | |
| /* the first colour goes into the cmap automatically: */ | |
| cmapsize = 0; mid = 0; | |
| for (y = 0; y < h; y++) { | |
| p.y = y; | |
| for (x = 0; x < w; x++) { | |
| p.x = x; | |
| col = ggetpixel(dw, p); | |
| /* only allow one transparent colour in the cmap: */ | |
| if (col & 0xF0000000UL) | |
| col = 0xFFFFFFFFUL; /* transparent */ | |
| else | |
| col &= 0x00FFFFFFUL; /* opaque */ | |
| /* binary search the cmap: */ | |
| low = 0; high = cmapsize - 1; | |
| while (low <= high) { | |
| mid = (low + high)/2; | |
| if (col < cmap[mid]) high = mid - 1; | |
| else if (col > cmap[mid]) low = mid + 1; | |
| else break; | |
| } | |
| if (high < low) { | |
| /* didn't find colour in cmap, insert it: */ | |
| if (cmapsize >= 256) | |
| return NULL; | |
| for (j = cmapsize; j > low; j--) | |
| cmap[j] = cmap[j-1]; | |
| cmap[low] = col; | |
| cmapsize ++; | |
| } | |
| } | |
| } | |
| /* now create the 8-bit indexed image: */ | |
| new_img = newimage(w, h, 8); | |
| if (! new_img) | |
| return new_img; | |
| setpalette(new_img, cmapsize, cmap); | |
| /* now convert each 32-bit pixel into an 8-bit pixel: */ | |
| pixel8 = (byte *) new_img->pixels; | |
| for (y = 0; y < h; y++) { | |
| p.y = y; | |
| for (x = 0; x < w; x++) { | |
| p.x = x; | |
| col = ggetpixel(dw, p); | |
| /* only allow one transparent colour in the cmap: */ | |
| if (col & 0xF0000000UL) | |
| col = 0xFFFFFFFFUL; /* transparent */ | |
| else | |
| col &= 0x00FFFFFFUL; /* opaque */ | |
| /* binary search the cmap (the colour must be there): */ | |
| low = 0; high = cmapsize - 1; | |
| while (low <= high) { | |
| mid = (low + high)/2; | |
| if (col < cmap[mid]) high = mid - 1; | |
| else if (col > cmap[mid]) low = mid + 1; | |
| else break; | |
| } | |
| if (high < low) { | |
| /* impossible situation */ | |
| delimage(new_img); | |
| return NULL; | |
| } | |
| *(pixel8++) = mid; | |
| } | |
| } | |
| return new_img; | |
| } | |
| /* | |
| * Try to generate a 32-bit version. | |
| * Return NULL if there is no memory left. | |
| */ | |
| static image copy2image32 (drawing dw) | |
| { | |
| image new_img; | |
| rgb *pixel32; | |
| long x, y, w, h; | |
| point p; | |
| w = getwidth(dw); | |
| h = getheight(dw); | |
| new_img = newimage(w, h, 32); | |
| if (! new_img) | |
| return new_img; | |
| pixel32 = (rgb *) new_img->pixels; | |
| for (y = 0; y < h; y++) { | |
| p.y = y; | |
| for (x = 0; x < w; x++) { | |
| p.x = x; | |
| *(pixel32++) = ggetpixel(dw, p); | |
| } | |
| } | |
| return new_img; | |
| } | |
| /* | |
| * Try to generate an image (with depth 8 or 32) from drawing dw: | |
| * Return NULL on failure. | |
| */ | |
| image bitmaptoimage (drawing dw) | |
| { | |
| image new_img; | |
| rect r = ggetcliprect(dw); | |
| gsetcliprect(dw, getrect(dw)); | |
| new_img = copy2image8(dw); | |
| if (!new_img) | |
| new_img = copy2image32(dw); | |
| gsetcliprect(dw, r); | |
| return new_img; | |
| } |