|
Carlos Lopez |
a09598 |
/* === S Y N F I G ========================================================= */
|
|
Carlos Lopez |
a09598 |
/*! \file trgt_gif.cpp
|
|
Carlos Lopez |
a09598 |
** \brief BMP Target Module
|
|
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 |
** === N O T E S ===========================================================
|
|
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 |
|
|
bw |
94d8a6 |
#include <synfig localization.h=""></synfig>
|
|
bw |
94d8a6 |
#include <synfig general.h=""></synfig>
|
|
|
a4bbdd |
#include <synfig color.h=""></synfig>
|
|
bw |
94d8a6 |
|
|
Carlos Lopez |
a09598 |
#include <etl stringf=""></etl>
|
|
Carlos Lopez |
a09598 |
#include "trgt_gif.h"
|
|
|
c13708 |
#include <cstdio></cstdio>
|
|
Carlos Lopez |
a09598 |
#endif
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === M A C R O S ========================================================= */
|
|
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 |
#define MAX_FRAME_RATE (20.0)
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === G L O B A L S ======================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
SYNFIG_TARGET_INIT(gif);
|
|
Carlos Lopez |
a09598 |
SYNFIG_TARGET_SET_NAME(gif,"gif");
|
|
Carlos Lopez |
a09598 |
SYNFIG_TARGET_SET_EXT(gif,"gif");
|
|
Carlos Lopez |
a09598 |
SYNFIG_TARGET_SET_VERSION(gif,"0.1");
|
|
Carlos Lopez |
a09598 |
SYNFIG_TARGET_SET_CVS_ID(gif,"$Id$");
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === M E T H O D S ======================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
|
6320b8 |
gif::gif(const char *filename_, const synfig::TargetParam & /* params */):
|
|
|
6320b8 |
bs(),
|
|
Carlos Lopez |
a09598 |
filename(filename_),
|
|
Carlos Lopez |
a09598 |
file( (filename=="-")?stdout:fopen(filename_,POPEN_BINARY_WRITE_TYPE) ),
|
|
|
6320b8 |
codesize(),
|
|
|
6320b8 |
rootsize(),
|
|
|
6320b8 |
nextcode(),
|
|
|
6320b8 |
table(NULL),
|
|
|
6320b8 |
next(NULL),
|
|
|
6320b8 |
node(NULL),
|
|
Carlos Lopez |
a09598 |
imagecount(0),
|
|
|
6320b8 |
cur_scanline(),
|
|
Carlos Lopez |
a09598 |
lossy(true),
|
|
Carlos Lopez |
a09598 |
multi_image(false),
|
|
Carlos Lopez |
a09598 |
dithering(true),
|
|
Carlos Lopez |
a09598 |
color_bits(8),
|
|
Carlos Lopez |
a09598 |
iframe_density(30),
|
|
Carlos Lopez |
a09598 |
loop_count(0x7fff),
|
|
Carlos Lopez |
a09598 |
local_palette(true)
|
|
|
6320b8 |
{ }
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
gif::~gif()
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
if(file)
|
|
Carlos Lopez |
a09598 |
fputc(';',file.get()); // Image terminator
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
bool
|
|
Carlos Lopez |
a09598 |
gif::set_rend_desc(RendDesc *given_desc)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
if(given_desc->get_frame_rate()>MAX_FRAME_RATE)
|
|
Carlos Lopez |
a09598 |
given_desc->set_frame_rate(MAX_FRAME_RATE);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
desc=*given_desc;
|
|
Carlos Lopez |
a09598 |
|
|
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 |
//set_remove_alpha();
|
|
Carlos Lopez |
a09598 |
imagecount=desc.get_frame_end()-desc.get_frame_start();
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
multi_image=false;
|
|
Carlos Lopez |
a09598 |
return true;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
bool
|
|
|
aae0f9 |
gif::init(synfig::ProgressCallback * /* cb */)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
int w=desc.get_w(),h=desc.get_h();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(!file)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
synfig::error(strprintf(_("Unable to open \"%s\" for write access!"),filename.c_str()));
|
|
Carlos Lopez |
a09598 |
return false;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
rootsize=color_bits; // Size of pixel bits
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
curr_frame.set_wh(w,h);
|
|
Carlos Lopez |
a09598 |
prev_frame.set_wh(w,h);
|
|
Carlos Lopez |
a09598 |
curr_surface.set_wh(w,h);
|
|
Carlos Lopez |
a09598 |
curr_frame.clear();
|
|
Carlos Lopez |
a09598 |
prev_frame.clear();
|
|
Carlos Lopez |
a09598 |
curr_surface.clear();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(get_quality()>5)
|
|
Carlos Lopez |
a09598 |
lossy=true;
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
lossy=false;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Output the header
|
|
Carlos Lopez |
a09598 |
fprintf(file.get(),"GIF89a");
|
|
Carlos Lopez |
a09598 |
fputc(w&0x000000ff,file.get());
|
|
Carlos Lopez |
a09598 |
fputc((w&0x0000ff00)>>8,file.get());
|
|
Carlos Lopez |
a09598 |
fputc(h&0x000000ff,file.get());
|
|
Carlos Lopez |
a09598 |
fputc((h&0x0000ff00)>>8,file.get());
|
|
Carlos Lopez |
a09598 |
if(!local_palette)
|
|
Carlos Lopez |
a09598 |
fputc(0xF0+(rootsize-1),file.get()); // flags
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
fputc((0xF0+(rootsize-1))&~(1<<7),file.get()); // flags
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
fputc(0,file.get()); // background color
|
|
Carlos Lopez |
a09598 |
fputc(0,file.get()); // Pixel Aspect Ratio
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(!local_palette)
|
|
Carlos Lopez |
a09598 |
{
|
|
|
a4bbdd |
curr_palette = Palette::grayscale(256/(1<<(8-rootsize))-1, 1);
|
|
Carlos Lopez |
a09598 |
output_curr_palette();
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(loop_count && multi_image)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
fputc(33,file.get()); // 33 (hex 0x21) GIF Extension code
|
|
Carlos Lopez |
a09598 |
fputc(255,file.get()); // 255 (hex 0xFF) Application Extension Label
|
|
Carlos Lopez |
a09598 |
fputc(11,file.get()); // 11 (hex (0x0B) Length of Application Block
|
|
Carlos Lopez |
a09598 |
fprintf(file.get(),"NETSCAPE2.0");
|
|
Carlos Lopez |
a09598 |
fputc(3,file.get()); // 3 (hex 0x03) Length of Data Sub-Block
|
|
Carlos Lopez |
a09598 |
fputc(1,file.get()); // 1 (hex 0x01)
|
|
Carlos Lopez |
a09598 |
fputc(loop_count&0x000000ff,file.get());
|
|
Carlos Lopez |
a09598 |
fputc((loop_count&0x0000ff00)>>8,file.get());
|
|
Carlos Lopez |
a09598 |
fputc(0,file.get()); // 0 (hex 0x00) a Data Sub-block Terminator.
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
return true;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
void
|
|
Carlos Lopez |
a09598 |
gif::output_curr_palette()
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
// Output the color table
|
|
|
a4bbdd |
for(int i = 0; i < 256/(1<<(8-rootsize)); ++i) {
|
|
|
a4bbdd |
if (i < (int)curr_palette.size()) {
|
|
|
a4bbdd |
Color color = curr_palette[i].color.clamped();
|
|
|
a4bbdd |
fputc((unsigned char)(color.get_r()*255.99), file.get());
|
|
|
a4bbdd |
fputc((unsigned char)(color.get_g()*255.99), file.get());
|
|
|
a4bbdd |
fputc((unsigned char)(color.get_b()*255.99), file.get());
|
|
|
a4bbdd |
} else {
|
|
Carlos Lopez |
a09598 |
fputc(255,file.get());
|
|
Carlos Lopez |
a09598 |
fputc(0,file.get());
|
|
Carlos Lopez |
a09598 |
fputc(255,file.get());
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
bool
|
|
Carlos Lopez |
a09598 |
gif::start_frame(synfig::ProgressCallback *callback)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
// int
|
|
Carlos Lopez |
a09598 |
// w=desc.get_w(),
|
|
Carlos Lopez |
a09598 |
// h=desc.get_h();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(!file)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
if(callback)callback->error(string("BUG:")+_("Description not set!"));
|
|
Carlos Lopez |
a09598 |
return false;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(callback)callback->task(filename+strprintf(" %d",imagecount));
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
return true;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
void
|
|
Carlos Lopez |
a09598 |
gif::end_frame()
|
|
Carlos Lopez |
a09598 |
{
|
|
|
a4bbdd |
int w = desc.get_w(), h = desc.get_h();
|
|
Carlos Lopez |
a09598 |
unsigned int value;
|
|
|
a4bbdd |
int delaytime = round_to_int(100.0/desc.get_frame_rate());
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
bool build_off_previous(multi_image);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
Palette prev_palette(curr_palette);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Fill in the background color
|
|
|
dc451c |
if(get_alpha_mode()==TARGET_ALPHA_MODE_KEEP)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
Surface::alpha_pen pen(curr_surface.begin(),1.0,Color::BLEND_BEHIND);
|
|
Carlos Lopez |
a09598 |
pen.set_value(get_canvas()->rend_desc().get_bg_color());
|
|
Carlos Lopez |
a09598 |
for(int y=0;y
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
int x;
|
|
Carlos Lopez |
a09598 |
for(x=0;x
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
if(pen.get_value().get_a()>0.1)
|
|
Carlos Lopez |
a09598 |
pen.put_value();
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
pen[0][0]=Color::alpha();
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
pen.dec_x(x);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(local_palette)
|
|
Carlos Lopez |
a09598 |
{
|
|
|
a4bbdd |
curr_palette = Palette(curr_surface, 256/(1<<(8-rootsize)) - build_off_previous - 1, Gamma());
|
|
Carlos Lopez |
a09598 |
synfig::info("curr_palette.size()=%d",curr_palette.size());
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
|
a4bbdd |
int transparent_index = curr_palette.find_closest(Color(1,0,1,0), Gamma()) - curr_palette.begin();
|
|
|
a4bbdd |
bool has_transparency = curr_palette[transparent_index].color.get_a()<=0.00001;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(has_transparency)
|
|
Carlos Lopez |
a09598 |
build_off_previous=false;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(build_off_previous)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
transparent_index=0;
|
|
Carlos Lopez |
a09598 |
has_transparency=true;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#define DISPOSE_UNDEFINED (0)
|
|
Carlos Lopez |
a09598 |
#define DISPOSE_NONE (1<<2)
|
|
Carlos Lopez |
a09598 |
#define DISPOSE_RESTORE_BGCOLOR (2<<2)
|
|
Carlos Lopez |
a09598 |
#define DISPOSE_RESTORE_PREVIOUS (3<<2)
|
|
Carlos Lopez |
a09598 |
int gec_flags(0);
|
|
Carlos Lopez |
a09598 |
if(build_off_previous)
|
|
Carlos Lopez |
a09598 |
gec_flags|=DISPOSE_NONE;
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
gec_flags|=DISPOSE_RESTORE_PREVIOUS;
|
|
Carlos Lopez |
a09598 |
if(has_transparency)
|
|
Carlos Lopez |
a09598 |
gec_flags|=1;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// output the Graphic Control Extension
|
|
Carlos Lopez |
a09598 |
fputc(0x21,file.get()); // Extension introducer
|
|
Carlos Lopez |
a09598 |
fputc(0xF9,file.get()); // Graphic Control Label
|
|
Carlos Lopez |
a09598 |
fputc(4,file.get()); // Block Size
|
|
Carlos Lopez |
a09598 |
fputc(gec_flags,file.get()); // Flags (Packed Fields)
|
|
Carlos Lopez |
a09598 |
fputc(delaytime&0x000000ff,file.get()); // Delay Time (MSB)
|
|
Carlos Lopez |
a09598 |
fputc((delaytime&0x0000ff00)>>8,file.get()); // Delay Time (LSB)
|
|
Carlos Lopez |
a09598 |
fputc(transparent_index,file.get()); // Transparent Color Index
|
|
Carlos Lopez |
a09598 |
fputc(0,file.get()); // Block Terminator
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// output the image header
|
|
Carlos Lopez |
a09598 |
fputc(',',file.get());
|
|
Carlos Lopez |
a09598 |
fputc(0,file.get()); // image left
|
|
Carlos Lopez |
a09598 |
fputc(0,file.get()); // image left
|
|
Carlos Lopez |
a09598 |
fputc(0,file.get()); // image top
|
|
Carlos Lopez |
a09598 |
fputc(0,file.get()); // image top
|
|
Carlos Lopez |
a09598 |
fputc(w&0x000000ff,file.get());
|
|
Carlos Lopez |
a09598 |
fputc((w&0x0000ff00)>>8,file.get());
|
|
Carlos Lopez |
a09598 |
fputc(h&0x000000ff,file.get());
|
|
Carlos Lopez |
a09598 |
fputc((h&0x0000ff00)>>8,file.get());
|
|
Carlos Lopez |
a09598 |
if(local_palette)
|
|
Carlos Lopez |
a09598 |
fputc(0x80|(rootsize-1),file.get()); // flags
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
fputc(0x00+ rootsize-1,file.get()); // flags
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(local_palette)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
Palette out(curr_palette);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(build_off_previous)
|
|
Carlos Lopez |
a09598 |
curr_palette.insert(curr_palette.begin(),Color(1,0,1,0));
|
|
Carlos Lopez |
a09598 |
output_curr_palette();
|
|
Carlos Lopez |
a09598 |
curr_palette=out;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
bs=bitstream(file);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Prepare ourselves for LZW compression
|
|
Carlos Lopez |
a09598 |
codesize=rootsize+1;
|
|
Carlos Lopez |
a09598 |
nextcode=(1<
|
|
Carlos Lopez |
a09598 |
table=lzwcode::NewTable((1<
|
|
Carlos Lopez |
a09598 |
node=table;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Output the rootsize
|
|
Carlos Lopez |
a09598 |
fputc(rootsize,file.get()); // rootsize;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Push a table reset into the bitstream
|
|
Carlos Lopez |
a09598 |
bs.push_value(1<
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
for(int cur_scanline=0;cur_scanline
|
|
Carlos Lopez |
a09598 |
{
|
|
|
d21b46 |
//color_to_pixelformat(curr_frame[cur_scanline], curr_surface[cur_scanline], PF_GRAY, &gamma(), desc.get_w());
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Now we compress it!
|
|
|
a4bbdd |
for(int i=0; i < w; ++i)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
Color color(curr_surface[cur_scanline][i].clamped());
|
|
|
a4bbdd |
Palette::iterator iter(curr_palette.find_closest(color, Gamma()));
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(dithering)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
Color error(color-iter->color);
|
|
Carlos Lopez |
a09598 |
//error*=0.25;
|
|
Carlos Lopez |
a09598 |
if(curr_surface.get_h()>cur_scanline+1)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
curr_surface[cur_scanline+1][i-1] += error * ((float)3/(float)16);
|
|
Carlos Lopez |
a09598 |
curr_surface[cur_scanline+1][i] += error * ((float)5/(float)16);
|
|
Carlos Lopez |
a09598 |
if(curr_surface.get_w()>i+1)
|
|
Carlos Lopez |
a09598 |
curr_surface[cur_scanline+1][i+1] += error * ((float)1/(float)16);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
if(curr_surface.get_w()>i+1)
|
|
Carlos Lopez |
a09598 |
curr_surface[cur_scanline][i+1] += error * ((float)7/(float)16);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
curr_frame[cur_scanline][i]=iter-curr_palette.begin();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
value=curr_frame[cur_scanline][i];
|
|
Carlos Lopez |
a09598 |
if(build_off_previous)
|
|
Carlos Lopez |
a09598 |
value++;
|
|
Carlos Lopez |
a09598 |
if(value>(unsigned)(1<
|
|
Carlos Lopez |
a09598 |
value=(1<
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// If the pixel is the same as the one that
|
|
Carlos Lopez |
a09598 |
// is already there, then we should make it
|
|
Carlos Lopez |
a09598 |
// transparent
|
|
Carlos Lopez |
a09598 |
if(build_off_previous)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
if(lossy)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Lossy
|
|
Carlos Lopez |
a09598 |
if(
|
|
Carlos Lopez |
a09598 |
abs( ( iter->color-prev_palette[prev_frame[cur_scanline][i]-1].color ).get_y() ) > (1.0/16.0) ||
|
|
Carlos Lopez |
a09598 |
// abs((int)value-(int)prev_frame[cur_scanline][i])>2||
|
|
Carlos Lopez |
a09598 |
// (value<=2 && value!=prev_frame[cur_scanline][i]) ||
|
|
Carlos Lopez |
a09598 |
(imagecount%iframe_density)==0 || imagecount==desc.get_frame_end()-1 ) // lossy version
|
|
Carlos Lopez |
a09598 |
prev_frame[cur_scanline][i]=value;
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
prev_frame[cur_scanline][i]=value;
|
|
Carlos Lopez |
a09598 |
value=0;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
// lossless version
|
|
Carlos Lopez |
a09598 |
if(value!=prev_frame[cur_scanline][i])
|
|
Carlos Lopez |
a09598 |
prev_frame[cur_scanline][i]=value;
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
value=0;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
prev_frame[cur_scanline][i]=value;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
next=node->FindCode(value);
|
|
Carlos Lopez |
a09598 |
if(next)
|
|
Carlos Lopez |
a09598 |
node=next;
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
node->AddNode(nextcode, value);
|
|
Carlos Lopez |
a09598 |
bs.push_value(node->code, codesize);
|
|
Carlos Lopez |
a09598 |
node = table->FindCode(value);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Check to see if we need to increase the codesize
|
|
Carlos Lopez |
a09598 |
if (nextcode == ( 1 << codesize))
|
|
Carlos Lopez |
a09598 |
codesize += 1;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
nextcode += 1;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// check to see if we have filled up the table
|
|
Carlos Lopez |
a09598 |
if (nextcode == 4096)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
// output the clear code: make sure to use the current
|
|
Carlos Lopez |
a09598 |
// codesize
|
|
Carlos Lopez |
a09598 |
bs.push_value((unsigned) 1 << rootsize, codesize);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
delete table;
|
|
Carlos Lopez |
a09598 |
table = lzwcode::NewTable((1<
|
|
Carlos Lopez |
a09598 |
codesize = rootsize + 1;
|
|
Carlos Lopez |
a09598 |
nextcode = (1 << rootsize) + 2;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// since we have a new table, need the correct prefix
|
|
Carlos Lopez |
a09598 |
node = table->FindCode(value);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Push the last code onto the bitstream
|
|
Carlos Lopez |
a09598 |
bs.push_value(node->code,codesize);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Push a end-of-stream code onto the bitstream
|
|
Carlos Lopez |
a09598 |
bs.push_value((1<
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Make sure everything is dumped out
|
|
Carlos Lopez |
a09598 |
bs.dump();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
delete table;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
fputc(0,file.get()); // Block terminator
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
fflush(file.get());
|
|
Carlos Lopez |
a09598 |
imagecount++;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
synfig::Color*
|
|
Carlos Lopez |
a09598 |
gif::start_scanline(int scanline)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
cur_scanline=scanline;
|
|
Carlos Lopez |
a09598 |
return curr_surface[scanline];
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
bool
|
|
Carlos Lopez |
a09598 |
gif::end_scanline()
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
if(!file)
|
|
Carlos Lopez |
a09598 |
return false;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// int w=desc.get_w(),i;
|
|
Carlos Lopez |
a09598 |
// unsigned int value;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
return true;
|
|
Carlos Lopez |
a09598 |
}
|