Blame synfig-core/src/modules/mod_png/trgt_png_spritesheet.cpp

Moritz Grosch (LittleFox) 5352f3
/* === S Y N F I G ========================================================= */
Moritz Grosch (LittleFox) 5352f3
/*!	\file trgt_png_spriteengine.cpp
Moritz Grosch (LittleFox) 5352f3
**	\brief png_trgt Target Module
Moritz Grosch (LittleFox) 5352f3
**
Moritz Grosch (LittleFox) 5352f3
**	$Id$
Moritz Grosch (LittleFox) 5352f3
**
Moritz Grosch (LittleFox) 5352f3
**	\legal
Moritz Grosch (LittleFox) 5352f3
**	Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
Moritz Grosch (LittleFox) 5352f3
**	Copyright (c) 2007 Chris Moore
2ed9df
**	Copyright (c) 2013 Moritz Grosch (LittleFox) <littlefox@fsfe.org></littlefox@fsfe.org>
Moritz Grosch (LittleFox) 5352f3
**
Moritz Grosch (LittleFox) 5352f3
**  Based on trgt_png.cpp
Moritz Grosch (LittleFox) 5352f3
**
Moritz Grosch (LittleFox) 5352f3
**	This package is free software; you can redistribute it and/or
Moritz Grosch (LittleFox) 5352f3
**	modify it under the terms of the GNU General Public License as
Moritz Grosch (LittleFox) 5352f3
**	published by the Free Software Foundation; either version 2 of
Moritz Grosch (LittleFox) 5352f3
**	the License, or (at your option) any later version.
Moritz Grosch (LittleFox) 5352f3
**
Moritz Grosch (LittleFox) 5352f3
**	This package is distributed in the hope that it will be useful,
Moritz Grosch (LittleFox) 5352f3
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
Moritz Grosch (LittleFox) 5352f3
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Moritz Grosch (LittleFox) 5352f3
**	General Public License for more details.
Moritz Grosch (LittleFox) 5352f3
**	\endlegal
Moritz Grosch (LittleFox) 5352f3
**
Moritz Grosch (LittleFox) 5352f3
** === N O T E S ===========================================================
Moritz Grosch (LittleFox) 5352f3
**
Moritz Grosch (LittleFox) 5352f3
** ========================================================================= */
Moritz Grosch (LittleFox) 5352f3
Moritz Grosch (LittleFox) 5352f3
/* === H E A D E R S ======================================================= */
Moritz Grosch (LittleFox) 5352f3
Moritz Grosch (LittleFox) 5352f3
#ifdef USING_PCH
Moritz Grosch (LittleFox) 5352f3
#	include "pch.h"
Moritz Grosch (LittleFox) 5352f3
#else
Moritz Grosch (LittleFox) 5352f3
#ifdef HAVE_CONFIG_H
Moritz Grosch (LittleFox) 5352f3
#	include <config.h></config.h>
Moritz Grosch (LittleFox) 5352f3
#endif
Moritz Grosch (LittleFox) 5352f3
bw 94d8a6
#include <synfig localization.h=""></synfig>
bw 94d8a6
#include <synfig general.h=""></synfig>
bw 94d8a6
Moritz Grosch (LittleFox) 5352f3
#include "trgt_png_spritesheet.h"
Moritz Grosch (LittleFox) 5352f3
#include <png.h></png.h>
Moritz Grosch (LittleFox) 5352f3
#include <etl stringf=""></etl>
Moritz Grosch (LittleFox) 5352f3
#include <cstdio></cstdio>
337598
#include <cstring> </cstring>
Moritz Grosch (LittleFox) 5352f3
#include <algorithm></algorithm>
Moritz Grosch (LittleFox) 5352f3
#include <functional></functional>
Moritz Grosch (LittleFox) 5352f3
#include <etl misc=""></etl>
trizer 613172
#include <iostream></iostream>
Moritz Grosch (LittleFox) 5352f3
Moritz Grosch (LittleFox) 5352f3
#endif
Moritz Grosch (LittleFox) 5352f3
Moritz Grosch (LittleFox) 5352f3
/* === M A C R O S ========================================================= */
Moritz Grosch (LittleFox) 5352f3
Moritz Grosch (LittleFox) 5352f3
using namespace synfig;
Moritz Grosch (LittleFox) 5352f3
using namespace std;
Moritz Grosch (LittleFox) 5352f3
using namespace etl;
Moritz Grosch (LittleFox) 5352f3
Moritz Grosch (LittleFox) 5352f3
/* === G L O B A L S ======================================================= */
Moritz Grosch (LittleFox) 5352f3
Moritz Grosch (LittleFox) 5352f3
SYNFIG_TARGET_INIT(png_trgt_spritesheet);
2ed9df
SYNFIG_TARGET_SET_NAME(png_trgt_spritesheet,"png-spritesheet");
2ed9df
SYNFIG_TARGET_SET_EXT(png_trgt_spritesheet,"png");
Moritz Grosch (LittleFox) 5352f3
SYNFIG_TARGET_SET_VERSION(png_trgt_spritesheet,"0.1");
Moritz Grosch (LittleFox) 5352f3
SYNFIG_TARGET_SET_CVS_ID(png_trgt_spritesheet,"$Id$");
Moritz Grosch (LittleFox) 5352f3
Moritz Grosch (LittleFox) 5352f3
/* === M E T H O D S ======================================================= */
Moritz Grosch (LittleFox) 5352f3
Moritz Grosch (LittleFox) 5352f3
void
Moritz Grosch (LittleFox) 5352f3
png_trgt_spritesheet::png_out_error(png_struct *png_data,const char *msg)
Moritz Grosch (LittleFox) 5352f3
{
Moritz Grosch (LittleFox) 5352f3
    png_trgt_spritesheet *me=(png_trgt_spritesheet*)png_get_error_ptr(png_data);
Moritz Grosch (LittleFox) 5352f3
    synfig::error(strprintf("png_trgt_spritesheet: error: %s",msg));
Moritz Grosch (LittleFox) 5352f3
    me->ready=false;
Moritz Grosch (LittleFox) 5352f3
}
Moritz Grosch (LittleFox) 5352f3
Moritz Grosch (LittleFox) 5352f3
void
Moritz Grosch (LittleFox) 5352f3
png_trgt_spritesheet::png_out_warning(png_struct *png_data,const char *msg)
Moritz Grosch (LittleFox) 5352f3
{
Moritz Grosch (LittleFox) 5352f3
    png_trgt_spritesheet *me=(png_trgt_spritesheet*)png_get_error_ptr(png_data);
Moritz Grosch (LittleFox) 5352f3
    synfig::warning(strprintf("png_trgt_spritesheet: warning: %s",msg));
Moritz Grosch (LittleFox) 5352f3
    me->ready=false;
Moritz Grosch (LittleFox) 5352f3
}
Moritz Grosch (LittleFox) 5352f3
Moritz Grosch (LittleFox) 5352f3
Moritz Grosch (LittleFox) 5352f3
//Target *png_trgt::New(const char *filename){	return new png_trgt(filename);}
Moritz Grosch (LittleFox) 5352f3
6320b8
png_trgt_spritesheet::png_trgt_spritesheet(const char *Filename, const synfig::TargetParam ¶ms):
6320b8
	ready(false),
