198 lines
5.2 KiB
C
198 lines
5.2 KiB
C
/*
|
|
* Orginal copyright from libpng example code
|
|
*
|
|
* Copyright 2002-2011 Guillaume Cottenceau and contributors.
|
|
*
|
|
* This software may be freely redistributed under the terms
|
|
* of the X11 license.
|
|
*
|
|
*/
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#include <png.h>
|
|
|
|
#include "imagecon.h"
|
|
|
|
static void
|
|
_wrapjmp(png_structp png_ptr)
|
|
{
|
|
if (setjmp(png_jmpbuf(png_ptr)))
|
|
abort_("Error during init_io");
|
|
}
|
|
|
|
static inline void
|
|
setRGB(png_byte *ptr, amiga_color_t color)
|
|
{
|
|
*ptr++ = color.r;
|
|
*ptr++ = color.g;
|
|
*ptr++ = color.b;
|
|
}
|
|
|
|
void
|
|
png_read(imagecon_image_t* ic, char* filename)
|
|
{
|
|
png_structp png_ptr;
|
|
png_byte color_type;
|
|
png_byte bit_depth;
|
|
png_infop info_ptr;
|
|
int number_of_passes = 0, rowbytes;
|
|
unsigned char header[8]; // 8 is the maximum size that can be checked
|
|
|
|
/* open file and test for it being a png */
|
|
FILE *fp = fopen(filename, "rb");
|
|
if (!fp)
|
|
abort_("Failed to open %s", filename);
|
|
fread(header, 1, 8, fp);
|
|
if (png_sig_cmp(header, 0, 8))
|
|
abort_("File %s is not recognized as a PNG file", filename);
|
|
|
|
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
|
|
|
if (!png_ptr)
|
|
abort_("png_create_read_struct failed");
|
|
|
|
info_ptr = png_create_info_struct(png_ptr);
|
|
if (!info_ptr)
|
|
abort_("png_create_info_struct failed");
|
|
|
|
|
|
_wrapjmp(png_ptr);
|
|
png_init_io(png_ptr, fp);
|
|
png_set_sig_bytes(png_ptr, 8);
|
|
|
|
png_read_info(png_ptr, info_ptr);
|
|
|
|
ic->width = png_get_image_width(png_ptr, info_ptr);
|
|
ic->height = png_get_image_height(png_ptr, info_ptr);
|
|
color_type = png_get_color_type(png_ptr, info_ptr);
|
|
bit_depth = png_get_bit_depth(png_ptr, info_ptr);
|
|
|
|
if (config.verbose) {
|
|
printf("width = %d\n", ic->width);
|
|
printf("height = %d\n", ic->height);
|
|
printf("color_type = %d (palette = %s)\n", color_type, color_type == PNG_COLOR_TYPE_PALETTE ? "yes" : "no");
|
|
printf("bit_depth = %d\n", bit_depth);
|
|
printf("number_of_passes = %d\n", number_of_passes);
|
|
}
|
|
|
|
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
|
png_set_palette_to_rgb(png_ptr);
|
|
|
|
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
|
png_set_expand_gray_1_2_4_to_8(png_ptr);
|
|
|
|
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
|
png_set_tRNS_to_alpha(png_ptr);
|
|
|
|
if (color_type == PNG_COLOR_TYPE_RGB ||
|
|
color_type == PNG_COLOR_TYPE_GRAY ||
|
|
color_type == PNG_COLOR_TYPE_PALETTE)
|
|
png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER);
|
|
|
|
if (bit_depth == 16)
|
|
png_set_strip_16(png_ptr);
|
|
|
|
number_of_passes = png_set_interlace_handling(png_ptr);
|
|
|
|
png_read_update_info(png_ptr, info_ptr);
|
|
ic->width = png_get_image_width(png_ptr, info_ptr);
|
|
ic->height = png_get_image_height(png_ptr, info_ptr);
|
|
color_type = png_get_color_type(png_ptr, info_ptr);
|
|
bit_depth = png_get_bit_depth(png_ptr, info_ptr);
|
|
|
|
if (setjmp(png_jmpbuf(png_ptr)))
|
|
abort_("Error during read_image");
|
|
|
|
ic->rowPointers = (png_bytep*) malloc(sizeof(png_bytep) * ic->height);
|
|
|
|
/*
|
|
if (bit_depth == 16)
|
|
rowbytes = ic->width*8;
|
|
else */
|
|
rowbytes = ic->width*4;
|
|
|
|
|
|
for (int y=0; y< ic->height; y++)
|
|
ic->rowPointers[y] = (png_byte*) malloc(rowbytes);
|
|
|
|
png_read_image(png_ptr, ic->rowPointers);
|
|
|
|
fclose(fp);
|
|
|
|
if (config.verbose) {
|
|
printf("width = %d\n", ic->width);
|
|
printf("height = %d\n", ic->height);
|
|
printf("color_type = %d (palette = %s)\n", color_type, color_type == PNG_COLOR_TYPE_PALETTE ? "yes" : "no");
|
|
printf("bit_depth = %d\n", bit_depth);
|
|
printf("number_of_passes = %d\n", number_of_passes);
|
|
}
|
|
|
|
ic->amigaImage = calloc(ic->width*ic->height, 1);
|
|
ic->dithered = 0;
|
|
}
|
|
|
|
|
|
void
|
|
png_write(imagecon_image_t* ic, char* filename)
|
|
{
|
|
FILE *fp = file_openWrite(filename);
|
|
png_structp png_ptr = NULL;
|
|
png_infop info_ptr = NULL;
|
|
png_bytep row = NULL;
|
|
|
|
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
|
|
|
if (png_ptr == NULL) {
|
|
abort_("png_write: could not allocate write struct");
|
|
}
|
|
|
|
info_ptr = png_create_info_struct(png_ptr);
|
|
if (info_ptr == NULL) {
|
|
abort_("png_write: could not allocate info struct");
|
|
}
|
|
|
|
if (setjmp(png_jmpbuf(png_ptr))) {
|
|
abort_("png_write: error during png creation");
|
|
}
|
|
|
|
png_init_io(png_ptr, fp);
|
|
|
|
// Write header (8 bit colour depth)
|
|
png_set_IHDR(png_ptr, info_ptr, ic->width, ic->height,
|
|
8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
|
|
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
|
|
|
// Set title
|
|
if (filename != NULL) {
|
|
png_text title_text;
|
|
title_text.compression = PNG_TEXT_COMPRESSION_NONE;
|
|
title_text.key = "Title";
|
|
title_text.text = filename;
|
|
png_set_text(png_ptr, info_ptr, &title_text, 1);
|
|
}
|
|
|
|
png_write_info(png_ptr, info_ptr);
|
|
|
|
// Allocate memory for one row (3 bytes per pixel - RGB)
|
|
row = (png_bytep) malloc(3 * ic->width * sizeof(png_byte));
|
|
|
|
// Write image data
|
|
int x, y;
|
|
for (y=0 ; y<ic->height ; y++) {
|
|
for (x=0 ; x<ic->width ; x++) {
|
|
setRGB(&(row[x*3]), color_getPalettedPixel(ic, x, y));
|
|
}
|
|
png_write_row(png_ptr, row);
|
|
}
|
|
|
|
// End write
|
|
png_write_end(png_ptr, NULL);
|
|
|
|
if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
|
|
if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
|
|
if (row != NULL) free(row);
|
|
}
|