Blame synfig-core/src/modules/mod_bmp/trgt_bmp.cpp

Carlos Lopez a09598
/* === S Y N F I G ========================================================= */
Carlos Lopez a09598
/*!	\file trgt_bmp.cpp
Carlos Lopez a09598
**	\brief Bitmap Target
Carlos Lopez a09598
**
Carlos Lopez a09598
**	$Id$
Carlos Lopez a09598
**
Carlos Lopez a09598
**	\legal
Carlos Lopez a09598
**	Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
Carlos Lopez a09598
**	Copyright (c) 2007 Chris Moore
Carlos Lopez a09598
**
Carlos Lopez a09598
**	This package is free software; you can redistribute it and/or
Carlos Lopez a09598
**	modify it under the terms of the GNU General Public License as
Carlos Lopez a09598
**	published by the Free Software Foundation; either version 2 of
Carlos Lopez a09598
**	the License, or (at your option) any later version.
Carlos Lopez a09598
**
Carlos Lopez a09598
**	This package is distributed in the hope that it will be useful,
Carlos Lopez a09598
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
Carlos Lopez a09598
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Carlos Lopez a09598
**	General Public License for more details.
Carlos Lopez a09598
**	\endlegal
Carlos Lopez a09598
*/
Carlos Lopez a09598
/* ========================================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
/* === H E A D E R S ======================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
#ifdef USING_PCH
Carlos Lopez a09598
#	include "pch.h"
Carlos Lopez a09598
#else
Carlos Lopez a09598
#ifdef HAVE_CONFIG_H
Carlos Lopez a09598
#	include <config.h></config.h>
Carlos Lopez a09598
#endif
Carlos Lopez a09598
Carlos Lopez a09598
#include "trgt_bmp.h"
Carlos Lopez a09598
#include <synfig general.h=""></synfig>
bw 94d8a6
#include <synfig localization.h=""></synfig>
Carlos Lopez a09598
Carlos Lopez a09598
#include <cstdio></cstdio>
Carlos Lopez a09598
#include <algorithm></algorithm>
Carlos Lopez a09598
#include <functional></functional>
Carlos Lopez a09598
#endif
Carlos Lopez a09598
Carlos Lopez a09598
/* === U S I N G =========================================================== */
Carlos Lopez a09598
Carlos Lopez a09598
using namespace synfig;
Carlos Lopez a09598
using namespace std;
Carlos Lopez a09598
using namespace etl;
Carlos Lopez a09598
Carlos Lopez a09598
/* === I N F O ============================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
SYNFIG_TARGET_INIT(bmp);
Carlos Lopez a09598
SYNFIG_TARGET_SET_NAME(bmp,"bmp");
Carlos Lopez a09598
SYNFIG_TARGET_SET_EXT(bmp,"bmp");
Carlos Lopez a09598
SYNFIG_TARGET_SET_VERSION(bmp,"0.1");
Carlos Lopez a09598
SYNFIG_TARGET_SET_CVS_ID(bmp,"$Id$");
Carlos Lopez a09598
Carlos Lopez a09598
/* === C L A S S E S & S T R U C T S ======================================= */
Carlos Lopez a09598
namespace synfig {
Carlos Lopez a09598
26ae22
/*struct BITMAPFILEHEADER
Carlos Lopez a09598
{
Carlos Lopez a09598
	unsigned char	bfType[2];
Carlos Lopez a09598
	unsigned long	bfSize;
Carlos Lopez a09598
	unsigned short	bfReserved1;
Carlos Lopez a09598
	unsigned short	bfReserved2;
Carlos Lopez a09598
	unsigned long	bfOffsetBits;
Carlos Lopez a09598
};
Carlos Lopez a09598
Carlos Lopez a09598
struct BITMAPINFOHEADER
Carlos Lopez a09598
{
Carlos Lopez a09598
	unsigned long	biSize;
Carlos Lopez a09598
	long			biWidth;
Carlos Lopez a09598
	long			biHeight;
Carlos Lopez a09598
	unsigned short	biPlanes;
Carlos Lopez a09598
	unsigned short	biBitCount;
Carlos Lopez a09598
	unsigned long	biCompression;
Carlos Lopez a09598
	unsigned long	biSizeImage;
Carlos Lopez a09598
	long			biXPelsPerMeter;
Carlos Lopez a09598
	long			biYPelsPerMeter;
Carlos Lopez a09598
	unsigned long	biClrUsed;
Carlos Lopez a09598
	unsigned long	biClrImportant;
26ae22
};*/
26ae22
26ae22
#pragma pack(push,1)
26ae22
namespace BITMAP
26ae22
{
26ae22
	typedef unsigned char uint8_t;
26ae22
	typedef unsigned short int uint16_t;
26ae22
	typedef int int32_t;
26ae22
	typedef unsigned int uint32_t;
26ae22
26ae22
	struct FILEHEADER
26ae22
	{
26ae22
		uint8_t		bfType[2];
26ae22
		uint32_t	bfSize;
26ae22
		uint16_t	bfReserved1;
26ae22
		uint16_t	bfReserved2;
26ae22
		uint32_t	bfOffsetBits;
26ae22
	};
26ae22
26ae22
	struct INFOHEADER
26ae22
	{
26ae22
		uint32_t	biSize;
26ae22
		int32_t		biWidth;
26ae22
		int32_t		biHeight;
26ae22
		uint16_t	biPlanes;
26ae22
		uint16_t	biBitCount;
26ae22
		uint32_t	biCompression;
26ae22
		uint32_t	biSizeImage;
26ae22
		int32_t		biXPelsPerMeter;
26ae22
		int32_t		biYPelsPerMeter;
26ae22
		uint32_t	biClrUsed;
26ae22
		uint32_t	biClrImportant;
26ae22
	};
26ae22
}
26ae22
#pragma pack(pop)
26ae22
Carlos Lopez a09598
Carlos Lopez a09598
}
Carlos Lopez a09598
/* === M E T H O D S ======================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
#ifdef WORDS_BIGENDIAN
Carlos Lopez a09598
inline long little_endian(const long &x)
Carlos Lopez a09598
{
Carlos Lopez a09598
	long ret;
Carlos Lopez a09598
	char *big_e=(char *)&ret;
Carlos Lopez a09598
	char *lit_e=(char *)&x;
Carlos Lopez a09598
	big_e[0]=lit_e[3];
Carlos Lopez a09598
	big_e[1]=lit_e[2];
Carlos Lopez a09598
	big_e[2]=lit_e[1];
Carlos Lopez a09598
	big_e[3]=lit_e[0];
Carlos Lopez a09598
	return ret;
Carlos Lopez a09598
}
Carlos Lopez a09598
inline short little_endian_short(const short &x)
Carlos Lopez a09598
{
Carlos Lopez a09598
	short ret;
Carlos Lopez a09598
	char *big_e=(char *)&ret;
Carlos Lopez a09598
	char *lit_e=(char *)&x;
Carlos Lopez a09598
	big_e[0]=lit_e[1];
Carlos Lopez a09598
	big_e[1]=lit_e[0];
Carlos Lopez a09598
	return ret;
Carlos Lopez a09598
}
Carlos Lopez a09598
#else
Carlos Lopez a09598
#define little_endian(x)	(x)
Carlos Lopez a09598
#define little_endian_short(x)	(x)
Carlos Lopez a09598
#endif
Carlos Lopez a09598
6320b8
bmp::bmp(const char *Filename, const synfig::TargetParam& params):
6320b8
	rowspan(),
6320b8
	imagecount(),
6320b8
	multi_image(false),
6320b8
	file(NULL),
6320b8
	filename(Filename),
6320b8
	buffer(NULL),
6320b8
	color_buffer(NULL),
6320b8
	pf()
Carlos Lopez a09598
{
dc451c
	set_alpha_mode(TARGET_ALPHA_MODE_FILL);
Carlos Lopez baadb1
	sequence_separator=params.sequence_separator;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
bmp::~bmp()
Carlos Lopez a09598
{
Carlos Lopez a09598
	if(file)
Carlos Lopez a09598
		fclose(file);
Carlos Lopez a09598
	file=NULL;
Carlos Lopez a09598
	delete [] buffer;
Carlos Lopez a09598
	delete [] color_buffer;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
bool
Carlos Lopez a09598
bmp::set_rend_desc(RendDesc *given_desc)
Carlos Lopez a09598
{
Carlos Lopez a09598
	pf=PF_BGR;
Carlos Lopez a09598
Carlos Lopez a09598
    // Flip the image upside down,
Carlos Lopez a09598
	// because bitmaps are upside down.
Carlos Lopez a09598
    given_desc->set_flags(0);
Carlos Lopez a09598
	Point tl=given_desc->get_tl();
Carlos Lopez a09598
	Point br=given_desc->get_br();
Carlos Lopez a09598
	Point::value_type tmp;
Carlos Lopez a09598
	tmp=tl[1];
Carlos Lopez a09598
	tl[1]=br[1];
Carlos Lopez a09598
	br[1]=tmp;
Carlos Lopez a09598
	given_desc->set_tl(tl);
Carlos Lopez a09598
	given_desc->set_br(br);
Carlos Lopez a09598
Carlos Lopez a09598
	desc=*given_desc;
Carlos Lopez a09598
	if(desc.get_frame_end()-desc.get_frame_start()>0)
Carlos Lopez a09598
	{
Carlos Lopez a09598
		multi_image=true;
Carlos Lopez a09598
		imagecount=desc.get_frame_start();
Carlos Lopez a09598
	}
Carlos Lopez a09598
	else
Carlos Lopez a09598
		multi_image=false;
Carlos Lopez a09598
Carlos Lopez a09598
    return true;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
void
Carlos Lopez a09598
bmp::end_frame()
Carlos Lopez a09598
{
Carlos Lopez a09598
	if(file)
Carlos Lopez a09598
		fclose(file);
Carlos Lopez a09598
	delete [] color_buffer;
Carlos Lopez a09598
	color_buffer=0;
Carlos Lopez a09598
	file=NULL;
Carlos Lopez a09598
	imagecount++;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
bool
Carlos Lopez a09598
bmp::start_frame(synfig::ProgressCallback *callback)
Carlos Lopez a09598
{
Carlos Lopez a09598
	int w=desc.get_w(),h=desc.get_h();
Carlos Lopez a09598
d21b46
	rowspan=4*((w*(pixel_size(pf)*8)+31)/32);
Carlos Lopez a09598
	if(multi_image)
Carlos Lopez a09598
	{
Carlos Lopez a09598
		String newfilename(filename_sans_extension(filename) +
Carlos Lopez baadb1
						   sequence_separator +
Carlos Lopez baadb1
						   etl::strprintf("%04d",imagecount) +
Carlos Lopez a09598
						   filename_extension(filename));
Carlos Lopez a09598
		file=fopen(newfilename.c_str(),POPEN_BINARY_WRITE_TYPE);
Carlos Lopez a09598
		if(callback)callback->task(newfilename+_(" (animated)"));
Carlos Lopez a09598
	}
Carlos Lopez a09598
	else
Carlos Lopez a09598
	{
Carlos Lopez a09598
		file=fopen(filename.c_str(),POPEN_BINARY_WRITE_TYPE);
Carlos Lopez a09598
		if(callback)callback->task(filename);
Carlos Lopez a09598
	}
Carlos Lopez a09598
Carlos Lopez a09598
	if(!file)
Carlos Lopez a09598
	{
Carlos Lopez a09598
		if(callback)callback->error(_("Unable to open file"));
Carlos Lopez a09598
		else synfig::error(_("Unable to open file"));
Carlos Lopez a09598
		return false;
Carlos Lopez a09598
	}
Carlos Lopez a09598
26ae22
	synfig::BITMAP::FILEHEADER fileheader;
26ae22
	synfig::BITMAP::INFOHEADER infoheader;
Carlos Lopez a09598
Carlos Lopez a09598
	fileheader.bfType[0]='B';
Carlos Lopez a09598
	fileheader.bfType[1]='M';
26ae22
	fileheader.bfSize=little_endian(sizeof(synfig::BITMAP::FILEHEADER)+sizeof(synfig::BITMAP::INFOHEADER)+rowspan*h);
Carlos Lopez a09598
	fileheader.bfReserved1=0;
Carlos Lopez a09598
	fileheader.bfReserved2=0;
26ae22
	fileheader.bfOffsetBits=little_endian(sizeof(synfig::BITMAP::FILEHEADER)+sizeof(synfig::BITMAP::INFOHEADER));
Carlos Lopez a09598
26ae22
	infoheader.biSize=little_endian(sizeof(synfig::BITMAP::INFOHEADER));
Carlos Lopez a09598
	infoheader.biWidth=little_endian(w);
Carlos Lopez a09598
	infoheader.biHeight=little_endian(h);
Carlos Lopez a09598
	infoheader.biPlanes=little_endian_short((short)1);
d21b46
	infoheader.biBitCount=little_endian_short((short)(pixel_size(pf)*8));
Carlos Lopez a09598
	infoheader.biCompression=little_endian(0);
Carlos Lopez a09598
	infoheader.biSizeImage=little_endian(0);
Carlos Lopez a09598
	infoheader.biXPelsPerMeter=little_endian((int)rend_desc().get_x_res());
Carlos Lopez a09598
	infoheader.biYPelsPerMeter=little_endian((int)rend_desc().get_y_res()); // pels per meter...?
Carlos Lopez a09598
	infoheader.biClrUsed=little_endian(0);
Carlos Lopez a09598
	infoheader.biClrImportant=little_endian(0);
Carlos Lopez a09598
26ae22
	//fprintf(file,"BM");
Carlos Lopez a09598
26ae22
	//if (!fwrite(&fileheader.bfSize,sizeof(synfig::BITMAPFILEHEADER)-4,1,file))
26ae22
	if (!fwrite(&fileheader, sizeof(synfig::BITMAP::FILEHEADER), 1, file))
Carlos Lopez a09598
	{
Carlos Lopez a09598
		if(callback)callback->error(_("Unable to write file header to file"));
Carlos Lopez a09598
		else synfig::error(_("Unable to write file header to file"));
Carlos Lopez a09598
		return false;
Carlos Lopez a09598
	}
Carlos Lopez a09598
26ae22
	if (!fwrite(&infoheader, sizeof(synfig::BITMAP::INFOHEADER), 1, file))
Carlos Lopez a09598
	{
Carlos Lopez a09598
		if(callback)callback->error(_("Unable to write info header"));
Carlos Lopez a09598
		else synfig::error(_("Unable to write info header"));
Carlos Lopez a09598
		return false;
Carlos Lopez a09598
	}
Carlos Lopez a09598
Carlos Lopez a09598
	delete [] buffer;
Carlos Lopez a09598
	buffer=new unsigned char[rowspan];
Carlos Lopez a09598
Carlos Lopez a09598
	delete [] color_buffer;
Carlos Lopez a09598
	color_buffer=new Color[desc.get_w()];
Carlos Lopez a09598
Carlos Lopez a09598
	return true;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
Color *
Carlos Lopez a09598
bmp::start_scanline(int /*scanline*/)
Carlos Lopez a09598
{
Carlos Lopez a09598
	return color_buffer;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
bool
Carlos Lopez a09598
bmp::end_scanline()
Carlos Lopez a09598
{
Carlos Lopez a09598
	if(!file)
Carlos Lopez a09598
		return false;
Carlos Lopez a09598
a4bbdd
	color_to_pixelformat(buffer, color_buffer, pf, 0, desc.get_w());
Carlos Lopez a09598
Carlos Lopez a09598
	if(!fwrite(buffer,1,rowspan,file))
Carlos Lopez a09598
		return false;
Carlos Lopez a09598
Carlos Lopez a09598
	return true;
Carlos Lopez a09598
}