6320b8
	initialized(false),
6320b8
	imagecount(),
6320b8
	lastimage(),
6320b8
	numimages(),
trizer 613172
	cur_y(0),
trizer d2fcc7
	cur_row(0),
trizer d2fcc7
	cur_col(0),
trizer 613172
	params(params),
trizer 613172
	color_data(0),
trizer 613172
	sheet_width(0),
trizer 613172
	sheet_height(0),
trizer 613172
	in_file_pointer(0),
e8b33d
	out_file_pointer(0),
e8b33d
	cur_out_image_row(0),
6320b8
	filename(Filename),
Denis Zdorovtsov 76fe0c
	sequence_separator(params.sequence_separator),
Denis Zdorovtsov 76fe0c
	overflow_buff(0)
Moritz Grosch (LittleFox) 5352f3
{
trizer 4e2b93
	cout << "png_trgt_spritesheet() " << params.offset_x << " " << params.offset_y << endl;
Moritz Grosch (LittleFox) 5352f3
}
Moritz Grosch (LittleFox) 5352f3
Moritz Grosch (LittleFox) 5352f3
png_trgt_spritesheet::~png_trgt_spritesheet()
Moritz Grosch (LittleFox) 5352f3
{
trizer 613172
	cout << "~png_trgt_spritesheet()" << endl;
trizer 613172
	if (ready)
trizer 613172
		write_png_file ();
trizer 613172
	if (color_data)
trizer 613172
	{
trizer 613172
		for (unsigned int i = 0; i < sheet_height; i++)
trizer 613172
			delete []color_data[i];
trizer 613172
		delete []color_data;
trizer 613172
	}
Denis Zdorovtsov 76fe0c
	if (overflow_buff)
Denis Zdorovtsov 76fe0c
		delete []overflow_buff;
Moritz Grosch (LittleFox) 5352f3
}
Moritz Grosch (LittleFox) 5352f3
Moritz Grosch (LittleFox) 5352f3
bool
Moritz Grosch (LittleFox) 5352f3
png_trgt_spritesheet::set_rend_desc(RendDesc *given_desc)
Moritz Grosch (LittleFox) 5352f3
{
trizer 613172
	cout << "set_rend_desc()" << endl;
Moritz Grosch (LittleFox) 5352f3
    //given_desc->set_pixel_format(PixelFormat((int)PF_RGB|(int)PF_A));
Moritz Grosch (LittleFox) 5352f3
    desc=*given_desc;
Moritz Grosch (LittleFox) 5352f3
    imagecount=desc.get_frame_start();
Moritz Grosch (LittleFox) 5352f3
    lastimage=desc.get_frame_end();
Denis Zdorovtsov 76fe0c
    numimages = (lastimage - imagecount) + 1;		
Moritz Grosch (LittleFox) 5352f3
Denis Zdorovtsov 76fe0c
	overflow_buff = new Color[desc.get_w()];
Denis Zdorovtsov 76fe0c
	
Denis Zdorovtsov 76fe0c
	//Reset on uninitialized values
Denis Zdorovtsov 76fe0c
	if ((params.columns == 0) || (params.rows == 0))
Denis Zdorovtsov 76fe0c
	{
luz.paz 55f599
		cout << "Uninitialized sheet parameters. Reset parameters." << endl;
trizer d2fcc7
		params.columns = numimages;
Denis Zdorovtsov 76fe0c
		params.rows = 1;
Denis Zdorovtsov 76fe0c
		params.append = true;
Denis Zdorovtsov 76fe0c
		params.dir = TargetParam::HR;
Denis Zdorovtsov 76fe0c
	}
Denis Zdorovtsov 76fe0c
Denis Zdorovtsov 76fe0c
	//Break on overflow
Denis Zdorovtsov 76fe0c
	if (params.columns * params.rows < numimages)
Denis Zdorovtsov 76fe0c
	{
Denis Zdorovtsov 76fe0c
		cout << "Sheet overflow. Break." << endl;
Denis Zdorovtsov 76fe0c
		synfig::error("Bad sheet parameters. Sheet overflow.");
Denis Zdorovtsov 76fe0c
		return false;
Denis Zdorovtsov 76fe0c
	}
trizer d2fcc7
	
trizer 613172
	cout << "Frame count" << numimages << endl;
Moritz Grosch (LittleFox) 5352f3
trizer 613172
	bool is_loaded = false;
Denis Zdorovtsov 76fe0c
Denis Zdorovtsov 76fe0c
	if (params.append)
trizer 613172
	{
Denis Zdorovtsov 76fe0c
		in_file_pointer = fopen(filename.c_str(), "rb");
Denis Zdorovtsov 76fe0c
		if (!in_file_pointer)
Denis Zdorovtsov 76fe0c
			synfig::error(strprintf("[read_png_file] File %s could not be opened for reading", filename.c_str()));
Denis Zdorovtsov 76fe0c
		else
Denis Zdorovtsov 76fe0c
		{
Denis Zdorovtsov 76fe0c
			is_loaded = load_png_file();
Denis Zdorovtsov 76fe0c
			if (!is_loaded)
Denis Zdorovtsov 76fe0c
				fclose(in_file_pointer);
Denis Zdorovtsov 76fe0c
		}
trizer 613172
	}
trizer 613172
		
trizer 613172
	//I select such size which appropriate to contain whole sprite sheet.
trizer d2fcc7
	unsigned int target_width = params.columns * desc.get_w() + params.offset_x;
trizer d2fcc7
	unsigned int target_height = params.rows * desc.get_h() + params.offset_y;
trizer 613172
	sheet_width = in_image.width > target_width? in_image.width : target_width;
trizer 613172
	sheet_height = in_image.height > target_height? in_image.height : target_height;
trizer 613172
trizer 613172
	if (sheet_width * sheet_height > 5000 * 2000)
trizer 613172
	{
luz.paz 55f599
		synfig::error(strprintf(_("The image is too large. It's size must be not more than 5000*2000=10000000 px. Currently it's %d*%d=%d px."), 
trizer 613172
		                          sheet_width, sheet_height, sheet_width * sheet_height));
trizer 613172
		return false;
trizer 613172
	}
trizer 613172
	
trizer 613172
	cout << "Sheet size: " << sheet_width << "x" << sheet_height << endl;
trizer 613172
trizer 613172
	cout << "Color size: " << sizeof(Color) << endl;
trizer 613172
	
trizer 613172
	color_data = new Color*[sheet_height];
trizer 613172
	for (unsigned int i = 0; i < sheet_height; i++)
trizer 613172
		color_data[i] = new Color[sheet_width];
trizer 613172
	
trizer 613172
	if (is_loaded)
trizer 613172
		ready = read_png_file();
trizer 613172
	else
trizer 613172
		ready = true;
trizer 613172
	
Moritz Grosch (LittleFox) 5352f3
    return true;
Moritz Grosch (LittleFox) 5352f3
}
Moritz Grosch (LittleFox) 5352f3
Moritz Grosch (LittleFox) 5352f3
void
Moritz Grosch (LittleFox) 5352f3
png_trgt_spritesheet::end_frame()
Moritz Grosch (LittleFox) 5352f3
{
trizer 613172
	cout << "end_frame()" << endl;
trizer 613172
		
Moritz Grosch (LittleFox) 5352f3
    imagecount++;
trizer 613172
	cur_y = 0;
Denis Zdorovtsov 76fe0c
	if (params.dir == TargetParam::HR)
Denis Zdorovtsov 76fe0c
	{
Pascal Schmid 2891f7
		//Horizontal render. Columns increment
Denis Zdorovtsov 76fe0c
		cur_col++;
Denis Zdorovtsov 76fe0c
		if (cur_col >= (unsigned int)params.columns)
Denis Zdorovtsov 76fe0c
		{
Denis Zdorovtsov 76fe0c
			cur_row++;
Denis Zdorovtsov 76fe0c
			cur_col = 0;
Denis Zdorovtsov 76fe0c
		}
Denis Zdorovtsov 76fe0c
	}
Denis Zdorovtsov 76fe0c
	else
trizer d2fcc7
	{
Denis Zdorovtsov 76fe0c
		//Vertical render. Rows increment.
trizer d2fcc7
		cur_row++;
Denis Zdorovtsov 76fe0c
		if (cur_row >= (unsigned int) params.rows)
Denis Zdorovtsov 76fe0c
		{
Denis Zdorovtsov 76fe0c
			cur_col++;
Denis Zdorovtsov 76fe0c
			cur_row = 0;
Denis Zdorovtsov 76fe0c
		}
trizer d2fcc7
	}
Moritz Grosch (LittleFox) 5352f3
}
Moritz Grosch (LittleFox) 5352f3
Moritz Grosch (LittleFox) 5352f3
bool
Moritz Grosch (LittleFox) 5352f3
png_trgt_spritesheet::start_frame(synfig::ProgressCallback *callback)
Moritz Grosch (LittleFox) 5352f3
{
trizer 613172
	cout << "start_frame()" << endl;
trizer 613172
    if(callback)
trizer 613172
		callback->task(strprintf("%s, (frame %d/%d)", filename.c_str(), 
trizer 613172
		                         imagecount - (lastimage - numimages), numimages).c_str());
Moritz Grosch (LittleFox) 5352f3
Moritz Grosch (LittleFox) 5352f3
    return true;
Moritz Grosch (LittleFox) 5352f3
}
Moritz Grosch (LittleFox) 5352f3
Moritz Grosch (LittleFox) 5352f3
Color *
Moritz Grosch (LittleFox) 5352f3
png_trgt_spritesheet::start_scanline(int /*scanline*/)
Moritz Grosch (LittleFox) 5352f3
{
Denis Zdorovtsov 76fe0c
	unsigned int y = cur_y + params.offset_y + cur_row * desc.get_h();
Denis Zdorovtsov 76fe0c
	unsigned int x = cur_col * desc.get_w() + params.offset_x;
Denis Zdorovtsov 76fe0c
	if ((x + desc.get_w() > sheet_width) || (y > sheet_height))
Denis Zdorovtsov 76fe0c
	{
Denis Zdorovtsov 76fe0c
		cout << "Buffer overflow. x: " << x << " y: " << y << endl; 
Denis Zdorovtsov 76fe0c
		//TODO: Fix exception processing outside the module.
Denis Zdorovtsov 76fe0c
		return overflow_buff; //Spike. Bad exception processing
Denis Zdorovtsov 76fe0c
	}
Denis Zdorovtsov 76fe0c
    return &color_data[y][x];
trizer 613172
}
Moritz Grosch (LittleFox) 5352f3
trizer 613172
bool
trizer 613172
png_trgt_spritesheet::end_scanline()
trizer 613172
{
trizer 613172
	cur_y++;
trizer 613172
    return true;
trizer 613172
}
Moritz Grosch (LittleFox) 5352f3
trizer 613172
//The func only loads file. Reading into the buffer in read_png_file().
trizer 613172
bool
trizer 613172
png_trgt_spritesheet::load_png_file()
trizer 613172
{
trizer 613172
	cout << "load_png_file()" << endl;
trizer 613172
trizer 613172
    char header[8];    // 8 is the maximum size that can be checked
trizer 613172
trizer 613172
	//Reads header for next checking.
trizer 4e2b93
    int length = fread(header, 1, 8, in_file_pointer);
trizer d2fcc7
    if ((length != 8) || png_sig_cmp((unsigned char *)header, 0, 8))
trizer 613172
	{
trizer 613172
		synfig::error(strprintf("[read_png_file] File %s is not recognized as a PNG file", filename.c_str()));
trizer 613172
		return false;
trizer 613172
	}
trizer 613172
trizer 613172
    /* initialize stuff */
trizer 613172
    in_image.png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
trizer 613172
trizer 613172
    if (!in_image.png_ptr)
trizer 613172
	{
trizer 613172
		synfig::error("[read_png_file] png_create_read_struct failed");
trizer 613172
		return false;
trizer 613172
	}
trizer 613172
trizer 613172
    in_image.info_ptr = png_create_info_struct(in_image.png_ptr);
trizer 613172
    if (!in_image.info_ptr)
trizer 613172
	{
trizer 613172
		synfig::error("[read_png_file] png_create_info_struct failed");
trizer 613172
		return false;
trizer 613172
	}
trizer 613172
trizer 613172
    if (setjmp(png_jmpbuf(in_image.png_ptr)))
trizer 613172
	{
trizer 613172
		synfig::error("[read_png_file] Error during init_io");
trizer 613172
		return false;
trizer 613172
	}
trizer 613172
trizer 613172
    png_init_io(in_image.png_ptr, in_file_pointer);
trizer 613172
    png_set_sig_bytes(in_image.png_ptr, 8);
trizer 613172
trizer 613172
    png_read_info(in_image.png_ptr, in_image.info_ptr);
trizer 613172
trizer 613172
    in_image.width = png_get_image_width(in_image.png_ptr, in_image.info_ptr);
trizer 613172
    in_image.height = png_get_image_height(in_image.png_ptr, in_image.info_ptr);
trizer 613172
	cout << "Img size: " << in_image.width << "x" << in_image.height << endl;
trizer 613172
    in_image.color_type = png_get_color_type(in_image.png_ptr, in_image.info_ptr);
trizer 613172
    in_image.bit_depth = png_get_bit_depth(in_image.png_ptr, in_image.info_ptr);
trizer 613172
trizer 613172
    png_read_update_info(in_image.png_ptr, in_image.info_ptr);
trizer 613172
trizer 613172
trizer 613172
    /* read file */
trizer 613172
    if (setjmp(png_jmpbuf(in_image.png_ptr)))
trizer 613172
	{
trizer 613172
        synfig::error("[read_png_file] Error during read_image");
trizer 613172
		return false;
trizer 613172
	}
trizer 613172
trizer 613172
	return true;
trizer 613172
}
trizer 613172
trizer 613172
bool 
trizer 613172
png_trgt_spritesheet::read_png_file()
trizer 613172
{
trizer 613172
	cout << "read_png_file()" << endl;
trizer 613172
	//Byte buffer for png data
trizer 613172
	png_bytep * row_pointers;
trizer 613172
    row_pointers = new png_bytep[in_image.height];
trizer 613172
    for (unsigned int y = 0; y < in_image.height; y++)
trizer 613172
            row_pointers[y] = new png_byte[png_get_rowbytes(in_image.png_ptr,in_image.info_ptr)];
trizer 613172
	cout << "row_pointers created" << endl;
trizer 613172
	
trizer 613172
	png_read_image(in_image.png_ptr, row_pointers);
trizer 613172
	cout << "image read" << endl;
trizer 613172
	
trizer 613172
    if (png_get_color_type(in_image.png_ptr, in_image.info_ptr) == PNG_COLOR_TYPE_RGB)
trizer 613172
	{
trizer 613172
        synfig::error("[process_file] input file is PNG_COLOR_TYPE_RGB but must be PNG_COLOR_TYPE_RGBA "
trizer 613172
               "(lacks the alpha channel)");
trizer 613172
		return false;
trizer 613172
	}
trizer 613172
trizer 613172
    if (png_get_color_type(in_image.png_ptr, in_image.info_ptr) != PNG_COLOR_TYPE_RGBA)
trizer 613172
	{
80b15f
        synfig::error("[process_file] color_type of input file must be PNG_COLOR_TYPE_RGBA (%d) (is %d)",
80b15f
			PNG_COLOR_TYPE_RGBA, png_get_color_type(in_image.png_ptr, in_image.info_ptr));
trizer 613172
		return false;
trizer 613172
	}
trizer 613172
trizer 613172
	cout << "colors checked" << endl;
trizer 613172
luz.paz 99f3ef
	//From png bytes to synfig::Color conversion
a4bbdd
	const ColorReal k = 1/255.0;
trizer 613172
    for (unsigned int y = 0; y < in_image.height; y++) 
trizer 613172
	{
trizer 613172
        png_byte* row = row_pointers[y];
trizer 613172
        for (unsigned int x = 0; x < in_image.width; x++) 
trizer 613172
		{
trizer 613172
            png_byte* ptr = &(row[x*4]);
a4bbdd
			color_data[y][x].set_r(ptr[0]*k);
a4bbdd
			color_data[y][x].set_g(ptr[1]*k);
a4bbdd
			color_data[y][x].set_b(ptr[2]*k);
a4bbdd
			color_data[y][x].set_a(ptr[3]*k);
trizer 613172
        }
trizer 613172
    }
Moritz Grosch (LittleFox) 5352f3
trizer 613172
	cout << "colors converted" << endl;
trizer 613172
	
trizer 613172
    for (unsigned int y = 0; y < in_image.height; y++)
trizer 613172
            delete []row_pointers[y];
80b15f
    
80b15f
	delete[] row_pointers;
trizer 613172
	cout << "row_pointers deleted" << endl;
trizer 613172
	return true;
Moritz Grosch (LittleFox) 5352f3
}
Moritz Grosch (LittleFox) 5352f3
trizer 613172
bool 
trizer 613172
png_trgt_spritesheet::write_png_file()
Moritz Grosch (LittleFox) 5352f3
{
trizer 613172
	cout << "write_png_file()" << endl;
trizer 613172
	png_structp png_ptr;
trizer 613172
	png_infop info_ptr;
trizer 613172
	unsigned char buffer [4 * sheet_width];
trizer 4e2b93
trizer 613172
	
trizer 613172
    if (filename == "-")
e8b33d
    	out_file_pointer=stdout;
trizer 613172
    else
e8b33d
    	out_file_pointer=fopen(filename.c_str(), POPEN_BINARY_WRITE_TYPE);
trizer 613172
trizer 4e2b93
	
trizer 613172
    png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)this,png_out_error, png_out_warning);
