loolwsd/Png.hpp | 75 ++++++++++++++++++++++++++++++++ loolwsd/test/TileCacheTests.cpp | 91 +++++++--------------------------------- 2 files changed, 92 insertions(+), 74 deletions(-)
New commits: commit 18ab6d28bfdf69bdd1827185d73081631d3e13af Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk> Date: Sat Aug 6 11:24:49 2016 -0400 loolwsd: refactored png decoding into own function Change-Id: I8310b3880f2171c26cecbee4cb1780889d38ea31 Reviewed-on: https://gerrit.libreoffice.org/27973 Reviewed-by: Ashod Nakashian <ashnak...@gmail.com> Tested-by: Ashod Nakashian <ashnak...@gmail.com> diff --git a/loolwsd/Png.hpp b/loolwsd/Png.hpp index 7533c4e..6796adf 100644 --- a/loolwsd/Png.hpp +++ b/loolwsd/Png.hpp @@ -48,6 +48,8 @@ #define PNG_SKIP_SETJMP_CHECK #include <png.h> +#include <cassert> + namespace png { @@ -155,6 +157,79 @@ bool encodeBufferToPNG(unsigned char* pixmap, int width, int height, return encodeSubBufferToPNG(pixmap, 0, 0, width, height, width, height, output, mode); } +static +void readTileData(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_voidp io_ptr = png_get_io_ptr(png_ptr); + assert(io_ptr); + + assert(io_ptr != nullptr); + std::stringstream& streamTile = *(std::stringstream*)io_ptr; + streamTile.read((char*)data, length); +} + +inline +std::vector<png_bytep> decodePNG(std::stringstream& stream, png_uint_32& height, png_uint_32& width, png_uint_32& rowBytes) +{ + png_byte signature[0x08]; + stream.read((char *)signature, 0x08); + if (png_sig_cmp(signature, 0x00, 0x08)) + { + throw std::runtime_error("Invalid PNG signature."); + } + + png_structp ptrPNG = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (ptrPNG == nullptr) + { + throw std::runtime_error("png_create_read_struct failed."); + } + + png_infop ptrInfo = png_create_info_struct(ptrPNG); + if (ptrInfo == nullptr) + { + throw std::runtime_error("png_create_info_struct failed."); + } + + png_infop ptrEnd = png_create_info_struct(ptrPNG); + if (ptrEnd == nullptr) + { + throw std::runtime_error("png_create_info_struct failed."); + } + + png_set_read_fn(ptrPNG, &stream, readTileData); + png_set_sig_bytes(ptrPNG, 0x08); + + png_read_info(ptrPNG, ptrInfo); + + width = png_get_image_width(ptrPNG, ptrInfo); + height = png_get_image_height(ptrPNG, ptrInfo); + + png_set_interlace_handling(ptrPNG); + png_read_update_info(ptrPNG, ptrInfo); + + rowBytes = png_get_rowbytes(ptrPNG, ptrInfo); + assert(width == rowBytes / 4); + + const size_t dataSize = (rowBytes + sizeof(png_bytep)) * height / sizeof(png_bytep); + const size_t size = dataSize + height + sizeof(png_bytep); + + std::vector<png_bytep> rows; + rows.resize(size); + + // rows + for (png_uint_32 itRow = 0; itRow < height; itRow++) + { + const auto index = height + (itRow * rowBytes + sizeof(png_bytep) - 1) / sizeof(png_bytep); + rows[itRow] = reinterpret_cast<png_bytep>(&rows[index]); + } + + png_read_image(ptrPNG, rows.data()); + png_read_end(ptrPNG, ptrEnd); + png_destroy_read_struct(&ptrPNG, &ptrInfo, &ptrEnd); + + return rows; +} + } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/loolwsd/test/TileCacheTests.cpp b/loolwsd/test/TileCacheTests.cpp index 6c0ba64..d4b0a4f 100644 --- a/loolwsd/test/TileCacheTests.cpp +++ b/loolwsd/test/TileCacheTests.cpp @@ -9,16 +9,16 @@ #include "config.h" -#include <png.h> #include <Poco/Net/WebSocket.h> #include <cppunit/extensions/HelperMacros.h> +#include "Common.hpp" +#include "LOOLProtocol.hpp" +#include "Png.hpp" +#include "TileCache.hpp" +#include "Unit.hpp" +#include "Util.hpp" #include "helpers.hpp" -#include <Common.hpp> -#include <LOOLProtocol.hpp> -#include <TileCache.hpp> -#include <Unit.hpp> -#include <Util.hpp> using namespace helpers; @@ -376,90 +376,33 @@ void TileCacheTests::testLoad12ods() } } -void readTileData(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_voidp io_ptr = png_get_io_ptr(png_ptr); - CPPUNIT_ASSERT(io_ptr); - - assert(io_ptr != nullptr); - std::stringstream& streamTile = *(std::stringstream*)io_ptr; - streamTile.read((char*)data, length); -} - void TileCacheTests::checkBlackTile(std::stringstream& tile) { - png_uint_32 width; - png_uint_32 height; - png_uint_32 itRow; - png_uint_32 itCol; - png_uint_32 black; - png_uint_32 rowBytes; - - png_infop ptrInfo; - png_infop ptrEnd; - png_structp ptrPNG; - png_byte signature[0x08]; - - tile.read((char *)signature, 0x08); - CPPUNIT_ASSERT_MESSAGE( "Tile is not recognized as a PNG", !png_sig_cmp(signature, 0x00, 0x08)); - - ptrPNG = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - CPPUNIT_ASSERT_MESSAGE("png_create_read_struct failed", ptrPNG); - - ptrInfo = png_create_info_struct(ptrPNG); - CPPUNIT_ASSERT_MESSAGE("png_create_info_struct failed", ptrInfo); - - ptrEnd = png_create_info_struct(ptrPNG); - CPPUNIT_ASSERT_MESSAGE("png_create_info_struct failed", ptrEnd); - - png_set_read_fn(ptrPNG, &tile, readTileData); - png_set_sig_bytes(ptrPNG, 0x08); - - png_read_info(ptrPNG, ptrInfo); + png_uint_32 height = 0; + png_uint_32 width = 0; + png_uint_32 rowBytes = 0; - width = png_get_image_width(ptrPNG, ptrInfo); - height = png_get_image_height(ptrPNG, ptrInfo); + auto rows = png::decodePNG(tile, height, width, rowBytes); - png_set_interlace_handling(ptrPNG); - png_read_update_info(ptrPNG, ptrInfo); - - rowBytes = png_get_rowbytes(ptrPNG, ptrInfo); - CPPUNIT_ASSERT_EQUAL(width, rowBytes / 4); - - // rows - png_bytep rows[height]; - for (itRow = 0; itRow < height; itRow++) - { - rows[itRow] = new png_byte[rowBytes]; - } - - png_read_image(ptrPNG, rows); - - black = 0; - for (itRow = 0; itRow < height; itRow++) + png_uint_32 black = 0; + for (png_uint_32 itRow = 0; itRow < height; ++itRow) { - itCol = 0; - while(itCol <= rowBytes) + png_uint_32 itCol = 0; + while (itCol <= rowBytes) { png_byte R = rows[itRow][itCol + 0]; png_byte G = rows[itRow][itCol + 1]; png_byte B = rows[itRow][itCol + 2]; //png_byte A = rows[itRow][itCol + 3]; if (R == 0x00 && G == 0x00 && B == 0x00) - black++; + { + ++black; + } itCol += 4; } } - png_read_end(ptrPNG, ptrEnd); - png_destroy_read_struct(&ptrPNG, &ptrInfo, &ptrEnd); - - for (itRow = 0; itRow < height; itRow++ ) - { - delete rows[itRow]; - } - CPPUNIT_ASSERT_MESSAGE("The tile is 100% black", black != height * width); assert(height * width != 0); CPPUNIT_ASSERT_MESSAGE("The tile is 90% black", (black * 100) / (height * width) < 90); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits