Commit 46d6b475 authored by Paul Asmuth's avatar Paul Asmuth
Browse files

write pixmap to disk using libpng

parent aa5eeee8
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -11,7 +11,8 @@ find_package(Threads)
find_package(Cairo)
find_package(Freetype)
find_package(HarfBuzz)
include_directories(${CAIRO_INCLUDE_DIRS} ${FREETYPE_INCLUDE_DIRS} ${HARFBUZZ_INCLUDE_DIRS})
find_package(PNG)
include_directories(${CAIRO_INCLUDE_DIRS} ${FREETYPE_INCLUDE_DIRS} ${HARFBUZZ_INCLUDE_DIRS} ${PNG_INCLUDE_DIRS})

add_definitions(-DFNORDMETRIC_VERSION="unstable")

@@ -23,6 +24,7 @@ add_library(signaltk STATIC
    src/signaltk/core/layer.cc
    src/signaltk/core/text.cc
    src/signaltk/core/rasterize.cc
    src/signaltk/codec/png.cc
    src/signaltk/plot/gridlines.cc
    src/signaltk/plot/axes.cc
    src/signaltk/plot/domain.cc
@@ -30,7 +32,6 @@ add_library(signaltk STATIC
    src/signaltk/plot/legenddefinition.cc
    src/signaltk/plot/series.cc
    src/signaltk/plot/timedomain.cc
    src/signaltk/plot/plot_api.cc
    src/signaltk/text/text_layout.cc
    src/signaltk/text/text_shaper.cc
    src/signaltk/util/random.cc
@@ -53,7 +54,7 @@ add_library(signaltk STATIC
    src/signaltk_cli.cc
    src/signaltk_cmd.cc)

set(SIGNALTK_LDFLAGS signaltk ${CAIRO_LIBRARIES} ${FREETYPE_LIBRARIES} ${HARFBUZZ_LIBRARIES} ${HARFBUZZ_ICU_LIBRARIES})
set(SIGNALTK_LDFLAGS signaltk ${CAIRO_LIBRARIES} ${FREETYPE_LIBRARIES} ${HARFBUZZ_LIBRARIES} ${HARFBUZZ_ICU_LIBRARIES} ${PNG_LIBRARIES})

file(GLOB test_files "test/**/test_*.cc")
foreach(test_path ${test_files})
+1 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ struct Context {
enum Status : int {
  OK,
  ERROR,
  ERROR_IO,
  ERROR_NOT_IMPLEMENTED,
  ERROR_INVALID_ARGUMENT
};
+85 −0
Original line number Diff line number Diff line
/**
 * This file is part of the "signaltk" project
 *   Copyright (c) 2017 Paul Asmuth
 *
 * signaltk is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <unistd.h>
#include <iostream>
#include <png.h>
#include <string.h>
#include "png.h"
#include "signaltk/util/file.h"
#include "signaltk/util/fileutil.h"

namespace signaltk {

Status pngWriteImageFile(
    const Image& image,
    const std::string& filename) {
  int color_type;
  int bit_depth;
  switch (image.getPixelFormat()) {
    case PixelFormat::RGB8:
      bit_depth = 8;
      color_type = PNG_COLOR_TYPE_RGB;
      break;
    case PixelFormat::RGBA8:
      bit_depth = 8;
      color_type = PNG_COLOR_TYPE_RGB_ALPHA;
      break;
    default:
      return ERROR_INVALID_ARGUMENT;
  }

  FILE* file = fopen(filename.c_str(), "wb");

  auto png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (!png) {
    fclose(file);
    return ERROR_IO;
  }

  auto png_info = png_create_info_struct(png);
  if (!png_info) {
    fclose(file);
    png_destroy_write_struct(&png, NULL);
    return ERROR_IO;
  }

  png_init_io(png, file);

  png_set_IHDR(
      png,
      png_info,
      image.getWidth(),
      image.getHeight(),
      bit_depth,
      color_type,
      PNG_INTERLACE_NONE,
      PNG_COMPRESSION_TYPE_BASE,
      PNG_FILTER_TYPE_BASE);

  png_write_info(png, png_info);

  std::vector<uint8_t> buf(sizeof(png_bytep) * image.getHeight());
  for (size_t i = 0; i < image.getHeight(); i++) {
    auto row = ((char *) image.getData()) + i * image.getPixelSize() * image.getWidth();
    ((png_bytepp) buf.data())[i] = (png_byte *) row;
  }

  png_write_image(png, (png_bytepp) buf.data());

  png_write_end(png, NULL);
  png_destroy_info_struct(png, &png_info);
  png_destroy_write_struct(&png, NULL);
  fclose(file);

  return OK;
}

} // namespace signaltk
+24 −0
Original line number Diff line number Diff line
/**
 * This file is part of the "signaltk" project
 *   Copyright (c) 2017 Paul Asmuth
 *
 * signaltk is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#pragma once
#include <stdlib.h>
#include <string>
#include <vector>
#include <signaltk.h>
#include <signaltk/core/image.h>

namespace signaltk {

Status pngWriteImageFile(
    const Image& image,
    const std::string& filename);

} // namespace signaltk
+12 −38
Original line number Diff line number Diff line
@@ -9,6 +9,8 @@
 * <http://www.gnu.org/licenses/>.
 */
#include "layer.h"
#include <signaltk/util/stringutil.h>
#include <signaltk/codec/png.h>

namespace signaltk {

@@ -25,48 +27,20 @@ Layer::Layer(

Layer::~Layer() {}

void Layer::clear(const Colour& c) {
  auto ctx = rasterizer.ctx;
  cairo_set_source_rgba(ctx, c.red(), c.green(), c.blue(), c.alpha());
  cairo_rectangle(ctx, 0, 0, width, height);
  cairo_fill(ctx);
Status Layer::writeToFile(const std::string& path) {
  if (StringUtil::endsWith(path, ".png")) {
    return pngWriteImageFile(pixmap, path);
  }

//bool Layer::loadPNG(const char* path) {
//  auto surface = rasterizer.surface;
//  auto ctx = rasterizer.ctx;
//  if (surface || ctx) {
//    return false;
//  }
//
//  surface = cairo_image_surface_create_from_png(path);
//  if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
//    return false;
//  }
//
//  ctx = cairo_create(surface);
//
//  double extent[4];
//  cairo_clip_extents(ctx, extent + 0, extent + 1, extent + 2, extent + 3);
//  width = extent[2] - extent[0];
//  height = extent[3] - extent[1];
//
//  return true;
//}

bool Layer::writePNG(const char* path) const {
  auto surface = rasterizer.surface;
  auto ctx = rasterizer.ctx;
  if (!surface || !ctx) {
    return false;
  return ERROR_INVALID_ARGUMENT;
}

  auto rc = cairo_surface_write_to_png(surface, path);
  return rc == CAIRO_STATUS_SUCCESS;
Status Layer::loadFromFile(const std::string& path) const {
  return ERROR_INVALID_ARGUMENT;
}

bool Layer::writePNG(const std::string& path) const {
  return writePNG(path.c_str());
void Layer::clear(const Colour& c) {
  pixmap.clear(c);
}

} // namespace signaltk
Loading