trizer 613172
    if (!png_ptr)
trizer 613172
    {
trizer 613172
        synfig::error("Unable to setup PNG struct");
e8b33d
        fclose(out_file_pointer);
e8b33d
        out_file_pointer=NULL;
Moritz Grosch (LittleFox) 5352f3
        return false;
trizer 613172
    }
Moritz Grosch (LittleFox) 5352f3
trizer 4e2b93
	
trizer 613172
    info_ptr= png_create_info_struct(png_ptr);
trizer 613172
    if (!info_ptr)
trizer 613172
    {
trizer 613172
        synfig::error("Unable to setup PNG info struct");
e8b33d
        fclose(out_file_pointer);
e8b33d
        out_file_pointer=NULL;
trizer 613172
        png_destroy_write_struct(&png_ptr,(png_infopp)NULL);
trizer 613172
        return false;
trizer 613172
    }
trizer 613172
trizer 4e2b93
	
trizer 613172
    if (setjmp(png_jmpbuf(png_ptr)))
trizer 613172
    {
trizer 613172
        synfig::error("Unable to setup longjump");
trizer 613172
        png_destroy_write_struct(&png_ptr, &info_ptr);
e8b33d
        fclose(out_file_pointer);
e8b33d
        out_file_pointer=NULL;
trizer 613172
        return false;
trizer 613172
    }
