Canola  0.8.D001
lib/icon_pixel.h
Go to the documentation of this file.
00001 //
00002 // canola - canon canola 1614p emulator
00003 // Copyright (C) 2011 Peter Miller
00004 //
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License, version 3, as
00007 // published by the Free Software Foundation.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License along
00015 // with this program. If not, see <http://www.gnu.org/licenses/>.
00016 //
00017 
00018 #ifndef LIB_ICON_PIXEL_H
00019 #define LIB_ICON_PIXEL_H
00020 
00021 #include <lib/ac/math.h>
00022 #include <string>
00023 
00024 
00032 class icon_pixel
00033 {
00034 public:
00039     ~icon_pixel(){}
00040 
00041     static const icon_pixel black;
00042     static const icon_pixel white;
00043     static const icon_pixel transparent;
00044 
00045     typedef double real_type;
00046     typedef unsigned short short_type;
00047     typedef unsigned char byte_type;
00048 
00053     icon_pixel() :
00054         red_real(0),
00055         red_short(0),
00056         green_real(0),
00057         green_short(0),
00058         blue_real(0),
00059         blue_short(0),
00060         alpha_real(0),
00061         alpha_short(0),
00062         real_valid(true),
00063         short_valid(true)
00064     {
00065     }
00066 
00079     icon_pixel(short_type rr, short_type gg, short_type bb) :
00080         red_real(0),
00081         red_short(rr),
00082         green_real(0),
00083         green_short(gg),
00084         blue_real(0),
00085         blue_short(bb),
00086         alpha_real(1.),
00087         alpha_short(65535),
00088         real_valid(false),
00089         short_valid(true)
00090     {
00091     }
00092 
00105     icon_pixel(short_type rr, short_type gg, short_type bb, short_type aa) :
00106         red_real(0),
00107         red_short(aa ? rr : 0),
00108         green_real(0),
00109         green_short(aa ? gg : 0),
00110         blue_real(0),
00111         blue_short(aa ? bb : 0),
00112         alpha_real(0),
00113         alpha_short(aa),
00114         real_valid(false),
00115         short_valid(true)
00116     {
00117     }
00118 
00131     icon_pixel(real_type rr, real_type gg, real_type bb) :
00132         red_real(rr),
00133         red_short(0),
00134         green_real(gg),
00135         green_short(0),
00136         blue_real(bb),
00137         blue_short(0),
00138         alpha_real(1.0),
00139         alpha_short(65535),
00140         real_valid(true),
00141         short_valid(false)
00142     {
00143     }
00144 
00157     icon_pixel(real_type rr, real_type gg, real_type bb, real_type aa) :
00158         red_real(aa > 0 ? rr : 0),
00159         red_short(0),
00160         green_real(aa > 0 ? gg : 0),
00161         green_short(0),
00162         blue_real(aa > 0 ? bb : 0),
00163         blue_short(0),
00164         alpha_real(aa),
00165         alpha_short(0),
00166         real_valid(true),
00167         short_valid(false)
00168     {
00169     }
00170 
00174     icon_pixel(const icon_pixel &arg) :
00175         red_real(arg.red_real),
00176         red_short(arg.red_short),
00177         green_real(arg.green_real),
00178         green_short(arg.green_short),
00179         blue_real(arg.blue_real),
00180         blue_short(arg.blue_short),
00181         alpha_real(arg.alpha_real),
00182         alpha_short(arg.alpha_short),
00183         real_valid(arg.real_valid),
00184         short_valid(arg.short_valid)
00185     {
00186     }
00187 
00191     icon_pixel &
00192     operator=(const icon_pixel &arg)
00193     {
00194         if (this != &arg)
00195         {
00196             red_real = arg.red_real;
00197             red_short = arg.red_short;
00198             green_real = arg.green_real;
00199             green_short = arg.green_short;
00200             blue_real = arg.blue_real;
00201             blue_short = arg.blue_short;
00202             alpha_real = arg.alpha_real;
00203             alpha_short = arg.alpha_short;
00204             real_valid = arg.real_valid;
00205             short_valid = arg.short_valid;
00206         }
00207         return *this;
00208     }
00209 
00215     bool
00216     is_transparent(void)
00217         const
00218     {
00219         return (short_valid ? (alpha_short == 0) : (alpha_real < 0.002));
00220     }
00221 
00227     bool
00228     is_opaque(void)
00229         const
00230     {
00231         return (short_valid ? (alpha_short >= 65408) : (alpha_real >= 1.0));
00232     }
00233 
00239     icon_pixel
00240     invert(void)
00241         const
00242     {
00243         return
00244             (
00245                 real_valid
00246             ?
00247                 icon_pixel
00248                 (
00249                     1. - red_real,
00250                     1. - green_real,
00251                     1. - blue_real,
00252                     alpha_real
00253                 )
00254             :
00255                 icon_pixel
00256                 (
00257                     short_type(65535 - red_short),
00258                     short_type(65535 - green_short),
00259                     short_type(65535 - blue_short),
00260                     alpha_short
00261                 )
00262             );
00263     }
00264 
00265     real_type
00266     get_red(void)
00267         const
00268     {
00269         if (!real_valid)
00270             convert_short_to_real();
00271         return red_real;
00272     }
00273 
00274     real_type
00275     get_green(void)
00276         const
00277     {
00278         if (!real_valid)
00279             convert_short_to_real();
00280         return green_real;
00281     }
00282 
00283     real_type
00284     get_blue(void)
00285         const
00286     {
00287         if (!real_valid)
00288             convert_short_to_real();
00289         return blue_real;
00290     }
00291 
00292     real_type
00293     get_alpha(void)
00294         const
00295     {
00296         if (!real_valid)
00297             convert_short_to_real();
00298         return alpha_real;
00299     }
00300 
00301     short_type
00302     get_red_short(void)
00303         const
00304     {
00305         if (!short_valid)
00306             convert_real_to_short();
00307         return red_short;
00308     }
00309 
00310     byte_type
00311     get_red_byte(void)
00312         const
00313     {
00314         if (!short_valid)
00315             convert_real_to_short();
00316         return (red_short >> 8);
00317     }
00318 
00319     short_type
00320     get_green_short(void)
00321         const
00322     {
00323         if (!short_valid)
00324             convert_real_to_short();
00325         return green_short;
00326     }
00327 
00328     byte_type
00329     get_green_byte(void)
00330         const
00331     {
00332         if (!short_valid)
00333             convert_real_to_short();
00334         return (green_short >> 8);
00335     }
00336 
00337     short_type
00338     get_blue_short(void)
00339         const
00340     {
00341         if (!short_valid)
00342             convert_real_to_short();
00343         return blue_short;
00344     }
00345 
00346     byte_type
00347     get_blue_byte(void)
00348         const
00349     {
00350         if (!short_valid)
00351             convert_real_to_short();
00352         return (blue_short >> 8);
00353     }
00354 
00355     short_type
00356     get_alpha_short(void)
00357         const
00358     {
00359         if (!short_valid)
00360             convert_real_to_short();
00361         return alpha_short;
00362     }
00363 
00364     byte_type
00365     get_alpha_byte(void)
00366         const
00367     {
00368         if (!short_valid)
00369             convert_real_to_short();
00370         return (alpha_short >> 8);
00371     }
00372 
00377     std::string representation(void) const;
00378 
00386     bool operator==(const icon_pixel &rhs) const;
00387 
00395     bool
00396     operator!=(const icon_pixel &rhs)
00397         const
00398     {
00399         return !operator==(rhs);
00400     }
00401 
00405     void operator*=(const icon_pixel &rhs);
00406 
00410     icon_pixel operator*(const icon_pixel &rhs) const;
00411 
00415     void operator*=(double);
00416 
00420     icon_pixel operator*(double) const;
00421 
00426     icon_pixel monochrome(void) const;
00427 
00432     real_type get_intensity(void) const;
00433 
00438     static short_type
00439     short_from_byte(byte_type x)
00440     {
00441         return ((short_type(x) << 8) | short_type(x));
00442     }
00443 
00444 private:
00450     mutable real_type red_real;
00451 
00456     mutable short_type red_short;
00457 
00463     mutable real_type green_real;
00464 
00469     mutable short_type green_short;
00470 
00476     mutable real_type blue_real;
00477 
00482     mutable short_type blue_short;
00483 
00489     mutable real_type alpha_real;
00490 
00495     mutable short_type alpha_short;
00496 
00501     mutable bool real_valid;
00502 
00507     mutable bool short_valid;
00508 
00517     static short_type
00518     convert_channel_real_to_short(real_type x)
00519     {
00520         // multiply by 65535 is slow, so break it up
00521         unsigned n = x * 65536;
00522         n -= (n >> 16);
00523         return n;
00524     }
00525 
00530     void
00531     convert_real_to_short(void)
00532         const
00533     {
00534         red_short = convert_channel_real_to_short(red_real);
00535         green_short = convert_channel_real_to_short(green_real);
00536         blue_short = convert_channel_real_to_short(blue_real);
00537         alpha_short = convert_channel_real_to_short(alpha_real);
00538         short_valid = true;
00539     }
00540 
00548     static real_type
00549     convert_channel_short_to_real(short_type x)
00550     {
00551         if (x >= 65535)
00552             return 1;
00553         return ldexp(real_type(x), -16);
00554     }
00555 
00556     void
00557     convert_short_to_real(void)
00558         const
00559     {
00560         red_real = convert_channel_short_to_real(red_short);
00561         green_real = convert_channel_short_to_real(green_short);
00562         blue_real = convert_channel_short_to_real(blue_short);
00563         alpha_real = convert_channel_short_to_real(alpha_short);
00564         real_valid = true;
00565     }
00566 };
00567 
00568 #endif // LIB_ICON_PIXEL_H