void reduce_4(T const& in, image_data_8 & out, octree<rgb> trees[], unsigned limits[], unsigned levels, std::vector<unsigned> & alpha) { unsigned width = in.width(); unsigned height = in.height(); std::vector<unsigned> alphaCount(alpha.size()); for(unsigned i=0; i<alpha.size(); i++) { alpha[i] = 0; alphaCount[i] = 0; } for (unsigned y = 0; y < height; ++y) { mapnik::image_data_32::pixel_type const * row = in.getRow(y); mapnik::image_data_8::pixel_type * row_out = out.getRow(y); for (unsigned x = 0; x < width; ++x) { unsigned val = row[x]; byte index = 0; int idx=-1; for(int j=levels-1; j>0; j--) { if (U2ALPHA(val)>=limits[j] && trees[j].colors()>0) { index = idx = trees[j].quantize(val); break; } } if (idx>=0 && idx<(int)alpha.size()) { alpha[idx]+=U2ALPHA(val); alphaCount[idx]++; } if (x%2 == 0) { index = index<<4; } row_out[x>>1] |= index; } } for(unsigned i=0; i<alpha.size(); i++) { if (alphaCount[i]!=0) { alpha[i] /= alphaCount[i]; } } }
void save_as_png(T & file, std::vector<rgb> const& palette, image_data_8 const& image, unsigned width, unsigned height, unsigned color_depth, int compression, int strategy, std::vector<unsigned> const&alpha, bool use_miniz) { if (use_miniz) { MiniZ::PNGWriter writer(compression); // image.width()/height() does not reflect the actual image dimensions; it // refers to the quantized scanlines. writer.writeIHDR(width, height, color_depth); writer.writePLTE(palette); writer.writetRNS(alpha); writer.writeIDAT(image); writer.writeIEND(); writer.toStream(file); return; } png_voidp error_ptr=0; png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, error_ptr,0, 0); if (!png_ptr) return; // switch on optimization only if supported #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) && defined(PNG_MMX_CODE_SUPPORTED) png_uint_32 mask, flags; flags = png_get_asm_flags(png_ptr); mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE); png_set_asm_flags(png_ptr, flags | mask); #endif png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE); png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr,(png_infopp)0); return; } jmp_buf* jmp_context = (jmp_buf*) png_get_error_ptr(png_ptr); if (jmp_context) { png_destroy_write_struct(&png_ptr, &info_ptr); return; } png_set_write_fn (png_ptr, &file, &write_data<T>, &flush_data<T>); png_set_compression_level(png_ptr, compression); png_set_compression_strategy(png_ptr, strategy); png_set_compression_buffer_size(png_ptr, 32768); png_set_IHDR(png_ptr, info_ptr,width,height,color_depth, PNG_COLOR_TYPE_PALETTE,PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT); png_color* pal = const_cast<png_color*>(reinterpret_cast<const png_color*>(&palette[0])); png_set_PLTE(png_ptr, info_ptr, pal, palette.size()); // make transparent lowest indexes, so tRNS is small if (alpha.size()>0) { std::vector<png_byte> trans(alpha.size()); unsigned alphaSize=0;//truncate to nonopaque values for(unsigned i=0; i < alpha.size(); i++) { trans[i]=alpha[i]; if (alpha[i]<255) alphaSize = i+1; } if (alphaSize>0) png_set_tRNS(png_ptr, info_ptr, (png_bytep)&trans[0], alphaSize, 0); } png_write_info(png_ptr, info_ptr); for (unsigned i=0; i<height; i++) { png_write_row(png_ptr,(png_bytep)image.getRow(i)); } png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); }