e8b33d
    png_init_io(png_ptr,out_file_pointer);
trizer 613172
    png_set_filter(png_ptr,0,PNG_FILTER_NONE);
Moritz Grosch (LittleFox) 5352f3
trizer 4e2b93
	
Moritz Grosch (LittleFox) 5352f3
    setjmp(png_jmpbuf(png_ptr));
Moritz Grosch (LittleFox) 5352f3
trizer 613172
	png_set_IHDR(png_ptr,info_ptr,
trizer 613172
	             sheet_width,
trizer 613172
	             sheet_height,
trizer 613172
	             8,
trizer 613172
	             (get_alpha_mode()==TARGET_ALPHA_MODE_KEEP)?PNG_COLOR_TYPE_RGBA:PNG_COLOR_TYPE_RGB,
trizer 613172
	             PNG_INTERLACE_NONE,
trizer 613172
	             PNG_COMPRESSION_TYPE_DEFAULT,
trizer 613172
	             PNG_FILTER_TYPE_DEFAULT);
trizer 613172
trizer 613172
    // Write the physical size
trizer 613172
    png_set_pHYs(png_ptr,info_ptr,round_to_int(desc.get_x_res()),round_to_int(desc.get_y_res()),PNG_RESOLUTION_METER);
trizer 613172
trizer 613172
    char title      [] = "Title";
