From 4f9f95a05a41bfbcc9965eaaf7f2d14c6af9f261 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sun, 12 Apr 2009 15:42:04 +0000 Subject: Write C++ libdimension-png wrapper. --- libdimensionxx/Makefile.am | 4 +- libdimensionxx/cookie.cpp | 163 ++++++++++++++++++++++++++++++++++ libdimensionxx/dimensionxx.hpp | 9 +- libdimensionxx/dimensionxx/canvas.hpp | 13 ++- libdimensionxx/dimensionxx/color.hpp | 25 ++++++ libdimensionxx/dimensionxx/cookie.hpp | 35 ++++++++ libdimensionxx/dimensionxx/error.hpp | 30 +++++++ libdimensionxx/dimensionxx/png.hpp | 59 ++++++++++++ libdimensionxx/png.cpp | 96 ++++++++++++++++++++ 9 files changed, 428 insertions(+), 6 deletions(-) create mode 100644 libdimensionxx/cookie.cpp create mode 100644 libdimensionxx/dimensionxx/cookie.hpp create mode 100644 libdimensionxx/dimensionxx/error.hpp create mode 100644 libdimensionxx/dimensionxx/png.hpp create mode 100644 libdimensionxx/png.cpp (limited to 'libdimensionxx') diff --git a/libdimensionxx/Makefile.am b/libdimensionxx/Makefile.am index 39687fe..da8f544 100644 --- a/libdimensionxx/Makefile.am +++ b/libdimensionxx/Makefile.am @@ -17,12 +17,12 @@ ## along with this program. If not, see . ## ########################################################################### -nobase_include_HEADERS = dimensionxx.hpp dimensionxx/geometry.hpp dimensionxx/color.hpp dimensionxx/canvas.hpp +nobase_include_HEADERS = dimensionxx.hpp dimensionxx/canvas.hpp dimensionxx/color.hpp dimensionxx/cookie.hpp dimensionxx/geometry.hpp dimensionxx/png.hpp INCLUDES = -I../libdimension -I../libdimension-png lib_LTLIBRARIES = libdimensionxx.la -libdimensionxx_la_SOURCES = dimensionxx.hpp dimensionxx/geometry.hpp dimensionxx/color.hpp dimensionxx/canvas.hpp canvas.cpp color.cpp geometry.cpp +libdimensionxx_la_SOURCES = $(nobase_include_HEADERS) canvas.cpp color.cpp cookie.cpp geometry.cpp png.cpp libdimensionxx_la_LDFLAGS = -version-info 0:0:0 libdimensionxx_la_LIBADD = ../libdimension/libdimension.la ../libdimension-png/libdimension-png.la diff --git a/libdimensionxx/cookie.cpp b/libdimensionxx/cookie.cpp new file mode 100644 index 0000000..dd8a06d --- /dev/null +++ b/libdimensionxx/cookie.cpp @@ -0,0 +1,163 @@ +/************************************************************************* + * Copyright (C) 2008 Tavian Barnes * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension 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 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension 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 program. If not, see * + * . * + *************************************************************************/ + +#include "dimensionxx.hpp" +#include + +namespace Dimension +{ + namespace + { + struct Cookie + { + public: + std::istream* istr; + std::ostream* ostr; + }; + + ssize_t + cookie_read(void* cookie, char* buf, size_t size) + { + Cookie* streams = reinterpret_cast(cookie); + + streams->istr->read(buf, size); + + if (streams->istr->eof()) { + return streams->istr->gcount(); + } else if (!streams->istr->good()) { + return -1; + } else { + return streams->istr->gcount(); + } + } + + ssize_t + cookie_write(void* cookie, const char* buf, size_t size) + { + Cookie* streams = reinterpret_cast(cookie); + + streams->ostr->write(buf, size); + + if (!streams->ostr->good()) { + return -1; + } else { + return size; + } + } + + int + cookie_seek(void* cookie, off64_t* offset, int whence) + { + Cookie* streams = reinterpret_cast(cookie); + bool success = true; + + if (streams->istr) { + switch (whence) { + case SEEK_SET: + streams->istr->seekg(*offset, std::ios::beg); + break; + case SEEK_CUR: + streams->istr->seekg(*offset, std::ios::cur); + break; + case SEEK_END: + streams->istr->seekg(*offset, std::ios::end); + break; + } + + if (!streams->istr->good()) { + success = false; + } + } + + if (streams->ostr) { + switch (whence) { + case SEEK_SET: + streams->ostr->seekp(*offset, std::ios::beg); + break; + case SEEK_CUR: + streams->ostr->seekp(*offset, std::ios::cur); + break; + case SEEK_END: + streams->ostr->seekp(*offset, std::ios::end); + } + + if (!streams->ostr->good()) { + success = false; + } + } + + return !success; + } + + int + cookie_close(void* cookie) + { + delete reinterpret_cast(cookie); + } + } + + std::FILE* + fcookie(std::istream& istr) + { + Cookie* cookie = new Cookie; + cookie->istr = &istr; + cookie->ostr = 0; + + cookie_io_functions_t io_funcs; + io_funcs.read = &cookie_read; + io_funcs.write = 0; + io_funcs.seek = &cookie_seek; + io_funcs.close = &cookie_close; + + return fopencookie(reinterpret_cast(cookie), "r", io_funcs); + } + + std::FILE* + fcookie(std::ostream& ostr) + { + Cookie* cookie = new Cookie; + cookie->istr = 0; + cookie->ostr = &ostr; + + cookie_io_functions_t io_funcs; + io_funcs.read = 0; + io_funcs.write = &cookie_write; + io_funcs.seek = &cookie_seek; + io_funcs.close = &cookie_close; + + return fopencookie(reinterpret_cast(cookie), "w", io_funcs); + } + + std::FILE* + fcookie(std::iostream& iostr) + { + Cookie* cookie = new Cookie; + cookie->istr = &iostr; + cookie->ostr = &iostr; + + cookie_io_functions_t io_funcs; + io_funcs.read = &cookie_read; + io_funcs.write = &cookie_write; + io_funcs.seek = &cookie_seek; + io_funcs.close = &cookie_close; + + return fopencookie(reinterpret_cast(cookie), "r+", io_funcs); + } +} diff --git a/libdimensionxx/dimensionxx.hpp b/libdimensionxx/dimensionxx.hpp index a9e89d8..7714f73 100644 --- a/libdimensionxx/dimensionxx.hpp +++ b/libdimensionxx/dimensionxx.hpp @@ -21,9 +21,16 @@ #ifndef DIMENSIONXX_HPP #define DIMENSIONXX_HPP -/* More includes */ +// Internal helpers +#include + +// libdimension wrappers +#include #include #include #include +// libdimension-png wrapper +#include + #endif /* DIMENSIONXX_HPP */ diff --git a/libdimensionxx/dimensionxx/canvas.hpp b/libdimensionxx/dimensionxx/canvas.hpp index f51aa75..c501413 100644 --- a/libdimensionxx/dimensionxx/canvas.hpp +++ b/libdimensionxx/dimensionxx/canvas.hpp @@ -26,10 +26,14 @@ namespace Dimension class Canvas { public: - Canvas(unsigned int x, unsigned int y) - : m_canvas(dmnsn_new_canvas(x, y)) { } + Canvas(unsigned int width, unsigned int height) + : m_canvas(dmnsn_new_canvas(width, height)) { } + explicit Canvas(dmnsn_canvas* canvas) : m_canvas(canvas) { } virtual ~Canvas(); + unsigned int width() const { return m_canvas->x; } + unsigned int height() const { return m_canvas->y; } + Color pixel(unsigned int x, unsigned int y) const { return Color(dmnsn_get_pixel(m_canvas, x, y)); } void pixel(unsigned int x, unsigned int y, const Color& c) @@ -38,9 +42,12 @@ namespace Dimension dmnsn_canvas* dmnsn() { return m_canvas; } const dmnsn_canvas* dmnsn() const { return m_canvas; } - private: + protected: + Canvas() : m_canvas(0) { } + dmnsn_canvas* m_canvas; + private: // Copying prohibited Canvas(const Canvas&); Canvas& operator=(const Canvas&); diff --git a/libdimensionxx/dimensionxx/color.hpp b/libdimensionxx/dimensionxx/color.hpp index 5db041a..afd7ea5 100644 --- a/libdimensionxx/dimensionxx/color.hpp +++ b/libdimensionxx/dimensionxx/color.hpp @@ -51,6 +51,8 @@ namespace Dimension double trans(double t) { m_color.trans = t; } // Color& operator=(const Color& c); + Color& operator+=(const Color& c) + { m_color = dmnsn_color_add(m_color, c.m_color); return *this; } dmnsn_color dmnsn() const { return m_color; } @@ -61,6 +63,7 @@ namespace Dimension class CIE_XYZ { public: + CIE_XYZ() { } CIE_XYZ(double X, double Y, double Z) { m_XYZ.X = X; m_XYZ.Y = Y; m_XYZ.Z = Z; } CIE_XYZ(const Color& c) : m_XYZ(dmnsn_XYZ_from_color(c.dmnsn())) { } @@ -85,6 +88,7 @@ namespace Dimension class CIE_xyY { public: + CIE_xyY() { } CIE_xyY(double x, double y, double Y) { m_xyY.x = x; m_xyY.y = y; m_xyY.Y = Y; } CIE_xyY(const Color& c) : m_xyY(dmnsn_xyY_from_color(c.dmnsn())) { } @@ -109,6 +113,7 @@ namespace Dimension class CIE_Lab { public: + CIE_Lab() { } CIE_Lab(double L, double a, double b) { m_Lab.L = L; m_Lab.a = a; m_Lab.b = b; } CIE_Lab(const Color& c, const CIE_XYZ& white = whitepoint) @@ -134,6 +139,7 @@ namespace Dimension class CIE_Luv { public: + CIE_Luv() { } CIE_Luv(double L, double u, double v) { m_Luv.L = L; m_Luv.u = u; m_Luv.v = v; } CIE_Luv(const Color& c, const CIE_XYZ& white = whitepoint) @@ -159,6 +165,7 @@ namespace Dimension class sRGB { public: + sRGB() { } sRGB(double R, double G, double B) { m_RGB.R = R; m_RGB.G = G; m_RGB.B = B; } sRGB(const Color& c) : m_RGB(dmnsn_sRGB_from_color(c.dmnsn())) { } @@ -180,6 +187,8 @@ namespace Dimension dmnsn_sRGB m_RGB; }; + // Color inline constructors + inline Color::Color(const CIE_XYZ& XYZ) : m_color(dmnsn_color_from_XYZ(XYZ.dmnsn())) { } @@ -194,6 +203,22 @@ namespace Dimension inline Color::Color(const sRGB& RGB) : m_color(dmnsn_color_from_sRGB(RGB.dmnsn())) { } + + // Color operators + + inline Color + operator+(const Color& lhs, const Color& rhs) + { + Color temp = lhs; + temp += rhs; + return temp; + } + + inline double + operator-(const Color& lhs, const Color& rhs) + { + return dmnsn_color_difference(lhs.dmnsn(), rhs.dmnsn()); + } } #endif /* DIMENSIONXX_COLOR_HPP */ diff --git a/libdimensionxx/dimensionxx/cookie.hpp b/libdimensionxx/dimensionxx/cookie.hpp new file mode 100644 index 0000000..acb783d --- /dev/null +++ b/libdimensionxx/dimensionxx/cookie.hpp @@ -0,0 +1,35 @@ +/************************************************************************* + * Copyright (C) 2008 Tavian Barnes * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension 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 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension 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 program. If not, see * + * . * + *************************************************************************/ + +#ifndef DIMENSIONXX_COOKIE_HPP +#define DIMENSIONXX_COOKIE_HPP + +#include +#include +#include + +namespace Dimension +{ + std::FILE* fcookie(std::istream& istr); + std::FILE* fcookie(std::ostream& ostr); + std::FILE* fcookie(std::iostream& iostr); +} + +#endif /* DIMENSIONXX_COOKIE_HPP */ diff --git a/libdimensionxx/dimensionxx/error.hpp b/libdimensionxx/dimensionxx/error.hpp new file mode 100644 index 0000000..a6a4ca6 --- /dev/null +++ b/libdimensionxx/dimensionxx/error.hpp @@ -0,0 +1,30 @@ +/************************************************************************* + * Copyright (C) 2008 Tavian Barnes * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension 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 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension 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 program. If not, see * + * . * + *************************************************************************/ + +#ifndef DIMENSIONXX_ERROR_HPP +#define DIMENSIONXX_ERROR_HPP + +#include + +namespace Dimension +{ +} + +#endif /* DIMENSIONXX_ERROR_HPP */ diff --git a/libdimensionxx/dimensionxx/png.hpp b/libdimensionxx/dimensionxx/png.hpp new file mode 100644 index 0000000..96ab2ca --- /dev/null +++ b/libdimensionxx/dimensionxx/png.hpp @@ -0,0 +1,59 @@ +/************************************************************************* + * Copyright (C) 2008 Tavian Barnes * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension 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 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension 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 program. If not, see * + * . * + *************************************************************************/ + +#ifndef DIMENSIONXX_PNG_HPP +#define DIMENSIONXX_PNG_HPP + +#include +#include + +namespace Dimension +{ + class PNG_Canvas : public Canvas + { + public: + explicit PNG_Canvas(std::istream& istr) + : Canvas(), m_istr(&istr), m_ostr(0), m_written(false) { read(); } + PNG_Canvas(unsigned int x, unsigned int y, std::ostream& ostr) + : Canvas(x, y), m_istr(0), m_ostr(&ostr), m_written(false) { } + PNG_Canvas(std::istream& istr, std::ostream& ostr) + : Canvas(), m_istr(&istr), m_ostr(&ostr), m_written(false) { read(); } + virtual ~PNG_Canvas(); + + void write(); + + protected: + PNG_Canvas(std::ostream* ostr) + : Canvas(), m_istr(0), m_ostr(ostr), m_written(false) { } + + private: + std::istream* m_istr; + std::ostream* m_ostr; + bool m_written; + + void read(); + + // Copying prohibited + PNG_Canvas(const PNG_Canvas&); + PNG_Canvas& operator=(const PNG_Canvas&); + }; +} + +#endif /* DIMENSIONXX_PNG_HPP */ diff --git a/libdimensionxx/png.cpp b/libdimensionxx/png.cpp new file mode 100644 index 0000000..14b8c4d --- /dev/null +++ b/libdimensionxx/png.cpp @@ -0,0 +1,96 @@ +/************************************************************************* + * Copyright (C) 2008 Tavian Barnes * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension 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 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension 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 program. If not, see * + * . * + *************************************************************************/ + +#include "dimensionxx.hpp" +#include "../libdimension-png/dimension-png.h" + +namespace Dimension +{ + PNG_Canvas::~PNG_Canvas() + { + if (m_ostr && !m_written) { + try { + write(); + } catch (...) { + dmnsn_error(DMNSN_SEVERITY_MEDIUM, + "Writing canvas to PNG failed in PNG_Canvas destructor."); + } + } + } + + void PNG_Canvas::write() + { + if (m_written) { + dmnsn_error(DMNSN_SEVERITY_MEDIUM, + "Attempt to write canvas to PNG twice."); + return; + } + + if (!m_ostr) { + dmnsn_error(DMNSN_SEVERITY_MEDIUM, + "Attempt to write canvas to PNG without an output stream."); + return; + } + + FILE* file = fcookie(*m_ostr); + if (!file) { + dmnsn_error(DMNSN_SEVERITY_MEDIUM, + "Couldn't create C++/C IO interface when writing canvas" + " to PNG."); + return; + } + + if (dmnsn_png_write_canvas(m_canvas, file)) { + fclose(file); + dmnsn_error(DMNSN_SEVERITY_MEDIUM, + "Writing canvas to PNG failed."); + return; + } + + fclose(file); + m_written = true; + } + + void PNG_Canvas::read() + { + if (!m_istr) { + dmnsn_error(DMNSN_SEVERITY_MEDIUM, + "Attempt to read canvas from PNG without an input stream."); + return; + } + + FILE* file = fcookie(*m_istr); + if (!file) { + dmnsn_error(DMNSN_SEVERITY_MEDIUM, + "Couldn't create C++/C IO interface when reading canvas" + " from PNG."); + return; + } + + if (!(m_canvas = dmnsn_png_read_canvas(file))) { + fclose(file); + dmnsn_error(DMNSN_SEVERITY_MEDIUM, + "Reading canvas from PNG failed."); + return; + } + + fclose(file); + } +} -- cgit v1.2.3