1 /******************************************************************************
3 * $Id: image.cpp,v 1.14 2001/03/19 19:27:40 root Exp $
6 * Copyright (C) 1997-2012 by Dimitri van Heesch.
8 * Permission to use, copy, modify, and distribute this software and its
9 * documentation under the terms of the GNU General Public License is hereby
10 * granted. No representations are made about the suitability of this software
11 * for any purpose. It is provided "as is" without express or implied warranty.
12 * See the GNU General Public License for more details.
14 * Documents produced by Doxygen are derivative works derived from the
15 * input used in their production; they are not affected by this license.
26 typedef unsigned char Byte;
28 /** Helper struct representing a RGBA color */
37 const int charSetWidth=80;
38 const int charHeight=12;
39 const int numChars=96;
41 unsigned short charPos[numChars] =
43 0, 5, 8, 13, 20, 27, 38, 47,
44 50, 54, 58, 65, 72, 76, 83, 87,
45 91, 98,105,112,119,126,133,140,
46 147,154,161,164,167,174,181,188,
47 195,207,216,224,233,242,250,258,
48 267,276,279,286,294,301,312,321,
49 331,339,349,357,365,372,380,389,
50 400,409,418,427,430,434,437,443,
51 450,453,460,467,474,481,488,492,
52 499,506,509,512,518,521,530,537,
53 544,551,557,562,568,571,578,585,
54 594,600,607,613,617,620,624,631
57 unsigned char charWidth[numChars] =
59 5, 3, 5, 7, 7,11, 9, 3,
60 4, 4, 7, 7, 4, 7, 4, 4,
62 7, 7, 7, 7, 7, 7, 7, 7,
63 7, 7, 3, 3, 7, 7, 7, 7,
64 12, 9, 8, 9, 9, 8, 8, 9,
65 9, 3, 7, 8, 7,11, 9,10,
66 8,10, 8, 8, 7, 8, 9,11,
67 9, 9, 9, 3, 4, 3, 6, 7,
68 3, 7, 7, 7, 7, 7, 4, 7,
69 7, 3, 3, 6, 3, 9, 7, 7,
70 7, 6, 5, 6, 3, 7, 7, 9,
71 6, 7, 6, 4, 3, 4, 7, 5
74 unsigned char fontRaw[charSetWidth*charHeight] = {
75 0x02, 0x50, 0x01, 0x06, 0x20, 0x60, 0xc6, 0x04, 0x00, 0x00, 0x00, 0x27,
76 0x04, 0x1c, 0x38, 0x11, 0xf1, 0xc7, 0xc7, 0x0e, 0x00, 0x00, 0x00, 0x03,
77 0x81, 0xf0, 0x10, 0x7c, 0x1e, 0x3e, 0x1f, 0x9f, 0x87, 0x88, 0x24, 0x09,
78 0x09, 0x02, 0x02, 0x41, 0x0f, 0x0f, 0x83, 0xc3, 0xe1, 0xe7, 0xf4, 0x24,
79 0x12, 0x22, 0x41, 0x20, 0x9f, 0xce, 0x30, 0x00, 0x10, 0x04, 0x00, 0x01,
80 0x00, 0x30, 0x08, 0x12, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
81 0x00, 0x00, 0x00, 0x00, 0x01, 0xac, 0x00, 0x00, 0x02, 0x51, 0x43, 0x89,
82 0x40, 0x90, 0x49, 0x15, 0x00, 0x00, 0x00, 0x28, 0x9c, 0x22, 0x44, 0x31,
83 0x02, 0x20, 0x48, 0x91, 0x00, 0x00, 0x00, 0x04, 0x46, 0x08, 0x28, 0x42,
84 0x21, 0x21, 0x10, 0x10, 0x08, 0x48, 0x24, 0x09, 0x11, 0x03, 0x06, 0x61,
85 0x10, 0x88, 0x44, 0x22, 0x12, 0x10, 0x84, 0x24, 0x12, 0x22, 0x22, 0x20,
86 0x80, 0x4a, 0x11, 0x00, 0x20, 0x04, 0x00, 0x01, 0x00, 0x40, 0x08, 0x00,
87 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
88 0x02, 0x22, 0x00, 0x00, 0x02, 0x51, 0x45, 0x49, 0x40, 0x90, 0x89, 0x0a,
89 0x00, 0x00, 0x00, 0x48, 0x84, 0x02, 0x04, 0x51, 0x02, 0x00, 0x88, 0x91,
90 0x00, 0x00, 0x00, 0x04, 0x44, 0xd4, 0x28, 0x42, 0x40, 0x20, 0x90, 0x10,
91 0x10, 0x08, 0x24, 0x09, 0x21, 0x03, 0x06, 0x51, 0x20, 0x48, 0x48, 0x12,
92 0x12, 0x00, 0x84, 0x22, 0x22, 0x22, 0x22, 0x11, 0x00, 0x89, 0x12, 0x80,
93 0x31, 0xc5, 0x87, 0x0d, 0x1c, 0xe3, 0x4b, 0x12, 0x49, 0x29, 0x16, 0x1c,
94 0x58, 0x69, 0x4c, 0xe8, 0x91, 0x44, 0x61, 0x44, 0xf2, 0x22, 0x00, 0x00,
95 0x02, 0x07, 0xe5, 0x06, 0x80, 0x60, 0x10, 0x95, 0x08, 0x00, 0x00, 0x48,
96 0x84, 0x04, 0x18, 0x51, 0xe2, 0xc0, 0x87, 0x11, 0x24, 0x18, 0x03, 0x00,
97 0x89, 0x24, 0x44, 0x42, 0x40, 0x20, 0x90, 0x10, 0x10, 0x08, 0x24, 0x09,
98 0x41, 0x02, 0x8a, 0x51, 0x20, 0x48, 0x48, 0x12, 0x11, 0x80, 0x84, 0x22,
99 0x21, 0x24, 0x14, 0x11, 0x01, 0x09, 0x14, 0x40, 0x02, 0x26, 0x48, 0x93,
100 0x22, 0x44, 0xcc, 0x92, 0x51, 0x36, 0x99, 0x22, 0x64, 0x99, 0x92, 0x48,
101 0x91, 0x44, 0x52, 0x44, 0x12, 0x22, 0x00, 0x00, 0x02, 0x01, 0x43, 0x80,
102 0x80, 0xa0, 0x10, 0x84, 0x08, 0x00, 0x00, 0x88, 0x84, 0x08, 0x04, 0x90,
103 0x13, 0x21, 0x08, 0x8f, 0x00, 0x61, 0xf0, 0xc0, 0x8a, 0x24, 0x44, 0x7c,
104 0x40, 0x20, 0x9f, 0x9f, 0x11, 0xcf, 0xe4, 0x09, 0xc1, 0x02, 0x8a, 0x49,
105 0x20, 0x4f, 0x88, 0x13, 0xe0, 0x60, 0x84, 0x22, 0x21, 0x54, 0x08, 0x0a,
106 0x02, 0x08, 0x90, 0x00, 0x00, 0x24, 0x48, 0x11, 0x22, 0x44, 0x48, 0x92,
107 0x61, 0x24, 0x91, 0x22, 0x44, 0x89, 0x10, 0x48, 0x91, 0x24, 0x8c, 0x44,
108 0x22, 0x22, 0x64, 0x00, 0x02, 0x07, 0xe1, 0x41, 0x31, 0x14, 0x10, 0x80,
109 0x3e, 0x07, 0xc0, 0x88, 0x84, 0x10, 0x05, 0x10, 0x12, 0x21, 0x08, 0x81,
110 0x01, 0x80, 0x00, 0x31, 0x0a, 0x24, 0x7c, 0x42, 0x40, 0x20, 0x90, 0x10,
111 0x10, 0x48, 0x24, 0x09, 0x21, 0x02, 0x52, 0x45, 0x20, 0x48, 0x08, 0x92,
112 0x20, 0x10, 0x84, 0x21, 0x41, 0x54, 0x14, 0x04, 0x04, 0x08, 0x90, 0x00,
113 0x01, 0xe4, 0x48, 0x11, 0x3e, 0x44, 0x48, 0x92, 0x61, 0x24, 0x91, 0x22,
114 0x44, 0x89, 0x0c, 0x48, 0x8a, 0x24, 0x8c, 0x48, 0x44, 0x21, 0x98, 0x00,
115 0x02, 0x02, 0x85, 0x41, 0x49, 0x08, 0x10, 0x80, 0x08, 0x00, 0x00, 0x88,
116 0x84, 0x20, 0x45, 0xf9, 0x12, 0x21, 0x08, 0x81, 0x00, 0x61, 0xf0, 0xc1,
117 0x0a, 0x68, 0x82, 0x42, 0x40, 0x20, 0x90, 0x10, 0x10, 0x48, 0x24, 0x89,
118 0x11, 0x02, 0x52, 0x45, 0x20, 0x48, 0x08, 0x52, 0x12, 0x10, 0x84, 0x21,
119 0x40, 0x88, 0x22, 0x04, 0x08, 0x08, 0x90, 0x00, 0x02, 0x24, 0x48, 0x11,
120 0x20, 0x44, 0x48, 0x92, 0x51, 0x24, 0x91, 0x22, 0x44, 0x89, 0x02, 0x48,
121 0x8a, 0x2a, 0x92, 0x28, 0x42, 0x22, 0x00, 0x00, 0x00, 0x02, 0x85, 0x41,
122 0x49, 0x18, 0x10, 0x80, 0x08, 0x00, 0x01, 0x08, 0x84, 0x20, 0x44, 0x11,
123 0x12, 0x22, 0x08, 0x91, 0x00, 0x18, 0x03, 0x00, 0x09, 0xb0, 0x82, 0x42,
124 0x21, 0x21, 0x10, 0x10, 0x08, 0xc8, 0x24, 0x89, 0x09, 0x02, 0x22, 0x43,
125 0x10, 0x88, 0x04, 0x22, 0x12, 0x10, 0x84, 0x20, 0x80, 0x88, 0x22, 0x04,
126 0x10, 0x08, 0x50, 0x00, 0x02, 0x26, 0x48, 0x93, 0x22, 0x44, 0xc8, 0x92,
127 0x49, 0x24, 0x91, 0x22, 0x64, 0x99, 0x12, 0x49, 0x84, 0x11, 0x21, 0x28,
128 0x82, 0x22, 0x00, 0x00, 0x02, 0x02, 0x83, 0x82, 0x30, 0xe4, 0x10, 0x80,
129 0x00, 0x20, 0x05, 0x07, 0x04, 0x3e, 0x38, 0x10, 0xe1, 0xc2, 0x07, 0x0e,
130 0x24, 0x00, 0x00, 0x01, 0x04, 0x00, 0x82, 0x7c, 0x1e, 0x3e, 0x1f, 0x90,
131 0x07, 0x48, 0x24, 0x71, 0x05, 0xf2, 0x22, 0x41, 0x0f, 0x08, 0x03, 0xd2,
132 0x11, 0xe0, 0x83, 0xc0, 0x80, 0x88, 0x41, 0x04, 0x1f, 0xc8, 0x50, 0x00,
133 0x01, 0xd5, 0x87, 0x0d, 0x1c, 0x43, 0x48, 0x92, 0x45, 0x24, 0x91, 0x1c,
134 0x58, 0x69, 0x0c, 0x66, 0x84, 0x11, 0x21, 0x10, 0xf2, 0x22, 0x00, 0x00,
135 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x20, 0x00, 0x00,
136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
137 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
139 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
140 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00,
141 0x00, 0x00, 0x00, 0x10, 0x02, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142 0x00, 0x00, 0x09, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146 0x00, 0x08, 0x10, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x04, 0x40, 0x02,
147 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
148 0x02, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00,
153 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x04, 0x00, 0x00, 0x00, 0x00,
154 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0xac, 0x00, 0x00
157 static Color palette[] =
159 { 0xff, 0xff, 0xff, 0x00 },
160 { 0x00, 0x00, 0x00, 0xff },
161 { 0xff, 0xff, 0xc0, 0xff },
162 { 0x9f, 0x9f, 0x60, 0xff },
163 { 0x90, 0x00, 0x00, 0xff },
164 { 0x00, 0x90, 0x00, 0xff },
165 { 0x00, 0x00, 0x90, 0xff },
166 { 0xc0, 0xc0, 0xc0, 0xff }
169 // for alpha we use x^(1/1.3)
170 static Color palette2[] =
172 { 0x00, 0x00, 0x00, 0x00 },
173 { 0x00, 0x00, 0x00, 0x2e },
174 { 0x00, 0x00, 0x00, 0x48 },
175 { 0x00, 0x00, 0x00, 0x5d },
176 { 0x00, 0x00, 0x00, 0x6f },
177 { 0x00, 0x00, 0x00, 0x80 },
178 { 0x00, 0x00, 0x00, 0x8f },
179 { 0x00, 0x00, 0x00, 0x9e },
180 { 0x00, 0x00, 0x00, 0xac },
181 { 0x00, 0x00, 0x00, 0xb9 },
182 { 0x00, 0x00, 0x00, 0xc5 },
183 { 0x00, 0x00, 0x00, 0xd2 },
184 { 0x00, 0x00, 0x00, 0xdd },
185 { 0x00, 0x00, 0x00, 0xe9 },
186 { 0x00, 0x00, 0x00, 0xf4 },
187 { 0x00, 0x00, 0x00, 0xff }
190 static Color palette3[] =
192 { 0xff, 0xff, 0xff, 0xff },
193 { 0xe0, 0xe0, 0xe0, 0xff },
194 { 0xd0, 0xd0, 0xd0, 0xff },
195 { 0xc0, 0xc0, 0xc0, 0xff },
196 { 0xb0, 0xb0, 0xb0, 0xff },
197 { 0xa0, 0xa0, 0xa0, 0xff },
198 { 0x90, 0x90, 0x90, 0xff },
199 { 0x80, 0x80, 0x80, 0xff },
200 { 0x70, 0x70, 0x70, 0xff },
201 { 0x60, 0x60, 0x60, 0xff },
202 { 0x50, 0x50, 0x50, 0xff },
203 { 0x40, 0x40, 0x40, 0xff },
204 { 0x30, 0x30, 0x30, 0xff },
205 { 0x20, 0x20, 0x20, 0xff },
206 { 0x10, 0x10, 0x10, 0xff },
207 { 0x00, 0x00, 0x00, 0xff }
211 Image::Image(int w,int h)
213 static int hue = Config_getInt("HTML_COLORSTYLE_HUE");
214 static int sat = Config_getInt("HTML_COLORSTYLE_SAT");
215 static int gamma = Config_getInt("HTML_COLORSTYLE_GAMMA");
217 double red1,green1,blue1;
218 double red2,green2,blue2;
220 ColoredImage::hsl2rgb(hue/360.0, // hue
221 sat/255.0, // saturation
222 pow(235/255.0,gamma/100.0), // luma (gamma corrected)
226 ColoredImage::hsl2rgb(hue/360.0, // hue
227 sat/255.0, // saturation
228 pow(138/255.0,gamma/100.0), // luma (gamma corrected)
232 palette[2].red = (int)(red1 * 255.0);
233 palette[2].green = (int)(green1 * 255.0);
234 palette[2].blue = (int)(blue1 * 255.0);
236 palette[3].red = (int)(red2 * 255.0);
237 palette[3].green = (int)(green2 * 255.0);
238 palette[3].blue = (int)(blue2 * 255.0);
240 data = new uchar[w*h];
251 void Image::setPixel(int x,int y,uchar val)
253 if (x>=0 && x<width && y>=0 && y<height)
254 data[y*width+x] = val;
257 uchar Image::getPixel(int x,int y) const
259 if (x>=0 && x<width && y>=0 && y<height)
260 return data[y*width+x];
265 void Image::writeChar(int x,int y,char c,uchar fg)
271 int cw = charWidth[ci];
272 int cp = charPos[ci];
273 for (yf=0;yf<charHeight;yf++)
275 unsigned short bitPattern=0;
277 int byteOffset = rowOffset+(cp>>3);
278 int bitOffset = cp&7;
279 // get the bit pattern for row yf of the character from the font data
282 int bits=8-bitOffset;
283 if (bits>bitsLeft) bits=bitsLeft;
285 bitPattern|=((fontRaw[byteOffset]<<bitOffset)&0xff)>>(8-bits);
291 // draw character row yf
292 for (xf=0;xf<cw;xf++)
294 setPixel(x+xf,y+yf,(bitPattern&mask) ? fg : getPixel(x+xf,y+yf));
297 rowOffset+=charSetWidth;
302 void Image::writeString(int x,int y,const char *s,uchar fg)
315 uint Image::stringLength(const char *s)
321 while ((c=*s++)) w+=charWidth[c-' '];
326 void Image::drawHorzLine(int y,int xs,int xe,uchar colIndex,uint mask)
329 for (x=xs;x<=xe;x++,j++)
332 if (mask&(1<<(i&0x1f))) setPixel(x,y,colIndex);
336 void Image::drawHorzArrow(int y,int xs,int xe,uchar colIndex,uint mask)
338 drawHorzLine(y,xs,xe,colIndex,mask);
343 drawVertLine(xe-i,y-h,y+h,colIndex,0xffffffff);
347 void Image::drawVertLine(int x,int ys,int ye,uchar colIndex,uint mask)
350 for (y=ys;y<=ye;y++,i++)
352 if (mask&(1<<(i&0x1f))) setPixel(x,y,colIndex);
356 void Image::drawVertArrow(int x,int ys,int ye,uchar colIndex,uint mask)
358 drawVertLine(x,ys,ye,colIndex,mask);
363 drawHorzLine(ys+i,x-h,x+h,colIndex,0xffffffff);
367 void Image::drawRect(int x,int y,int w,int h,uchar colIndex,uint mask)
369 drawHorzLine(y,x,x+w-1,colIndex,mask);
370 drawHorzLine(y+h-1,x,x+w-1,colIndex,mask);
371 drawVertLine(x,y,y+h-1,colIndex,mask);
372 drawVertLine(x+w-1,y,y+h-1,colIndex,mask);
375 void Image::fillRect(int x,int y,int lwidth,int lheight,uchar colIndex,uint mask)
378 for (yp=y,yi=0;yp<y+lheight;yp++,yi++)
379 for (xp=x,xi=0;xp<x+lwidth;xp++,xi++)
380 if (mask&(1<<((xi+yi)&0x1f)))
381 setPixel(xp,yp,colIndex);
384 bool Image::save(const char *fileName,int mode)
387 GifEncoder gifenc(data,
388 mode==0 ? palette : palette2,
392 QFile file(fileName);
393 if (file.open(IO_WriteOnly))
395 gifenc.writeGIF(file);
403 static bool useTransparency = Config_getBool("FORMULA_TRANSPARENT");
406 LodePNG_Encoder encoder;
407 LodePNG_Encoder_init(&encoder);
408 int numCols = mode==0 ? 8 : 16;
409 Color *pPal = mode==0 ? palette :
410 useTransparency ? palette2 :
413 for (i=0;i<numCols;i++,pPal++)
415 LodePNG_InfoColor_addPalette(&encoder.infoPng.color,
416 pPal->red,pPal->green,pPal->blue,pPal->alpha);
418 encoder.infoPng.color.colorType = 3;
419 encoder.infoRaw.color.colorType = 3;
420 LodePNG_encode(&encoder, &buffer, &bufferSize, data, width, height);
421 LodePNG_saveFile(buffer, bufferSize, fileName);
423 LodePNG_Encoder_cleanup(&encoder);
427 //----------------------------------------------------------------
429 void ColoredImage::hsl2rgb(double h,double s,double l,
430 double *pRed,double *pGreen,double *pBlue)
435 r = l; // default to gray
438 v = (l <= 0.5) ? (l * (1.0 + s)) : (l + s - l * s);
444 double fract, vsf, mid1, mid2;
451 vsf = v * sv * fract;
493 ColoredImage::ColoredImage(int width,int height,
494 const uchar *greyLevels,const uchar *alphaLevels,
495 int saturation,int hue,int gamma)
497 m_hasAlpha = alphaLevels!=0;
500 m_data = (uchar*)malloc(width*height*4);
502 for (i=0;i<width*height;i++)
505 double red,green,blue;
506 hsl2rgb(hue/360.0, // hue
507 saturation/255.0, // saturation
508 pow(greyLevels[i]/255.0,gamma/100.0), // luma (gamma corrected)
510 r = (int)(red *255.0);
511 g = (int)(green*255.0);
512 b = (int)(blue *255.0);
513 a = alphaLevels ? alphaLevels[i] : 255;
521 ColoredImage::~ColoredImage()
526 bool ColoredImage::save(const char *fileName)
530 LodePNG_Encoder encoder;
531 LodePNG_Encoder_init(&encoder);
532 encoder.infoPng.color.colorType = m_hasAlpha ? 6 : 2; // 2=RGB 24 bit, 6=RGBA 32 bit
533 encoder.infoRaw.color.colorType = 6; // 6=RGBA 32 bit
534 LodePNG_encode(&encoder, &buffer, &bufferSize, m_data, m_width, m_height);
535 LodePNG_saveFile(buffer, bufferSize, fileName);
536 LodePNG_Encoder_cleanup(&encoder);