trizer 613172
    char description[] = "Description";
trizer 613172
    char software   [] = "Software";
trizer 613172
    char synfig     [] = "SYNFIG";
93c6c7
93c6c7
	// Output any text info along with the file
93c6c7
	png_text comments[3];
93c6c7
	memset(comments, 0, sizeof(comments));
93c6c7
93c6c7
	comments[0].compression = PNG_TEXT_COMPRESSION_NONE;
93c6c7
	comments[0].key         = title;
93c6c7
	comments[0].text        = const_cast<char *="">(get_canvas()->get_name().c_str());</char>
93c6c7
	comments[0].text_length = strlen(comments[0].text);
93c6c7
93c6c7
	comments[1].compression = PNG_TEXT_COMPRESSION_NONE;
93c6c7
	comments[1].key         = description;
93c6c7
	comments[1].text        = const_cast<char *="">(get_canvas()->get_description().c_str());</char>
93c6c7
	comments[1].text_length = strlen(comments[1].text);
93c6c7
93c6c7
	comments[2].compression = PNG_TEXT_COMPRESSION_NONE;
93c6c7
	comments[2].key         = software;
93c6c7
	comments[2].text        = synfig;
93c6c7
	comments[2].text_length = strlen(comments[2].text);
93c6c7
93c6c7
	png_set_text(png_ptr, info_ptr, comments, sizeof(comments)/sizeof(png_text));
