2 * psychlops_g_image_Win32_GL.cpp
3 * Psychlops Standard Library (Universal)
5 * Last Modified 2007/07/07 by Kenchi HOSOKAWA
6 * (C) 2006 Kenchi HOSOKAWA, Kazushi MARUYA and Takao SATO
15 #define PSYCHLOPS_WINDOW_API_PLATFORM
16 #include "../psychlops_platform_selector.h"
17 #include "../../core/graphic/psychlops_g_image.h"
23 const int APIImageProperties::PixCompGL_[3] = { GL_LUMINANCE, GL_RGB, GL_RGBA };
24 const int APIImageProperties::PixPrecGL_[2] = { GL_UNSIGNED_BYTE, GL_FLOAT };
27 class ImageManipulator {
29 inline static int pix_offset(const Image &img, const int x, const int iy) {
30 int y = img.height_-iy-1;
31 if(0>x || x>img.width_-1 || y<0 || y>img.height_-1) throw Exception(typeid(Image), "Out Of Bound Exception", "Specified coordinate is out of bound.");
32 return y*img.lineValue_ + x*img.PixCompSize_[img.pixcomp_];
34 inline static unsigned char round8bit(double value) {
35 double val = value*255.0+0.5, integer_part, frac;
36 frac = modf(val, &integer_part);
37 if(frac!=0.0) return (unsigned char)integer_part;
38 if((int)(integer_part)%2==0) return (unsigned char)integer_part; else return (unsigned char)integer_part-1;
43 inline static void pix_gen_ub_1(unsigned char *p, const Color &col) { *(p) = round8bit(col.Red); }
44 inline static void pix_gen_ub_3(unsigned char *p, const Color &col) { *(p) = round8bit(col.Red); *(++p) = round8bit(col.Green); *(++p) = round8bit(col.Blue); }
45 inline static void pix_gen_ub_4(unsigned char *p, const Color &col) { *(p) = round8bit(col.Red); *(++p) = round8bit(col.Green); *(++p) = round8bit(col.Blue); *(++p) = round8bit(col.Alpha); }
\r
46 inline static void pix_gen_f_1(float *p, const Color &col) { *(p) = (float)(col.Red); }
47 inline static void pix_gen_f_3(float *p, const Color &col) { *(p) = (float)(col.Red); *(++p) = (float)(col.Green); *(++p) = (float)(col.Blue); }
48 inline static void pix_gen_f_4(float *p, const Color &col) { *(p) = (float)(col.Red); *(++p) = (float)(col.Green); *(++p) = (float)(col.Blue); *(++p) = (float)(col.Alpha); }
52 static void (*(pix_direct_[2][3]))(const Image &, const int, const int, const Color&);// = { { &pix_d_ub_l_, &pix_d_ub_rgb_ , &pix_d_ub_rgba_ } , { &pix_d_f_l_, &pix_d_f_rgb_ , &pix_d_f_rgba_ } };
54 static void pix_d_ub_l_ (const Image &img, const int ix, const int iy, const Color &col) { pix_gen_ub_1( img.bitmapub_ + pix_offset(img, ix, iy), col ); }
55 static void pix_d_f_l_ (const Image &img, const int ix, const int iy, const Color &col) { pix_gen_f_1 ( img.bitmapf_ + pix_offset(img, ix, iy), col ); }
56 static void pix_d_ub_rgb_ (const Image &img, const int ix, const int iy, const Color &col) { pix_gen_ub_3( img.bitmapub_ + pix_offset(img, ix, iy), col ); }
57 static void pix_d_f_rgb_ (const Image &img, const int ix, const int iy, const Color &col) { pix_gen_f_3 ( img.bitmapf_ + pix_offset(img, ix, iy), col ); }
58 static void pix_d_ub_rgba_(const Image &img, const int ix, const int iy, const Color &col) { pix_gen_ub_4( img.bitmapub_ + pix_offset(img, ix, iy), col ); }
59 static void pix_d_f_rgba_ (const Image &img, const int ix, const int iy, const Color &col) { pix_gen_f_4 ( img.bitmapf_ + pix_offset(img, ix, iy), col ); }
62 // ALPHA BLENDING INCLUDED
64 static void (*(pix_[2][3]))(const Image &, const int, const int, const Color&);// = { { &pix_ub_l_, &pix_ub_rgb_ , &pix_ub_rgba_ } , { &pix_f_l_, &pix_f_rgb_ , &pix_f_rgba_ } };
66 static void pix_ub_l_(const Image &img, const int ix, const int iy, const Color &col) {
67 pix_gen_ub_1(img.bitmapub_ + pix_offset(img, ix, iy), col);
69 static void pix_f_l_(const Image &img, const int ix, const int iy, const Color &col) {
70 pix_gen_f_1(img.bitmapf_ + pix_offset(img, ix, iy), col);
72 static void pix_ub_rgb_(const Image &img, const int ix, const int iy, const Color &col) {
73 unsigned char *p = img.bitmapub_ + pix_offset(img, ix, iy);
74 if(Color::getCalibrationMode()==Color::SOFTWARE_GAMMA_VALUE || Color::getCalibrationMode()==Color::SOFTWARE_TABLE) {
75 double red, green, blue, alpha;
76 col.get(red, green, blue, alpha);
77 Color xcol = getpix_ub_rgb_(img, ix, iy);
78 double xred, xgreen, xblue, xalpha;
79 xcol.get(xred, xgreen, xblue, xalpha);
81 (1.0-alpha)*xred + alpha*red,
82 (1.0-alpha)*xgreen + alpha*green,
83 (1.0-alpha)*xblue + alpha*blue,
84 (1.0-alpha)*xalpha + alpha*alpha
86 *(p) = round8bit(ycol.Red);
87 *(++p) = round8bit(ycol.Green);
88 *(++p) = round8bit(ycol.Blue);
90 *(p) = round8bit(((1.0-col.Alpha)*(*p/255.0) + col.Alpha*col.Red)); p++;
91 *(p) = round8bit(((1.0-col.Alpha)*(*p/255.0) + col.Alpha*col.Green)); p++;
92 *(p) = round8bit(((1.0-col.Alpha)*(*p/255.0) + col.Alpha*col.Blue)); p++;
95 static void pix_f_rgb_(const Image &img, const int ix, const int iy, const Color &col) {
96 float *p = img.bitmapf_ + pix_offset(img, ix, iy);
97 if(Color::getCalibrationMode()==Color::SOFTWARE_GAMMA_VALUE || Color::getCalibrationMode()==Color::SOFTWARE_TABLE) {
98 double red, green, blue, alpha;
99 col.get(red, green, blue, alpha);
100 Color xcol = getpix_f_rgba_(img, ix, iy);
101 double xred, xgreen, xblue, xalpha;
102 xcol.get(xred, xgreen, xblue, xalpha);
104 (1.0-alpha)*xred + alpha*red,
105 (1.0-alpha)*xgreen + alpha*green,
106 (1.0-alpha)*xblue + alpha*blue,
107 (1.0-alpha)*xalpha + alpha*alpha
109 *(p) = (float)(ycol.Red);
110 *(++p) = (float)(ycol.Green);
111 *(++p) = (float)(ycol.Blue);
113 *(p) = (float)((1.0-col.Alpha)*(*p) + col.Alpha*col.Red);
114 *(++p) = (float)((1.0-col.Alpha)*(*p) + col.Alpha*col.Green);
115 *(++p) = (float)((1.0-col.Alpha)*(*p) + col.Alpha*col.Blue);
118 static void pix_ub_rgba_(const Image &img, const int ix, const int iy, const Color &col) {
119 unsigned char *p = img.bitmapub_ + pix_offset(img, ix, iy);
120 if(Color::getCalibrationMode()==Color::SOFTWARE_GAMMA_VALUE || Color::getCalibrationMode()==Color::SOFTWARE_TABLE) {
121 double red, green, blue, alpha;
122 col.get(red, green, blue, alpha);
123 Color xcol = getpix_ub_rgba_(img, ix, iy);
124 double xred, xgreen, xblue, xalpha;
125 xcol.get(xred, xgreen, xblue, xalpha);
127 (1.0-alpha)*xred + alpha*red,
128 (1.0-alpha)*xgreen + alpha*green,
129 (1.0-alpha)*xblue + alpha*blue,
130 (1.0-alpha)*xalpha + alpha*alpha
132 *(p) = round8bit(ycol.Red);
133 *(++p) = round8bit(ycol.Green);
134 *(++p) = round8bit(ycol.Blue);
135 *(++p) = round8bit(ycol.Alpha);
137 *(p) = round8bit(((1.0-col.Alpha)*(*p/255.0) + col.Alpha*col.Red)); p++;
138 *(p) = round8bit(((1.0-col.Alpha)*(*p/255.0) + col.Alpha*col.Green)); p++;
139 *(p) = round8bit(((1.0-col.Alpha)*(*p/255.0) + col.Alpha*col.Blue)); p++;
140 *(p) = round8bit(((1.0-col.Alpha)*(*p/255.0) + col.Alpha*col.Alpha));
143 static void pix_f_rgba_(const Image &img, const int ix, const int iy, const Color &col) {
144 float *p = img.bitmapf_ + pix_offset(img, ix, iy);
145 if(Color::getCalibrationMode()==Color::SOFTWARE_GAMMA_VALUE || Color::getCalibrationMode()==Color::SOFTWARE_TABLE) {
146 double red, green, blue, alpha;
147 col.get(red, green, blue, alpha);
148 Color xcol = getpix_f_rgba_(img, ix, iy);
149 double xred, xgreen, xblue, xalpha;
150 xcol.get(xred, xgreen, xblue, xalpha);
152 (1.0-alpha)*xred + alpha*red,
153 (1.0-alpha)*xgreen + alpha*green,
154 (1.0-alpha)*xblue + alpha*blue,
155 (1.0-alpha)*xalpha + alpha*alpha
157 *(p) = (float)(ycol.Red);
158 *(++p) = (float)(ycol.Green);
159 *(++p) = (float)(ycol.Blue);
160 *(++p) = (float)(ycol.Alpha);
162 *(p) = (float)((1.0-col.Alpha)*(*p) + col.Alpha*col.Red);
163 *(++p) = (float)((1.0-col.Alpha)*(*p) + col.Alpha*col.Green);
164 *(++p) = (float)((1.0-col.Alpha)*(*p) + col.Alpha*col.Blue);
165 *(++p) = (float)((1.0-col.Alpha)*(*p) + col.Alpha*col.Alpha);
170 static void (*(pix_alpha_[2][3]))(const Image &, const int, const int, const double);// = { { &alpha_null_, &alpha_null_ , &alpha_ub_rgba_ } , { &alpha_null_, &alpha_null_ , &alphs_f_rgba_ } };
172 static void alpha_null_(const Image &img, const int ix, const int iy, const double alpha) {
173 int x = ix, y = img.height_-iy-1;
174 if(0>x || x>img.width_-1 || y<0 || y>img.height_-1) throw Exception(typeid(Image), "Out Of Bound Exception", "Specified coordinate is out of bound.");
176 static void alpha_ub_rgba_(const Image &img, const int ix, const int iy, const double alpha) {
177 int x = ix, y = img.height_-iy-1;
178 if(0>x || x>img.width_-1 || y<0 || y>img.height_-1) throw Exception(typeid(Image), "Out Of Bound Exception", "Specified coordinate is out of bound.");
179 int offset = y*img.lineValue_ + x*img.PixCompSize_[img.pixcomp_];
180 unsigned char *p = img.bitmapub_ + offset;
181 *(p+3) = round8bit(alpha);
183 static void alpha_f_rgba_(const Image &img, const int ix, const int iy, const double alpha) {
184 int x = ix, y = img.height_-iy-1;
185 if(0>x || x>img.width_-1 || y<0 || y>img.height_-1) throw Exception(typeid(Image), "Out Of Bound Exception", "Specified coordinate is out of bound.");
186 int offset = y*img.lineValue_ + x*img.PixCompSize_[img.pixcomp_];
187 float *p = img.bitmapf_ + offset;
188 *(p+3) = (float)alpha;
193 static Color (*(getpix_[2][3]))(const Image &, int, int);// = { { &getpix_ub_l_, &getpix_ub_rgb_ , &getpix_ub_rgba_ } , { &getpix_f_l_, &getpix_f_rgb_ , &getpix_f_rgba_ } };
195 static Color getpix_ub_l_(const Image &img, int ix, int iy) {
196 int x = ix, y = img.height_-iy-1;
197 if(0>x || x>img.width_-1 || y<0 || y>img.height_-1) throw Exception(typeid(Image), "Out Of Bound Exception", "Specified coordinate is out of bound.");
198 int offset = y*img.lineValue_ + x*img.PixCompSize_[img.pixcomp_];
199 return Color(*(img.bitmapub_+offset)/255.0, *(img.bitmapub_+offset)/255.0, *(img.bitmapub_+offset)/255.0, 1.0, false);
201 static Color getpix_f_l_(const Image &img, int ix, int iy) {
202 int x = ix, y = img.height_-iy-1;
203 if(0>x || x>img.width_-1 || y<0 || y>img.height_-1) throw Exception(typeid(Image), "Out Of Bound Exception", "Specified coordinate is out of bound.");
204 int offset = y*img.lineValue_ + x*img.PixCompSize_[img.pixcomp_];
205 return Color(*(img.bitmapf_+offset), *(img.bitmapf_+offset), *(img.bitmapf_+offset), 1.0, false);
207 static Color getpix_ub_rgb_(const Image &img, int ix, int iy) {
208 int x = ix, y = img.height_-iy-1;
209 if(0>x || x>img.width_-1 || y<0 || y>img.height_-1) throw Exception(typeid(Image), "Out Of Bound Exception", "Specified coordinate is out of bound.");
210 int offset = y*img.lineValue_ + x*img.PixCompSize_[img.pixcomp_];
211 unsigned char *bitmapub_ = img.bitmapub_ + offset;
212 return Color(*(bitmapub_)/255.0, *(bitmapub_+1)/255.0, *(bitmapub_+2)/255.0, 1.0, false);
214 static Color getpix_f_rgb_(const Image &img, int ix, int iy) {
215 int x = ix, y = img.height_-iy-1;
216 if(0>x || x>img.width_-1 || y<0 || y>img.height_-1) throw Exception(typeid(Image), "Out Of Bound Exception", "Specified coordinate is out of bound.");
217 int offset = y*img.lineValue_ + x*img.PixCompSize_[img.pixcomp_];
218 float *bitmapf_ = img.bitmapf_ + offset;
219 return Color(*(bitmapf_), *(bitmapf_+1), *(bitmapf_+2), 1.0, false);
221 static Color getpix_ub_rgba_(const Image &img, int ix, int iy) {
222 int x = ix, y = img.height_-iy-1;
223 if(0>x || x>img.width_-1 || y<0 || y>img.height_-1) throw Exception(typeid(Image), "Out Of Bound Exception", "Specified coordinate is out of bound.");
224 int offset = y*img.lineValue_ + x*img.PixCompSize_[img.pixcomp_];
225 unsigned char *bitmapub_ = img.bitmapub_ + offset;
226 return Color(*(bitmapub_)/255.0, *(bitmapub_+1)/255.0, *(bitmapub_+2)/255.0, *(bitmapub_+3)/255.0 , false);
228 static Color getpix_f_rgba_(const Image &img, int ix, int iy) {
229 int x = ix, y = img.height_-iy-1;
230 if(0>x || x>img.width_-1 || y<0 || y>img.height_-1) throw Exception(typeid(Image), "Out Of Bound Exception", "Specified coordinate is out of bound.");
231 int offset = y*img.lineValue_ + x*img.PixCompSize_[img.pixcomp_];
232 float *bitmapf_ = img.bitmapf_ + offset;
233 return Color(*(bitmapf_), *(bitmapf_+1), *(bitmapf_+2), *(bitmapf_+3), false);
236 void (*(ImageManipulator::pix_[2][3]))(const Image &, const int, const int, const Color&) = { { &pix_ub_l_, &pix_ub_rgb_ , &pix_ub_rgba_ } , { &pix_f_l_, &pix_f_rgb_ , &pix_f_rgba_ } };
237 void (*(ImageManipulator::pix_direct_[2][3]))(const Image &, const int, const int, const Color&) = { { &pix_d_ub_l_, &pix_d_ub_rgb_ , &pix_d_ub_rgba_ } , { &pix_d_f_l_, &pix_d_f_rgb_ , &pix_d_f_rgba_ } };
238 void (*(ImageManipulator::pix_alpha_[2][3]))(const Image &, const int, const int, const double) = { { &alpha_null_, &alpha_null_ , &alpha_ub_rgba_ } , { &alpha_null_, &alpha_null_ , &alpha_f_rgba_ } };
239 Color (*(ImageManipulator::getpix_[2][3]))(const Image &, int, int) = { { &getpix_ub_l_, &getpix_ub_rgb_ , &getpix_ub_rgba_ } , { &getpix_f_l_, &getpix_f_rgb_ , &getpix_f_rgba_ } };
242 Image& Image::pix(const int ix, const int iy, const Color &col) {
243 pix_(*this, ix, iy, col);
247 Color Image::getPix(int ix, int iy) const {
248 return getpix_(*this, ix, iy);
252 void Image::line_direct_copy_(const Image &src, Image &tgt, const int iy, const int jy) {
253 int sy = src.height_-iy-1, ty = jy<0 ? tgt.height_-iy-1 : tgt.height_-jy-1;
254 if(sy<0 || sy>src.height_-1) throw Exception(typeid(Image), "Out Of Bound Exception", "Specified coordinate is out of bound.");
255 size_t bytes = ( src.lineBytes_>tgt.lineBytes_ ? tgt.lineBytes_ : src.lineBytes_ );
256 switch(src.pixprec_) {
258 memcpy((void *)(tgt.bitmapub_+ty*tgt.lineValue_), (void *)(src.bitmapub_+sy*src.lineValue_), bytes);
261 memcpy((void *)(tgt.bitmapf_+ty*tgt.lineValue_), (void *)(src.bitmapf_+sy*src.lineValue_), bytes);
264 throw Exception(typeid(Image), "Format Error", "Class Image recieved unknown format for pixels.");
270 void Image::set(long ix, long iy, PixelComponentsCnt pixcomp, PixelComponentsPrecision pixprec) {
271 if(have_instance_) throw Exception(typeid(*this), "Memory Error", "Image object already has its bitmap.");
273 // init basic properties
274 if(ix<=0) throw Exception(typeid(*this), "FORMAT ERROR", "The specified width is illegal");
276 if(iy<=0) throw Exception(typeid(*this), "FORMAT ERROR", "The specified height is illegal");
278 if(pixcomp<0) throw Exception(typeid(*this), "FORMAT ERROR", "The specified pixel component is illegal"); else
279 if(pixcomp>=3) throw Exception(typeid(*this), "FORMAT ERROR", "The specified pixel component is illegal"); else
281 if(pixprec<0) throw Exception(typeid(*this), "FORMAT ERROR", "The specified precision is illegal"); else
282 if(pixprec>=2) throw Exception(typeid(*this), "FORMAT ERROR", "The specified precision is illegal"); else
285 // init calculable parameters
286 targetarea_ = localarea_ = area_ = Rectangle(width_, height_);
287 pixBytes_ = PixCompSize_[pixcomp_] * PixPrecSize_[pixprec_];
288 lineBytes_ = pixBytes_ * width_;
289 lineBytes_ = ( (lineBytes_%lineBytesAlingnment_==0 ? 0 : 1) + ((int)lineBytes_ / (int)lineBytesAlingnment_) ) * lineBytesAlingnment_;
290 bitmapBytes_ = lineBytes_ * height_;
291 lineValue_ = lineBytes_ / PixPrecSize_[pixprec_];
292 bitmapValue_ = lineValue_ * height_;
296 if(NULL==(bitmapub_ = new GLubyte[bitmapValue_])) throw Exception(typeid(*this), "Memory Error", "Image failed to allocate memory.");
300 if(NULL==(bitmapf_ = new GLfloat[bitmapValue_])) throw Exception(typeid(*this), "Memory Error", "Image failed to allocate memory.");
304 throw Exception(typeid(*this), "Format Error", "Class Image recieved unknown format for pixels.");
307 api_ = new APIImageProperties(this);
308 pix_ = ImageManipulator::pix_[pixprec_][pixcomp_];
309 pix_direct_ = ImageManipulator::pix_direct_[pixprec_][pixcomp_];
310 pix_alpha_ = ImageManipulator::pix_alpha_[pixprec_][pixcomp_];
311 getpix_ = ImageManipulator::getpix_[pixprec_][pixcomp_];
312 have_instance_ = true;
313 if(!setWithoutClear_) clear(Color::black);
316 void Image::from(const Image &readimage) {
319 api_ = new APIImageProperties(this);
321 void *target_bitmap, *source_bitmap;
325 if(NULL==(bitmapub_ = new GLubyte[bitmapValue_])) throw Exception(typeid(*this), "Memory Error", "Image failed to allocate memory.");
326 target_bitmap = (void *)(bitmapub_);
327 source_bitmap = (void *)(readimage.bitmapub_);
330 if(NULL==(bitmapf_ = new GLfloat[bitmapValue_])) throw Exception(typeid(*this), "Memory Error", "Image failed to allocate memory.");
331 target_bitmap = (void *)(bitmapf_);
332 source_bitmap = (void *)(readimage.bitmapf_);
335 throw Exception(typeid(*this), "Format Error", "Class Image recieved unknown format for pixels.");
338 memcpy(target_bitmap, source_bitmap, bitmapBytes_);
339 have_instance_ = true;
345 } /* <- namespace Psycholops */