2 * This file is part of ShapeFusion (Copyright 2000 Tito Dal Canton)
4 * ShapeFusion is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * ShapeFusion is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with ShapeFusion; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 #include "ShapesElements.h"
19 #include "utilities.h"
21 // convert an 8-bit ShapesBitmap to a RGB wxImage using the provided color table.
22 // <white_transparency> renders transparent pixels as white instead of using
23 // the chroma-key color. NOTE: this routine assumes valid pointers.
24 wxImage ShapesBitmapToImage(ShapesBitmap *bp, ShapesColorTable *ct, bool white_transparency)
28 bool transparency_enabled = bp->IsTransparent();
30 unsigned char *imgbuf = img.GetData(),
33 unsigned int colors_per_table = ct->ColorCount();
35 for (int i = 0; i < w * h; i++) {
36 unsigned char value = *inp++;
38 if (value == 0 && transparency_enabled && white_transparency) {
42 } else if (value < colors_per_table) {
43 ShapesColor *color = ct->GetColor(value);
45 *outp++ = color->Red() >> 8;
46 *outp++ = color->Green() >> 8;
47 *outp++ = color->Blue() >> 8;
49 wxLogError(wxT("[utilities ShapesBitmapToImage] Pixel value %u with just %u colors/table. Aborting"),
50 value, colors_per_table);
57 // create a wxBitmap thumbnail of the given wxImage. If the major wxImage
58 // dimension is greater than the specified thumbnail size, the wxImage
59 // will be scaled down (keeping its aspect ratio). If the wxImage is smaller,
60 // it will be just converted to a wxBitmap.
61 wxBitmap ImageThumbnail(wxImage &img, int tn_size, bool filtering)
63 int w = img.GetWidth(),
66 // scale the wxImage down to thumbnail size if larger
67 if (w > tn_size || h > tn_size) {
72 new_h = new_w * h / w;
77 new_w = new_h * w / h;
83 // wx doesn't allow nice scaling, so we supply here. The thing works this way:
84 // 1) calculate where each source pixel will end up in the final image
85 // 2) add the source pixel value to the destination pixel
86 // 3) divide each destination pixel by the number of pixels
87 // that were added there.
88 // It's nothing more than a brutal pixel-level average, but results are quite good.
89 wxImage scaledimg(new_w, new_h);
90 unsigned char *src = img.GetData(),
92 *dst = scaledimg.GetData();
93 unsigned int pixcount = new_w * new_h,
94 *tempbuf = new unsigned int[pixcount * 3],
95 *countbuf = new unsigned int[pixcount];
97 memset(tempbuf, 0, pixcount * 3 * sizeof(unsigned int));
98 memset(countbuf, 0, pixcount * sizeof(unsigned int));
100 for (int y = 0; y < h; y++) {
101 unsigned int dsty = (y * new_h) / h * new_w;
103 for (int x = 0; x < w; x++) {
104 unsigned int i = x * new_w / w + dsty,
105 *tempp = &tempbuf[3 * i];
114 unsigned int *tempp = tempbuf,
116 unsigned char *dstp = dst;
118 for (unsigned int i = 0; i < pixcount; i++) {
119 unsigned int count = *countp++;
126 *dstp++ = *tempp++ / count;
127 *dstp++ = *tempp++ / count;
128 *dstp++ = *tempp++ / count;
134 return wxBitmap(scaledimg);
136 // ugly (but fast and simple) wx scaler
137 img.Rescale(new_w, new_h);
138 return wxBitmap(img);
141 return wxBitmap(img);
145 // create the "bad item" (red 'X') thumbnail
146 wxBitmap BadThumbnail(int tn_size)
148 wxImage newimg(tn_size, tn_size);
149 unsigned char *imgbuf = newimg.GetData(), *p = imgbuf;
151 for (int y = 0; y < tn_size; y++) {
152 for (int x = 0; x < tn_size; x++) {
153 if (x == y || (tn_size - x - 1) == y || (x - 1) == y || (x + 1) == y
154 || (tn_size - x - 2) == y || (tn_size - x) == y) {
165 return wxBitmap(newimg);
168 // compute (squared) distance between given RGB colours (range [0;1]).
169 // This is used to quantize imported bitmaps against collection palettes.
170 // The formula seems to work quite well even for photos and very bad
171 // destination palettes. It was taken from the article "Colour metric"
172 // by T. Riemersma, available under a Creative Commons license at
173 // http://www.compuphase.com/cmetric.htm.
174 float ColourDistance(float r1, float g1, float b1, float r2, float g2, float b2)
176 float rMean = (r1 + r2) / 2.0,
181 return (2.0+rMean)*deltaR*deltaR + 4.0*deltaG*deltaG + (2.0+1.0-rMean)*deltaB*deltaB;