trizer 613172
trizer 613172
    png_write_info_before_PLTE(png_ptr, info_ptr);
trizer 613172
    png_write_info(png_ptr, info_ptr);
e8b33d
e8b33d
    //Writing spritesheet into png image
e8b33d
	for (cur_out_image_row = 0; cur_out_image_row < sheet_height; cur_out_image_row++)
trizer 613172
	{
d21b46
		color_to_pixelformat(
d21b46
			buffer,
d21b46
			color_data[cur_out_image_row],
d21b46
            //PF_RGB|(get_alpha_mode()==TARGET_ALPHA_MODE_KEEP)?PF_A:PF_RGB, //Note: PF_RGB == 0
d21b46
			(get_alpha_mode() == TARGET_ALPHA_MODE_KEEP) ? PF_RGB | PF_A : PF_RGB, //Note: PF_RGB == 0
a4bbdd
			0,
d21b46
			sheet_width );
trizer 613172
		setjmp(png_jmpbuf(png_ptr));
trizer 613172
		png_write_row(png_ptr,buffer);
trizer 613172
	}
e8b33d
	cur_out_image_row = 0;
e8b33d
    if(out_file_pointer)
trizer 613172
    {
trizer 613172
        png_write_end(png_ptr,info_ptr);
trizer 613172
        png_destroy_write_struct(&png_ptr, &info_ptr);
e8b33d
        fclose(out_file_pointer);
e8b33d
        out_file_pointer=NULL;
trizer 613172
trizer 613172
    }
trizer 613172
	return true;
Moritz Grosch (LittleFox) 5352f3
}