103
103
unsigned val = row[x];
104
104
mapnik::rgb c((val)&0xff, (val>>8)&0xff, (val>>16) & 0xff);
105
105
byte index = tree.quantize(c);
106
if (!((val>>24)&0x80)) index = 0;//alfa
106
107
row_out[x] = index;
111
112
template <typename T>
112
113
void reduce_4 (T const& in, ImageData8 & out, octree<rgb> & tree)
114
115
unsigned width = in.width();
115
116
unsigned height = in.height();
117
118
for (unsigned y = 0; y < height; ++y)
119
120
mapnik::ImageData32::pixel_type const * row = in.getRow(y);
120
121
mapnik::ImageData8::pixel_type * row_out = out.getRow(y);
122
123
for (unsigned x = 0; x < width; ++x)
124
125
unsigned val = row[x];
125
126
mapnik::rgb c((val)&0xff, (val>>8)&0xff, (val>>16) & 0xff);
126
127
byte index = tree.quantize(c);
127
128
if (x%2 > 0) index = index<<4;
128
row_out[x>>1] |= index;
129
if (!((val>>24)&0x80)) index = 0;//alfa
130
row_out[x>>1] |= index;
133
135
// 1-bit but only one color.
134
136
template <typename T>
135
137
void reduce_1(T const&, ImageData8 & out, octree<rgb> &)
137
139
out.set(0); // only one color!!!
140
142
template <typename T>
141
void save_as_png(T & file, std::vector<mapnik::rgb> & palette,
142
mapnik::ImageData8 const& image,
143
void save_as_png(T & file, std::vector<mapnik::rgb> & palette,
144
mapnik::ImageData8 const& image,
145
unsigned color_depth)
147
unsigned color_depth,
147
150
png_voidp error_ptr=0;
148
151
png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING,
151
154
if (!png_ptr) return;
153
156
// switch on optimization only if supported
154
157
#if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) && defined(PNG_MMX_CODE_SUPPORTED)
155
158
png_uint_32 mask, flags;
172
175
png_set_write_fn (png_ptr, &file, &write_data<T>, &flush_data<T>);
174
177
png_set_IHDR(png_ptr, info_ptr,width,height,color_depth,
175
178
PNG_COLOR_TYPE_PALETTE,PNG_INTERLACE_NONE,
176
179
PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);
178
181
png_set_PLTE(png_ptr,info_ptr,reinterpret_cast<png_color*>(&palette[0]),palette.size());
183
// make transparent lowest indexes, so tRNS is small
186
byte trans[] = {0,0,0,0};
187
//png_color_16p unused;
188
png_set_tRNS(png_ptr, info_ptr, (png_bytep)trans, 1, NULL);
180
191
png_write_info(png_ptr, info_ptr);
181
192
for (unsigned i=0;i<height;i++)
183
194
png_write_row(png_ptr,(png_bytep)image.getRow(i));
186
197
png_write_end(png_ptr, info_ptr);
187
198
png_destroy_write_struct(&png_ptr, &info_ptr);
190
201
template <typename T1,typename T2>
191
202
void save_as_png256(T1 & file, T2 const& image)
199
210
for (unsigned x = 0; x < width; ++x)
201
212
unsigned val = row[x];
202
tree.insert(mapnik::rgb((val)&0xff, (val>>8)&0xff, (val>>16) & 0xff));
215
tree.insert(mapnik::rgb((val)&0xff, (val>>8)&0xff, (val>>16) & 0xff));
206
224
std::vector<rgb> palette;
207
225
tree.create_palette(palette);
208
226
assert(palette.size() <= 256);
210
228
if (palette.size() > 16 )
212
230
// >16 && <=256 colors -> write 8-bit color depth
213
ImageData8 reduced_image(width,height);
231
ImageData8 reduced_image(width,height);
214
232
reduce_8(image,reduced_image,tree);
215
save_as_png(file,palette,reduced_image,width,height,8);
233
save_as_png(file,palette,reduced_image,width,height,8,tree.hasAlfa());
217
else if (palette.size() == 1)
235
else if (palette.size() == 1)
219
237
// 1 color image -> write 1-bit color depth PNG
220
238
unsigned image_width = (int(0.125*width) + 7)&~7;
221
239
unsigned image_height = height;
222
240
ImageData8 reduced_image(image_width,image_height);
223
reduce_1(image,reduced_image,tree);
224
save_as_png(file,palette,reduced_image,width,height,1);
241
reduce_1(image,reduced_image,tree);
242
save_as_png(file,palette,reduced_image,width,height,1,tree.hasAlfa());
228
246
// <=16 colors -> write 4-bit color depth PNG
229
247
unsigned image_width = (int(0.5*width) + 3)&~3;
230
248
unsigned image_height = height;
231
249
ImageData8 reduced_image(image_width,image_height);
232
250
reduce_4(image,reduced_image,tree);
233
save_as_png(file,palette,reduced_image,width,height,4);
251
save_as_png(file,palette,reduced_image,width,height,4,tree.hasAlfa());