/* * Image output functions * * Copyright (C) 2019 Patrick McDermott * * This file is part of fbcon2png. * * fbcon2png is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * fbcon2png 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with fbcon2png. If not, see . */ #include "image.h" #include #include #include #include #include "font.h" #include "i18n.h" #include "output.h" #include "text.h" struct image { FILE *fp; png_structp png_ptr; png_infop info_ptr; }; struct image * image_new(const char *file_name) { struct image *image; assert(file_name && *file_name); image = calloc(1, sizeof(*image)); if (!image) { error(_("Cannot allocate memory for image object")); return NULL; } if (strcmp(file_name, "-") != 0) { image->fp = fopen(file_name, "wb"); if (!image->fp) { error(_("Cannot open \"%s\" for writing"), file_name); return image_destroy(&image); } } image->png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!image->png_ptr) { error(_("Failed to create PNG structure")); return image_destroy(&image); } image->info_ptr = png_create_info_struct(image->png_ptr); if (!image->info_ptr) { error(_("Failed to create PNG info structure")); return image_destroy(&image); } if (image->fp) { png_init_io(image->png_ptr, image->fp); } else { png_init_io(image->png_ptr, stdout); } return image; } void image_render(struct image *image, const struct text *text, const struct font *font) { size_t width; size_t height; png_byte **rows; size_t i; assert(image); assert(text); assert(font); width = text_get_width(text) * font_get_width(font); height = text_get_height(text) * font_get_height(font); png_set_IHDR(image->png_ptr, image->info_ptr, width, height, IMAGE_BIT_DEPTH, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); rows = png_malloc(image->png_ptr, height * sizeof(*rows)); for (i = 0; i < height; ++i) { rows[i] = png_malloc(image->png_ptr, width * IMAGE_PIXEL_SIZE); } png_set_rows(image->png_ptr, image->info_ptr, rows); text_render(text, font, rows); png_write_png(image->png_ptr, image->info_ptr, PNG_TRANSFORM_IDENTITY, NULL); for (i = 0; i < height; ++i) { png_free(image->png_ptr, rows[i]); } png_free(image->png_ptr, rows); } struct image * image_destroy(struct image **image_p) { struct image *image; assert(image_p && *image_p); image = *image_p; if (image->fp) { fclose(image->fp); } png_destroy_write_struct(&image->png_ptr, &image->info_ptr); free(image); return image = NULL; }