commit
bc08617eb8
6 changed files with 3 additions and 5341 deletions
|
@ -1,95 +0,0 @@
|
||||||
/*****************************************************************************
|
|
||||||
*
|
|
||||||
* This file is part of Mapnik (c++ mapping toolkit)
|
|
||||||
*
|
|
||||||
* Copyright (C) 2015 Artem Pavlenko
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#ifndef MAPNIK_MINIZ_PNG_HPP
|
|
||||||
#define MAPNIK_MINIZ_PNG_HPP
|
|
||||||
|
|
||||||
// mapnik
|
|
||||||
#include <mapnik/palette.hpp>
|
|
||||||
#include <mapnik/config.hpp>
|
|
||||||
|
|
||||||
// stl
|
|
||||||
#include <vector>
|
|
||||||
#include <iostream>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include <mapnik/image.hpp>
|
|
||||||
#include <mapnik/image_view.hpp>
|
|
||||||
|
|
||||||
/* miniz.c porting issues:
|
|
||||||
- duplicate symbols in python bindings require moving miniz.c include to just cpp file
|
|
||||||
- due to http://code.google.com/p/miniz/issues/detail?id=7
|
|
||||||
- avoiding including miniz.c here requires fwd declaring the two structs below
|
|
||||||
- being able to fwd declare requires removing typedef from struct declarations in miniz.c
|
|
||||||
- being able to fwd declare also requires using pointers to structs
|
|
||||||
- if updated, need to apply c++11 fix: https://github.com/mapnik/mapnik/issues/1967
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TODO: try using #define MINIZ_HEADER_FILE_ONLY
|
|
||||||
struct tdefl_output_buffer;
|
|
||||||
struct tdefl_compressor;
|
|
||||||
|
|
||||||
namespace mapnik { namespace MiniZ {
|
|
||||||
|
|
||||||
using mapnik::rgb;
|
|
||||||
|
|
||||||
class MAPNIK_DECL PNGWriter {
|
|
||||||
|
|
||||||
public:
|
|
||||||
PNGWriter(int level, int strategy);
|
|
||||||
~PNGWriter();
|
|
||||||
private:
|
|
||||||
inline void writeUInt32BE(unsigned char *target, unsigned int value);
|
|
||||||
size_t startChunk(const unsigned char header[], size_t length);
|
|
||||||
void finishChunk(size_t start);
|
|
||||||
public:
|
|
||||||
void writeIHDR(unsigned int width, unsigned int height, unsigned char pixel_depth);
|
|
||||||
void writePLTE(std::vector<rgb> const& palette);
|
|
||||||
void writetRNS(std::vector<unsigned> const& alpha);
|
|
||||||
template<typename T>
|
|
||||||
void writeIDAT(T const& image);
|
|
||||||
template<typename T>
|
|
||||||
void writeIDATStripAlpha(T const& image);
|
|
||||||
void writeIEND();
|
|
||||||
void toStream(std::ostream& stream);
|
|
||||||
|
|
||||||
private:
|
|
||||||
tdefl_compressor *compressor;
|
|
||||||
tdefl_output_buffer *buffer;
|
|
||||||
static const unsigned char preamble[];
|
|
||||||
static const unsigned char IHDR_tpl[];
|
|
||||||
static const unsigned char PLTE_tpl[];
|
|
||||||
static const unsigned char tRNS_tpl[];
|
|
||||||
static const unsigned char IDAT_tpl[];
|
|
||||||
static const unsigned char IEND_tpl[];
|
|
||||||
};
|
|
||||||
|
|
||||||
extern template MAPNIK_DECL void PNGWriter::writeIDAT<image_gray8>(image_gray8 const& image);
|
|
||||||
extern template MAPNIK_DECL void PNGWriter::writeIDAT<image_view_gray8>(image_view_gray8 const& image);
|
|
||||||
extern template MAPNIK_DECL void PNGWriter::writeIDAT<image_rgba8>(image_rgba8 const& image);
|
|
||||||
extern template MAPNIK_DECL void PNGWriter::writeIDAT<image_view_rgba8>(image_view_rgba8 const& image);
|
|
||||||
extern template MAPNIK_DECL void PNGWriter::writeIDATStripAlpha<image_rgba8>(image_rgba8 const& image);
|
|
||||||
extern template MAPNIK_DECL void PNGWriter::writeIDATStripAlpha<image_view_rgba8>(image_view_rgba8 const& image);
|
|
||||||
|
|
||||||
}}
|
|
||||||
|
|
||||||
#endif // MAPNIK_MINIZ_PNG_HPP
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include <mapnik/palette.hpp>
|
#include <mapnik/palette.hpp>
|
||||||
#include <mapnik/octree.hpp>
|
#include <mapnik/octree.hpp>
|
||||||
#include <mapnik/hextree.hpp>
|
#include <mapnik/hextree.hpp>
|
||||||
#include <mapnik/miniz_png.hpp>
|
|
||||||
#include <mapnik/image.hpp>
|
#include <mapnik/image.hpp>
|
||||||
|
|
||||||
// zlib
|
// zlib
|
||||||
|
@ -53,7 +52,6 @@ struct png_options {
|
||||||
double gamma;
|
double gamma;
|
||||||
bool paletted;
|
bool paletted;
|
||||||
bool use_hextree;
|
bool use_hextree;
|
||||||
bool use_miniz;
|
|
||||||
png_options() :
|
png_options() :
|
||||||
colors(256),
|
colors(256),
|
||||||
compression(Z_DEFAULT_COMPRESSION),
|
compression(Z_DEFAULT_COMPRESSION),
|
||||||
|
@ -61,8 +59,7 @@ struct png_options {
|
||||||
trans_mode(-1),
|
trans_mode(-1),
|
||||||
gamma(-1),
|
gamma(-1),
|
||||||
paletted(true),
|
paletted(true),
|
||||||
use_hextree(true),
|
use_hextree(true) {}
|
||||||
use_miniz(false) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -85,23 +82,6 @@ void save_as_png(T1 & file,
|
||||||
png_options const& opts)
|
png_options const& opts)
|
||||||
|
|
||||||
{
|
{
|
||||||
if (opts.use_miniz)
|
|
||||||
{
|
|
||||||
MiniZ::PNGWriter writer(opts.compression,opts.strategy);
|
|
||||||
if (opts.trans_mode == 0)
|
|
||||||
{
|
|
||||||
writer.writeIHDR(image.width(), image.height(), 24);
|
|
||||||
writer.writeIDATStripAlpha(image);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
writer.writeIHDR(image.width(), image.height(), 32);
|
|
||||||
writer.writeIDAT(image);
|
|
||||||
}
|
|
||||||
writer.writeIEND();
|
|
||||||
writer.toStream(file);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
png_voidp error_ptr=0;
|
png_voidp error_ptr=0;
|
||||||
png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING,
|
png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING,
|
||||||
error_ptr,0, 0);
|
error_ptr,0, 0);
|
||||||
|
@ -273,19 +253,6 @@ void save_as_png(T & file, std::vector<mapnik::rgb> const& palette,
|
||||||
std::vector<unsigned> const&alpha,
|
std::vector<unsigned> const&alpha,
|
||||||
png_options const& opts)
|
png_options const& opts)
|
||||||
{
|
{
|
||||||
if (opts.use_miniz)
|
|
||||||
{
|
|
||||||
MiniZ::PNGWriter writer(opts.compression,opts.strategy);
|
|
||||||
// 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_voidp error_ptr=0;
|
||||||
png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING,
|
png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING,
|
||||||
error_ptr,0, 0);
|
error_ptr,0, 0);
|
||||||
|
|
|
@ -155,7 +155,6 @@ source = Split(
|
||||||
params.cpp
|
params.cpp
|
||||||
image_filter_types.cpp
|
image_filter_types.cpp
|
||||||
image_filter_grammar.cpp
|
image_filter_grammar.cpp
|
||||||
miniz_png.cpp
|
|
||||||
color.cpp
|
color.cpp
|
||||||
conversions.cpp
|
conversions.cpp
|
||||||
image_copy.cpp
|
image_copy.cpp
|
||||||
|
|
|
@ -85,7 +85,7 @@ void handle_png_options(std::string const& type,
|
||||||
}
|
}
|
||||||
else if (key == "e" && val && *val == "miniz")
|
else if (key == "e" && val && *val == "miniz")
|
||||||
{
|
{
|
||||||
opts.use_miniz = true;
|
throw image_writer_exception("miniz support has been removed from Mapnik");
|
||||||
}
|
}
|
||||||
else if (key == "c")
|
else if (key == "c")
|
||||||
{
|
{
|
||||||
|
@ -168,7 +168,7 @@ void handle_png_options(std::string const& type,
|
||||||
{
|
{
|
||||||
throw image_writer_exception("invalid gamma parameter: unavailable for true color (non-paletted) images");
|
throw image_writer_exception("invalid gamma parameter: unavailable for true color (non-paletted) images");
|
||||||
}
|
}
|
||||||
if ((opts.use_miniz == false) && opts.compression > Z_BEST_COMPRESSION)
|
if (opts.compression > Z_BEST_COMPRESSION)
|
||||||
{
|
{
|
||||||
throw image_writer_exception("invalid compression value: (only -1 through 9 are valid)");
|
throw image_writer_exception("invalid compression value: (only -1 through 9 are valid)");
|
||||||
}
|
}
|
||||||
|
|
4834
src/miniz.c
4834
src/miniz.c
File diff suppressed because it is too large
Load diff
|
@ -1,375 +0,0 @@
|
||||||
/*****************************************************************************
|
|
||||||
*
|
|
||||||
* This file is part of Mapnik (c++ mapping toolkit)
|
|
||||||
*
|
|
||||||
* Copyright (C) 2015 Artem Pavlenko
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
// mapnik
|
|
||||||
#include <mapnik/palette.hpp>
|
|
||||||
#include <mapnik/miniz_png.hpp>
|
|
||||||
#include <mapnik/image.hpp>
|
|
||||||
#include <mapnik/image_view.hpp>
|
|
||||||
|
|
||||||
// miniz
|
|
||||||
#define MINIZ_NO_ARCHIVE_APIS
|
|
||||||
#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
|
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#include <mapnik/warning_ignore.hpp>
|
|
||||||
extern "C" {
|
|
||||||
#include "miniz.c"
|
|
||||||
}
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
|
|
||||||
// zlib
|
|
||||||
#include <zlib.h>
|
|
||||||
|
|
||||||
// stl
|
|
||||||
#include <vector>
|
|
||||||
#include <iostream>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
namespace mapnik { namespace MiniZ {
|
|
||||||
|
|
||||||
PNGWriter::PNGWriter(int level, int strategy)
|
|
||||||
{
|
|
||||||
buffer = nullptr;
|
|
||||||
compressor = nullptr;
|
|
||||||
|
|
||||||
if (level == -1)
|
|
||||||
{
|
|
||||||
level = MZ_DEFAULT_LEVEL; // 6
|
|
||||||
}
|
|
||||||
else if (level < 0 || level > 10)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("compression level must be between 0 and 10");
|
|
||||||
}
|
|
||||||
mz_uint flags = s_tdefl_num_probes[level] | TDEFL_WRITE_ZLIB_HEADER;
|
|
||||||
if (level <= 3)
|
|
||||||
{
|
|
||||||
flags |= TDEFL_GREEDY_PARSING_FLAG;
|
|
||||||
}
|
|
||||||
if (strategy == Z_FILTERED) flags |= TDEFL_FILTER_MATCHES;
|
|
||||||
else if (strategy == Z_HUFFMAN_ONLY) flags &= ~TDEFL_MAX_PROBES_MASK;
|
|
||||||
else if (strategy == Z_RLE) flags |= TDEFL_RLE_MATCHES;
|
|
||||||
else if (strategy == Z_FIXED) flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
|
|
||||||
|
|
||||||
buffer = (tdefl_output_buffer *)MZ_MALLOC(sizeof(tdefl_output_buffer));
|
|
||||||
if (buffer == nullptr)
|
|
||||||
{
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer->m_pBuf = nullptr;
|
|
||||||
buffer->m_capacity = 8192;
|
|
||||||
buffer->m_expandable = MZ_TRUE;
|
|
||||||
buffer->m_pBuf = (mz_uint8 *)MZ_MALLOC(buffer->m_capacity);
|
|
||||||
if (buffer->m_pBuf == nullptr)
|
|
||||||
{
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
|
|
||||||
compressor = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
|
|
||||||
if (compressor == nullptr)
|
|
||||||
{
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset output buffer.
|
|
||||||
buffer->m_size = 0;
|
|
||||||
tdefl_status tdstatus = tdefl_init(compressor, tdefl_output_buffer_putter, buffer, flags);
|
|
||||||
if (tdstatus != TDEFL_STATUS_OKAY)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("tdefl_init failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write preamble.
|
|
||||||
mz_bool status = tdefl_output_buffer_putter(preamble, 8, buffer);
|
|
||||||
if (status != MZ_TRUE)
|
|
||||||
{
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PNGWriter::~PNGWriter()
|
|
||||||
{
|
|
||||||
if (compressor)
|
|
||||||
{
|
|
||||||
MZ_FREE(compressor);
|
|
||||||
}
|
|
||||||
if (buffer)
|
|
||||||
{
|
|
||||||
if (buffer->m_pBuf)
|
|
||||||
{
|
|
||||||
MZ_FREE(buffer->m_pBuf);
|
|
||||||
}
|
|
||||||
MZ_FREE(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void PNGWriter::writeUInt32BE(mz_uint8 *target, mz_uint32 value)
|
|
||||||
{
|
|
||||||
target[0] = (value >> 24) & 0xFF;
|
|
||||||
target[1] = (value >> 16) & 0xFF;
|
|
||||||
target[2] = (value >> 8) & 0xFF;
|
|
||||||
target[3] = value & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t PNGWriter::startChunk(const mz_uint8 header[], size_t length)
|
|
||||||
{
|
|
||||||
size_t start = buffer->m_size;
|
|
||||||
mz_bool status = tdefl_output_buffer_putter(header, length, buffer);
|
|
||||||
if (status != MZ_TRUE)
|
|
||||||
{
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PNGWriter::finishChunk(size_t start)
|
|
||||||
{
|
|
||||||
// Write chunk length at the beginning of the chunk.
|
|
||||||
size_t payloadLength = buffer->m_size - start - 4 - 4;
|
|
||||||
writeUInt32BE(buffer->m_pBuf + start, static_cast<mz_uint32>(payloadLength));
|
|
||||||
// Write CRC32 checksum. Don't include the 4-byte length, but /do/ include
|
|
||||||
// the 4-byte chunk name.
|
|
||||||
mz_uint32 crc = mz_crc32(MZ_CRC32_INIT, buffer->m_pBuf + start + 4, payloadLength + 4);
|
|
||||||
mz_uint8 checksum[] = { static_cast<mz_uint8>(crc >> 24),
|
|
||||||
static_cast<mz_uint8>(crc >> 16),
|
|
||||||
static_cast<mz_uint8>(crc >> 8),
|
|
||||||
static_cast<mz_uint8>(crc) };
|
|
||||||
mz_bool status = tdefl_output_buffer_putter(checksum, 4, buffer);
|
|
||||||
if (status != MZ_TRUE)
|
|
||||||
{
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PNGWriter::writeIHDR(mz_uint32 width, mz_uint32 height, mz_uint8 pixel_depth)
|
|
||||||
{
|
|
||||||
// Write IHDR chunk.
|
|
||||||
size_t IHDR = startChunk(IHDR_tpl, 21);
|
|
||||||
writeUInt32BE(buffer->m_pBuf + IHDR + 8, width);
|
|
||||||
writeUInt32BE(buffer->m_pBuf + IHDR + 12, height);
|
|
||||||
|
|
||||||
if (pixel_depth == 32)
|
|
||||||
{
|
|
||||||
// Alpha full color image.
|
|
||||||
buffer->m_pBuf[IHDR + 16] = 8; // bit depth
|
|
||||||
buffer->m_pBuf[IHDR + 17] = 6; // color type (6 == true color with alpha)
|
|
||||||
}
|
|
||||||
else if (pixel_depth == 24)
|
|
||||||
{
|
|
||||||
// Full color image.
|
|
||||||
buffer->m_pBuf[IHDR + 16] = 8; // bit depth
|
|
||||||
buffer->m_pBuf[IHDR + 17] = 2; // color type (2 == true color without alpha)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Paletted image.
|
|
||||||
buffer->m_pBuf[IHDR + 16] = pixel_depth; // bit depth
|
|
||||||
buffer->m_pBuf[IHDR + 17] = 3; // color type (3 == indexed color)
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer->m_pBuf[IHDR + 18] = 0; // compression method
|
|
||||||
buffer->m_pBuf[IHDR + 19] = 0; // filter method
|
|
||||||
buffer->m_pBuf[IHDR + 20] = 0; // interlace method
|
|
||||||
finishChunk(IHDR);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PNGWriter::writePLTE(std::vector<rgb> const& palette)
|
|
||||||
{
|
|
||||||
// Write PLTE chunk.
|
|
||||||
size_t PLTE = startChunk(PLTE_tpl, 8);
|
|
||||||
const mz_uint8 *colors = reinterpret_cast<const mz_uint8 *>(&palette[0]);
|
|
||||||
mz_bool status = tdefl_output_buffer_putter(colors, palette.size() * 3, buffer);
|
|
||||||
if (status != MZ_TRUE)
|
|
||||||
{
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
finishChunk(PLTE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PNGWriter::writetRNS(std::vector<unsigned> const& alpha)
|
|
||||||
{
|
|
||||||
if (alpha.size() == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<unsigned char> transparency(alpha.size());
|
|
||||||
unsigned char transparencySize = 0; // Stores position of biggest to nonopaque value.
|
|
||||||
for(unsigned i = 0; i < alpha.size(); i++)
|
|
||||||
{
|
|
||||||
transparency[i] = alpha[i];
|
|
||||||
if (alpha[i] < 255)
|
|
||||||
{
|
|
||||||
transparencySize = i + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (transparencySize > 0)
|
|
||||||
{
|
|
||||||
// Write tRNS chunk.
|
|
||||||
size_t tRNS = startChunk(tRNS_tpl, 8);
|
|
||||||
mz_bool status = tdefl_output_buffer_putter(&transparency[0], transparencySize, buffer);
|
|
||||||
if (status != MZ_TRUE)
|
|
||||||
{
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
finishChunk(tRNS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void PNGWriter::writeIDAT(T const& image)
|
|
||||||
{
|
|
||||||
// Write IDAT chunk.
|
|
||||||
size_t IDAT = startChunk(IDAT_tpl, 8);
|
|
||||||
mz_uint8 filter_type = 0;
|
|
||||||
tdefl_status status;
|
|
||||||
|
|
||||||
int bytes_per_pixel = sizeof(typename T::pixel_type);
|
|
||||||
int stride = image.width() * bytes_per_pixel;
|
|
||||||
|
|
||||||
for (unsigned int y = 0; y < image.height(); y++)
|
|
||||||
{
|
|
||||||
// Write filter_type
|
|
||||||
status = tdefl_compress_buffer(compressor, &filter_type, 1, TDEFL_NO_FLUSH);
|
|
||||||
if (status != TDEFL_STATUS_OKAY)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("failed to compress image");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write scanline
|
|
||||||
status = tdefl_compress_buffer(compressor, (mz_uint8 *)image.get_row(y), stride, TDEFL_NO_FLUSH);
|
|
||||||
if (status != TDEFL_STATUS_OKAY)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("failed to compress image");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
status = tdefl_compress_buffer(compressor, nullptr, 0, TDEFL_FINISH);
|
|
||||||
if (status != TDEFL_STATUS_DONE)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("failed to compress image");
|
|
||||||
}
|
|
||||||
|
|
||||||
finishChunk(IDAT);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void PNGWriter::writeIDATStripAlpha(T const& image) {
|
|
||||||
// Write IDAT chunk.
|
|
||||||
size_t IDAT = startChunk(IDAT_tpl, 8);
|
|
||||||
mz_uint8 filter_type = 0;
|
|
||||||
tdefl_status status;
|
|
||||||
|
|
||||||
size_t stride = image.width() * 3;
|
|
||||||
size_t i, j;
|
|
||||||
mz_uint8 *scanline = (mz_uint8 *)MZ_MALLOC(stride);
|
|
||||||
|
|
||||||
for (unsigned int y = 0; y < image.height(); y++) {
|
|
||||||
// Write filter_type
|
|
||||||
status = tdefl_compress_buffer(compressor, &filter_type, 1, TDEFL_NO_FLUSH);
|
|
||||||
if (status != TDEFL_STATUS_OKAY)
|
|
||||||
{
|
|
||||||
MZ_FREE(scanline);
|
|
||||||
throw std::runtime_error("failed to compress image");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Strip alpha bytes from scanline
|
|
||||||
mz_uint8 *row = (mz_uint8 *)image.get_row(y);
|
|
||||||
for (i = 0, j = 0; j < stride; i += 4, j += 3) {
|
|
||||||
scanline[j] = row[i];
|
|
||||||
scanline[j+1] = row[i+1];
|
|
||||||
scanline[j+2] = row[i+2];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write scanline
|
|
||||||
status = tdefl_compress_buffer(compressor, scanline, stride, TDEFL_NO_FLUSH);
|
|
||||||
if (status != TDEFL_STATUS_OKAY) {
|
|
||||||
MZ_FREE(scanline);
|
|
||||||
throw std::runtime_error("failed to compress image");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MZ_FREE(scanline);
|
|
||||||
|
|
||||||
status = tdefl_compress_buffer(compressor, nullptr, 0, TDEFL_FINISH);
|
|
||||||
if (status != TDEFL_STATUS_DONE) throw std::runtime_error("failed to compress image");
|
|
||||||
|
|
||||||
finishChunk(IDAT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PNGWriter::writeIEND()
|
|
||||||
{
|
|
||||||
// Write IEND chunk.
|
|
||||||
size_t IEND = startChunk(IEND_tpl, 8);
|
|
||||||
finishChunk(IEND);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PNGWriter::toStream(std::ostream& stream)
|
|
||||||
{
|
|
||||||
stream.write((char *)buffer->m_pBuf, buffer->m_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
const mz_uint8 PNGWriter::preamble[] = {
|
|
||||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a
|
|
||||||
};
|
|
||||||
|
|
||||||
const mz_uint8 PNGWriter::IHDR_tpl[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x0D, // chunk length
|
|
||||||
'I', 'H', 'D', 'R', // "IHDR"
|
|
||||||
0x00, 0x00, 0x00, 0x00, // image width (4 bytes)
|
|
||||||
0x00, 0x00, 0x00, 0x00, // image height (4 bytes)
|
|
||||||
0x00, // bit depth (1 byte)
|
|
||||||
0x00, // color type (1 byte)
|
|
||||||
0x00, // compression method (1 byte), has to be 0
|
|
||||||
0x00, // filter method (1 byte)
|
|
||||||
0x00 // interlace method (1 byte)
|
|
||||||
};
|
|
||||||
|
|
||||||
const mz_uint8 PNGWriter::PLTE_tpl[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, // chunk length
|
|
||||||
'P', 'L', 'T', 'E' // "IDAT"
|
|
||||||
};
|
|
||||||
|
|
||||||
const mz_uint8 PNGWriter::tRNS_tpl[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, // chunk length
|
|
||||||
't', 'R', 'N', 'S' // "IDAT"
|
|
||||||
};
|
|
||||||
|
|
||||||
const mz_uint8 PNGWriter::IDAT_tpl[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, // chunk length
|
|
||||||
'I', 'D', 'A', 'T' // "IDAT"
|
|
||||||
};
|
|
||||||
|
|
||||||
const mz_uint8 PNGWriter::IEND_tpl[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, // chunk length
|
|
||||||
'I', 'E', 'N', 'D' // "IEND"
|
|
||||||
};
|
|
||||||
|
|
||||||
template void PNGWriter::writeIDAT<image_gray8>(image_gray8 const& image);
|
|
||||||
template void PNGWriter::writeIDAT<image_view_gray8>(image_view_gray8 const& image);
|
|
||||||
template void PNGWriter::writeIDAT<image_rgba8>(image_rgba8 const& image);
|
|
||||||
template void PNGWriter::writeIDAT<image_view_rgba8>(image_view_rgba8 const& image);
|
|
||||||
template void PNGWriter::writeIDATStripAlpha<image_rgba8>(image_rgba8 const& image);
|
|
||||||
template void PNGWriter::writeIDATStripAlpha<image_view_rgba8>(image_view_rgba8 const& image);
|
|
||||||
|
|
||||||
}}
|
|
Loading…
Reference in a new issue