00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef GRAPHICS_HPP
00026 #define GRAPHICS_HPP
00027
00028 #include <mapnik/color.hpp>
00029 #include <mapnik/gamma.hpp>
00030 #include <mapnik/image_data.hpp>
00031 #include <mapnik/envelope.hpp>
00032 #include <mapnik/image_view.hpp>
00033
00034 #include <cmath>
00035 #include <string>
00036 #include <cassert>
00037
00038 namespace mapnik
00039 {
00040 class MAPNIK_DECL Image32
00041 {
00042 private:
00043 unsigned width_;
00044 unsigned height_;
00045 Color background_;
00046 ImageData32 data_;
00047 public:
00048 Image32(int width,int height);
00049 Image32(Image32 const& rhs);
00050 ~Image32();
00051 void setBackground(Color const& background);
00052 const Color& getBackground() const;
00053 const ImageData32& data() const;
00054
00055 inline ImageData32& data()
00056 {
00057 return data_;
00058 }
00059
00060 inline const unsigned char* raw_data() const
00061 {
00062 return data_.getBytes();
00063 }
00064
00065 inline unsigned char* raw_data()
00066 {
00067 return data_.getBytes();
00068 }
00069
00070 inline image_view<ImageData32> get_view(unsigned x,unsigned y, unsigned w,unsigned h)
00071 {
00072 return image_view<ImageData32>(x,y,w,h,data_);
00073 }
00074
00075 private:
00076
00077 inline bool checkBounds(unsigned x, unsigned y) const
00078 {
00079 return (x < width_ && y < height_);
00080 }
00081
00082 public:
00083 inline void setPixel(int x,int y,unsigned int rgba)
00084 {
00085 if (checkBounds(x,y))
00086 {
00087 data_(x,y)=rgba;
00088 }
00089 }
00090 inline void blendPixel(int x,int y,unsigned int rgba1,int t)
00091 {
00092 if (checkBounds(x,y))
00093 {
00094 unsigned rgba0 = data_(x,y);
00095 unsigned a1 = (rgba1 >> 24) & 0xff;
00096 a1 = (t*a1) / 255;
00097 if (a1 == 0) return;
00098 unsigned r1 = rgba1 & 0xff;
00099 unsigned g1 = (rgba1 >> 8 ) & 0xff;
00100 unsigned b1 = (rgba1 >> 16) & 0xff;
00101
00102 unsigned a0 = (rgba0 >> 24) & 0xff;
00103 unsigned r0 = (rgba0 & 0xff) * a0;
00104 unsigned g0 = ((rgba0 >> 8 ) & 0xff) * a0;
00105 unsigned b0 = ((rgba0 >> 16) & 0xff) * a0;
00106
00107 a0 = ((a1 + a0) << 8) - a0*a1;
00108
00109 r0 = ((((r1 << 8) - r0) * a1 + (r0 << 8)) / a0);
00110 g0 = ((((g1 << 8) - g0) * a1 + (g0 << 8)) / a0);
00111 b0 = ((((b1 << 8) - b0) * a1 + (b0 << 8)) / a0);
00112 a0 = a0 >> 8;
00113 data_(x,y)= (a0 << 24)| (b0 << 16) | (g0 << 8) | (r0) ;
00114 }
00115 }
00116
00117 inline unsigned width() const
00118 {
00119 return width_;
00120 }
00121
00122 inline unsigned height() const
00123 {
00124 return height_;
00125 }
00126
00127 inline void set_rectangle(int x0,int y0,ImageData32 const& data)
00128 {
00129 Envelope<int> ext0(0,0,width_,height_);
00130 Envelope<int> ext1(x0,y0,x0+data.width(),y0+data.height());
00131
00132 if (ext0.intersects(ext1))
00133 {
00134 Envelope<int> box = ext0.intersect(ext1);
00135 for (int y = box.miny(); y < box.maxy(); ++y)
00136 {
00137 unsigned int* row_to = data_.getRow(y);
00138 unsigned int const * row_from = data.getRow(y-y0);
00139
00140 for (int x = box.minx(); x < box.maxx(); ++x)
00141 {
00142 if (row_from[x-x0] & 0xff000000)
00143 {
00144 row_to[x] = row_from[x-x0];
00145 }
00146 }
00147 }
00148 }
00149 }
00150
00151 inline void set_rectangle_alpha(int x0,int y0,const ImageData32& data)
00152 {
00153 Envelope<int> ext0(0,0,width_,height_);
00154 Envelope<int> ext1(x0,y0,x0 + data.width(),y0 + data.height());
00155
00156 if (ext0.intersects(ext1))
00157 {
00158 Envelope<int> box = ext0.intersect(ext1);
00159 for (int y = box.miny(); y < box.maxy(); ++y)
00160 {
00161 unsigned int* row_to = data_.getRow(y);
00162 unsigned int const * row_from = data.getRow(y-y0);
00163 for (int x = box.minx(); x < box.maxx(); ++x)
00164 {
00165 unsigned rgba0 = row_to[x];
00166 unsigned rgba1 = row_from[x-x0];
00167
00168 unsigned a1 = (rgba1 >> 24) & 0xff;
00169 if (a1 == 0) continue;
00170 unsigned r1 = rgba1 & 0xff;
00171 unsigned g1 = (rgba1 >> 8 ) & 0xff;
00172 unsigned b1 = (rgba1 >> 16) & 0xff;
00173
00174 unsigned a0 = (rgba0 >> 24) & 0xff;
00175 unsigned r0 = (rgba0 & 0xff) * a0;
00176 unsigned g0 = ((rgba0 >> 8 ) & 0xff) * a0;
00177 unsigned b0 = ((rgba0 >> 16) & 0xff) * a0;
00178
00179 a0 = ((a1 + a0) << 8) - a0*a1;
00180
00181 r0 = ((((r1 << 8) - r0) * a1 + (r0 << 8)) / a0);
00182 g0 = ((((g1 << 8) - g0) * a1 + (g0 << 8)) / a0);
00183 b0 = ((((b1 << 8) - b0) * a1 + (b0 << 8)) / a0);
00184 a0 = a0 >> 8;
00185 row_to[x] = (a0 << 24)| (b0 << 16) | (g0 << 8) | (r0) ;
00186 }
00187 }
00188 }
00189 }
00190
00191 inline void set_rectangle_alpha2(ImageData32 const& data, unsigned x0, unsigned y0, float opacity)
00192 {
00193 Envelope<int> ext0(0,0,width_,height_);
00194 Envelope<int> ext1(x0,y0,x0 + data.width(),y0 + data.height());
00195
00196 if (ext0.intersects(ext1))
00197 {
00198 Envelope<int> box = ext0.intersect(ext1);
00199 for (int y = box.miny(); y < box.maxy(); ++y)
00200 {
00201 unsigned int* row_to = data_.getRow(y);
00202 unsigned int const * row_from = data.getRow(y-y0);
00203 for (int x = box.minx(); x < box.maxx(); ++x)
00204 {
00205 unsigned rgba0 = row_to[x];
00206 unsigned rgba1 = row_from[x-x0];
00207 unsigned a1 = int( ((rgba1 >> 24) & 0xff) * opacity );
00208 if (a1 == 0) continue;
00209 unsigned r1 = rgba1 & 0xff;
00210 unsigned g1 = (rgba1 >> 8 ) & 0xff;
00211 unsigned b1 = (rgba1 >> 16) & 0xff;
00212
00213 unsigned a0 = (rgba0 >> 24) & 0xff;
00214 unsigned r0 = rgba0 & 0xff ;
00215 unsigned g0 = (rgba0 >> 8 ) & 0xff;
00216 unsigned b0 = (rgba0 >> 16) & 0xff;
00217
00218 unsigned a = (a1 * 255 + (255 - a1) * a0 + 127)/255;
00219
00220 r0 = (r1*a1 + (((255 - a1) * a0 + 127)/255) * r0 + 127)/a;
00221 g0 = (g1*a1 + (((255 - a1) * a0 + 127)/255) * g0 + 127)/a;
00222 b0 = (b1*a1 + (((255 - a1) * a0 + 127)/255) * b0 + 127)/a;
00223
00224 row_to[x] = (a << 24)| (b0 << 16) | (g0 << 8) | (r0) ;
00225 }
00226 }
00227 }
00228 }
00229 };
00230 }
00231 #endif //GRAPHICS_HPP