X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-core%2Fsrc%2Fmodules%2Fmod_bmp%2Ftrgt_bmp.cpp;fp=synfig-core%2Fsrc%2Fmodules%2Fmod_bmp%2Ftrgt_bmp.cpp;h=2985c5388f1d4b3c4b4f9b68142e407ce9fd6376;hb=a095981e18cc37a8ecc7cd237cc22b9c10329264;hp=0000000000000000000000000000000000000000;hpb=9459638ad6797b8139f1e9f0715c96076dbf0890;p=synfig.git diff --git a/synfig-core/src/modules/mod_bmp/trgt_bmp.cpp b/synfig-core/src/modules/mod_bmp/trgt_bmp.cpp new file mode 100644 index 0000000..2985c53 --- /dev/null +++ b/synfig-core/src/modules/mod_bmp/trgt_bmp.cpp @@ -0,0 +1,265 @@ +/* === S Y N F I G ========================================================= */ +/*! \file trgt_bmp.cpp +** \brief Bitmap Target +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007 Chris Moore +** +** This package 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. +** +** This package 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. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#define SYNFIG_NO_ANGLE + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "trgt_bmp.h" +#include + +#include +#include +#include +#endif + +/* === U S I N G =========================================================== */ + +using namespace synfig; +using namespace std; +using namespace etl; + +/* === I N F O ============================================================= */ + +SYNFIG_TARGET_INIT(bmp); +SYNFIG_TARGET_SET_NAME(bmp,"bmp"); +SYNFIG_TARGET_SET_EXT(bmp,"bmp"); +SYNFIG_TARGET_SET_VERSION(bmp,"0.1"); +SYNFIG_TARGET_SET_CVS_ID(bmp,"$Id$"); + +/* === C L A S S E S & S T R U C T S ======================================= */ +namespace synfig { + +struct BITMAPFILEHEADER +{ + unsigned char bfType[2]; + unsigned long bfSize; + unsigned short bfReserved1; + unsigned short bfReserved2; + unsigned long bfOffsetBits; +}; + +struct BITMAPINFOHEADER +{ + unsigned long biSize; + long biWidth; + long biHeight; + unsigned short biPlanes; + unsigned short biBitCount; + unsigned long biCompression; + unsigned long biSizeImage; + long biXPelsPerMeter; + long biYPelsPerMeter; + unsigned long biClrUsed; + unsigned long biClrImportant; +}; + +} +/* === M E T H O D S ======================================================= */ + +#ifdef WORDS_BIGENDIAN +inline long little_endian(const long &x) +{ + long ret; + char *big_e=(char *)&ret; + char *lit_e=(char *)&x; + big_e[0]=lit_e[3]; + big_e[1]=lit_e[2]; + big_e[2]=lit_e[1]; + big_e[3]=lit_e[0]; + return ret; +} +inline short little_endian_short(const short &x) +{ + short ret; + char *big_e=(char *)&ret; + char *lit_e=(char *)&x; + big_e[0]=lit_e[1]; + big_e[1]=lit_e[0]; + return ret; +} +#else +#define little_endian(x) (x) +#define little_endian_short(x) (x) +#endif + +bmp::bmp(const char *Filename) +{ + file=NULL; + filename=Filename; + multi_image=false; + buffer=0; + color_buffer=0; + set_remove_alpha(); + +} + +bmp::~bmp() +{ + if(file) + fclose(file); + file=NULL; + delete [] buffer; + delete [] color_buffer; +} + +bool +bmp::set_rend_desc(RendDesc *given_desc) +{ + pf=PF_BGR; + + // Flip the image upside down, + // because bitmaps are upside down. + given_desc->set_flags(0); + Point tl=given_desc->get_tl(); + Point br=given_desc->get_br(); + Point::value_type tmp; + tmp=tl[1]; + tl[1]=br[1]; + br[1]=tmp; + given_desc->set_tl(tl); + given_desc->set_br(br); + + desc=*given_desc; + if(desc.get_frame_end()-desc.get_frame_start()>0) + { + multi_image=true; + imagecount=desc.get_frame_start(); + } + else + multi_image=false; + + return true; +} + +void +bmp::end_frame() +{ + if(file) + fclose(file); + delete [] color_buffer; + color_buffer=0; + file=NULL; + imagecount++; +} + +bool +bmp::start_frame(synfig::ProgressCallback *callback) +{ + int w=desc.get_w(),h=desc.get_h(); + + rowspan=4*((w*(channels(pf)*8)+31)/32); + if(multi_image) + { + String newfilename(filename_sans_extension(filename) + + etl::strprintf(".%04d",imagecount) + + filename_extension(filename)); + file=fopen(newfilename.c_str(),POPEN_BINARY_WRITE_TYPE); + if(callback)callback->task(newfilename+_(" (animated)")); + } + else + { + file=fopen(filename.c_str(),POPEN_BINARY_WRITE_TYPE); + if(callback)callback->task(filename); + } + + if(!file) + { + if(callback)callback->error(_("Unable to open file")); + else synfig::error(_("Unable to open file")); + return false; + } + + synfig::BITMAPFILEHEADER fileheader; + synfig::BITMAPINFOHEADER infoheader; + + fileheader.bfType[0]='B'; + fileheader.bfType[1]='M'; + fileheader.bfSize=little_endian(sizeof(synfig::BITMAPFILEHEADER)+sizeof(synfig::BITMAPINFOHEADER)+rowspan*h); + fileheader.bfReserved1=0; + fileheader.bfReserved2=0; + fileheader.bfOffsetBits=little_endian(sizeof(synfig::BITMAPFILEHEADER)+sizeof(synfig::BITMAPINFOHEADER)-2); + + infoheader.biSize=little_endian(40); + infoheader.biWidth=little_endian(w); + infoheader.biHeight=little_endian(h); + infoheader.biPlanes=little_endian_short((short)1); + infoheader.biBitCount=little_endian_short((short)(channels(pf)*8)); + infoheader.biCompression=little_endian(0); + infoheader.biSizeImage=little_endian(0); + infoheader.biXPelsPerMeter=little_endian((int)rend_desc().get_x_res()); + infoheader.biYPelsPerMeter=little_endian((int)rend_desc().get_y_res()); // pels per meter...? + infoheader.biClrUsed=little_endian(0); + infoheader.biClrImportant=little_endian(0); + + fprintf(file,"BM"); + + if(!fwrite(&fileheader.bfSize,sizeof(synfig::BITMAPFILEHEADER)-4,1,file)) + { + if(callback)callback->error(_("Unable to write file header to file")); + else synfig::error(_("Unable to write file header to file")); + return false; + } + + if(!fwrite(&infoheader,sizeof(synfig::BITMAPINFOHEADER),1,file)) + { + if(callback)callback->error(_("Unable to write info header")); + else synfig::error(_("Unable to write info header")); + return false; + } + + delete [] buffer; + buffer=new unsigned char[rowspan]; + + delete [] color_buffer; + color_buffer=new Color[desc.get_w()]; + + return true; +} + +Color * +bmp::start_scanline(int /*scanline*/) +{ + return color_buffer; +} + +bool +bmp::end_scanline() +{ + if(!file) + return false; + + convert_color_format(buffer, color_buffer, desc.get_w(), pf, gamma()); + + if(!fwrite(buffer,1,rowspan,file)) + return false; + + return true; +}