summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2019-03-26 18:22:10 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2019-03-26 18:22:10 (GMT)
commit721d605ee4974a66ffd11cfad4e2443075363582 (patch)
tree42f81a95dd48e843e79a10197e0282cb70eaa5d1
parent93bb51f96b175143d0ac17c5c0d25d3ba6459c7a (diff)
downloadblt-721d605ee4974a66ffd11cfad4e2443075363582.zip
blt-721d605ee4974a66ffd11cfad4e2443075363582.tar.gz
blt-721d605ee4974a66ffd11cfad4e2443075363582.tar.bz2
support animated gif
-rw-r--r--ds9/library/movie.tcl4
-rw-r--r--tkagif/tkagif.C456
-rw-r--r--tkagif/tkagif.h22
3 files changed, 299 insertions, 183 deletions
diff --git a/ds9/library/movie.tcl b/ds9/library/movie.tcl
index 88f23b6..9dc2922 100644
--- a/ds9/library/movie.tcl
+++ b/ds9/library/movie.tcl
@@ -339,10 +339,10 @@ proc MoviePhotoGIF {} {
if {$movie(first)} {
switch [$current(frame) get type] {
rgb {
- agif create $movie(fn) [image width $ph] [image height $ph] 16
+ agif create $movie(fn) [image width $ph] [image height $ph]
}
default {
- agif create $movie(fn) [image width $ph] [image height $ph] 4
+ agif create $movie(fn) [image width $ph] [image height $ph]
}
}
set movie(first) 0
diff --git a/tkagif/tkagif.C b/tkagif/tkagif.C
index dcd3e4c..977a8b8 100644
--- a/tkagif/tkagif.C
+++ b/tkagif/tkagif.C
@@ -21,19 +21,6 @@ extern "C" {
const char* argv[]);
}
-typedef struct {
- int count;
- unsigned char red;
- unsigned char green;
- unsigned char blue;
-} Color;
-
-typedef struct {
- unsigned char red;
- unsigned char green;
- unsigned char blue;
-} Pixel;
-
TkAGIF* tkagif=NULL;
int Tkagif_Init(Tcl_Interp* interp) {
@@ -84,15 +71,15 @@ TkAGIF::TkAGIF(Tcl_Interp* interp)
out_ =NULL;
width_ = 512;
height_ = 512;
- colorRes_ = 4; // pseudocolor
- //colorRes_ = 16; // rgb
+ resolution_ =0;
// state vars
- colorTableSize_ =0;
- resolution_ =0;
pict_ =NULL;
pictCount_ =0;
+ colorTable_ =NULL;
+ colorTableSize_ =0;
+
// Compress
initialBits_ =0;
numBits_ =0;
@@ -111,14 +98,14 @@ TkAGIF::TkAGIF(Tcl_Interp* interp)
int TkAGIF::create(int argc, const char* argv[])
{
- if (argc == 6) {
+ if (argc == 5) {
if (*argv[2] == '\0') {
Tcl_AppendResult(interp_, "bad filename", NULL);
return TCL_ERROR;
}
}
else {
- Tcl_AppendResult(interp_, "usage: tkagif create <filename> <width> <height> <color resolution> ", NULL);
+ Tcl_AppendResult(interp_, "usage: tkagif create <filename> <width> <height>", NULL);
return TCL_ERROR;
}
@@ -141,11 +128,6 @@ int TkAGIF::create(int argc, const char* argv[])
istringstream str(s);
str >> height_;
}
- {
- string s(argv[5]);
- istringstream str(s);
- str >> colorRes_;
- }
// *** Header ***
{
@@ -287,8 +269,6 @@ static int cmpColor(const void* a, const void* b)
return 1;
}
-#define ALMOST(aa,bb) (abs(aa-bb) <= colorRes_ ? 1 : 0)
-
int TkAGIF::add(int argc, const char* argv[])
{
if (argc == 3) {
@@ -302,47 +282,6 @@ int TkAGIF::add(int argc, const char* argv[])
return TCL_ERROR;
}
- // colortable
- int maxColors = 4096;
- int totalColors =11;
- Color cc[maxColors];
- memset(cc,0,sizeof(Color)*maxColors);
-
- // Base Colors
- // 0: black
- // 1: white
- cc[1].red = cc[1].green = cc[1].blue = 255;
- cc[1].count++;
- // 2: red
- cc[2].red = 255;
- cc[2].count++;
- // 3: green
- cc[3].green = 255;
- cc[3].count++;
- // 4: blue
- cc[4].blue = 255;
- cc[4].count++;
- // 5: cyan
- cc[5].green = cc[5].blue = 255;
- cc[5].count++;
- // 6: magenta
- cc[6].red = cc[6].blue = 255;
- cc[6].count++;
- // 7: yellow
- cc[7].red = cc[7].green = 255;
- cc[7].count++;
-
- // some Greys for numerics
- // 8: 1/4 grey
- cc[8].red = cc[8].green = cc[8].blue = 64;
- cc[8].count++;
- // 9: 1/2 grey
- cc[9].red = cc[9].green = cc[9].blue = 128;
- cc[9].count++;
- // 10: 3/4 grey
- cc[10].red = cc[10].green = cc[10].blue = 192;
- cc[10].count++;
-
// RGB img
Pixel* pixels = new Pixel[width_*height_];
memset(pixels,0,sizeof(Pixel)*width_*height_);
@@ -368,7 +307,253 @@ int TkAGIF::add(int argc, const char* argv[])
}
}
}
+
+ // Indexed img
+ if (pict_)
+ delete [] pict_;
+ pict_ =NULL;
+ pictCount_ =0;
+
+ pict_ = new unsigned char[width_*height_];
+ memset(pict_,0,width_*height_);
+
+ //alg1(pixels);
+ alg2(pixels);
+
+ // *** Local Image Descriptor ***
+ {
+ // Image Separator
+ unsigned char img= 0x2C;
+ out_->write((char*)&img,1);
+
+ // Image Left Position
+ unsigned short left = 0;
+ out_->write((char*)&left,2);
+
+ // Image Top Position
+ unsigned short top = 0;
+ out_->write((char*)&top,2);
+
+ // Image Width
+ unsigned short ww = width_;
+ out_->write((char*)&ww,2);
+
+ // Image Heght
+ unsigned short hh = height_;
+ out_->write((char*)&hh,2);
+
+ // Packed Field msb to lsb
+ // Local Table Flag (1): 1 local table, 0 no
+ // Interlace Flag (1): 1 interlaced, 0 no
+ // Sort Flag (1): 1 sorted, 0 no
+ // Reserved (2):
+ // Size of Local Table (3): size 2^(x+1)
+ union qq {
+ struct pp {
+ unsigned int size: 3;
+ unsigned int reserve: 2;
+ unsigned int sort: 1;
+ unsigned int interlace: 1;
+ unsigned int ct: 1;
+ } tt;
+ unsigned char cc;
+ };
+ union qq pkg;
+
+ pkg.tt.ct = 1;
+ pkg.tt.interlace =0;
+ pkg.tt.sort = 0;
+ pkg.tt.reserve = 0;
+ pkg.tt.size = resolution_-1;
+
+ out_->write((char*)&pkg.cc,1);
+ }
+
+ // *** Local Color Table ***
+ for (int ii=0; ii<colorTableSize_; ii++) {
+ out_->write((char*)&colorTable_[ii].red,1);
+ out_->write((char*)&colorTable_[ii].green,1);
+ out_->write((char*)&colorTable_[ii].blue,1);
+ }
+
+ // *** Image Data ***
+ // noCompress();
+ compress();
+
+ // end of Image Data
+ unsigned char end= 0x00;
+ out_->write((char*)&end,1);
+
+ // cleanup
+ if (pict_)
+ delete [] pict_;
+ pict_ =NULL;
+ pictCount_ =0;
+
+ if (colorTable_)
+ delete [] colorTable_;
+ colorTable_ =NULL;
+
+ return TCL_OK;
+}
+
+int TkAGIF::close(int argc, const char* argv[])
+{
+ // *** Trailer ***
+ unsigned char end = 0x3B;
+ out_->write((char*)&end,1);
+
+ out_->close();
+ delete out_;
+
+ return TCL_OK;
+}
+
+void TkAGIF::initColorTable(Color* ct)
+{
+ // Base Colors
+ // 0: black
+ // 1: white
+ ct[1].red = ct[1].green = ct[1].blue = 255;
+ ct[1].count++;
+ // 2: red
+ ct[2].red = 255;
+ ct[2].count++;
+ // 3: green
+ ct[3].green = 255;
+ ct[3].count++;
+ // 4: blue
+ ct[4].blue = 255;
+ ct[4].count++;
+ // 5: cyan
+ ct[5].green = ct[5].blue = 255;
+ ct[5].count++;
+ // 6: magenta
+ ct[6].red = ct[6].blue = 255;
+ ct[6].count++;
+ // 7: yellow
+ ct[7].red = ct[7].green = 255;
+ ct[7].count++;
+
+ // some Greys for numerics
+ // 8: 1/4 grey
+ ct[8].red = ct[8].green = ct[8].blue = 64;
+ ct[8].count++;
+ // 9: 1/2 grey
+ ct[9].red = ct[9].green = ct[9].blue = 128;
+ ct[9].count++;
+ // 10: 3/4 grey
+ ct[10].red = ct[10].green = ct[10].blue = 192;
+ ct[10].count++;
+}
+
+#define ALMOSTRED(aa,bb) (abs(aa-bb) <= resRed ? 1 : 0)
+#define ALMOSTGREEN(aa,bb) (abs(aa-bb) <= resGreen ? 1 : 0)
+#define ALMOSTBLUE(aa,bb) (abs(aa-bb) <= resBlue ? 1 : 0)
+
+void TkAGIF::alg2(Pixel* pixels)
+{
+ int maxColors = 256;
+
+ int finished =0;
+ int res = 1;
+ int totalColors =11;
+ do {
+ int resRed = res;
+ int resGreen = res;
+ int resBlue = res;
+ // int resRed = int(res*.59/.3+.5);
+ // int resGreen = res;
+ // int resBlue = int(res*.59/.11+.5);
+ // int resRed = int(res*.7154/.2125+.5);
+ // int resGreen = res;
+ // int resBlue = int(res*.7154/.072+.5);
+ if (colorTable_)
+ delete [] colorTable_;
+ colorTable_ =NULL;
+ colorTable_ = new Color[maxColors];
+ memset(colorTable_,0,sizeof(Color)*maxColors);
+ totalColors =11;
+ initColorTable(colorTable_);
+
+ Pixel* src = pixels;
+ unsigned char* dst = pict_;
+ for (int jj=0; jj<height_; jj++) {
+ for (int ii=0; ii<width_; ii++, src++, dst++) {
+ // first try all known colors
+ int done =0;
+ for (int kk=0; kk<totalColors; kk++) {
+ if (ALMOSTRED(src->red, colorTable_[kk].red) &&
+ ALMOSTGREEN(src->green, colorTable_[kk].green) &&
+ ALMOSTBLUE(src->blue, colorTable_[kk].blue)) {
+ colorTable_[kk].count++;
+ *dst = kk;
+ done =1;
+ break;
+ }
+ }
+
+ // add color
+ if (!done) {
+ if (totalColors<maxColors) {
+ colorTable_[totalColors].red = src->red;
+ colorTable_[totalColors].green = src->green;
+ colorTable_[totalColors].blue = src->blue;
+ colorTable_[totalColors].count++;
+ *dst = totalColors;
+ totalColors++;
+ }
+ else {
+ // abort, try again
+ res ++;
+ goto end;
+ }
+ }
+ }
+ }
+ finished =1;
+ cerr << "Res : " << res << ' '
+ << resRed << ' '
+ << resGreen << ' '
+ << resBlue << endl;
+ cerr << " Count: " << totalColors << endl;
+
+ end:
+ ;
+ // nothing
+ } while (!finished);
+
+ resolution_ =0;
+ while (totalColors >> resolution_)
+ resolution_++;
+ if (resolution_>8)
+ resolution_ =8;
+ colorTableSize_ = 1 << resolution_;
+
+ if (0) {
+ cerr << "Resolution: " << resolution_ << endl;
+ cerr << "ColorTableSize: " << colorTableSize_ << endl;
+ cerr << "Total Colors: " << totalColors << endl;
+ for (int ii=0; ii<totalColors; ii++) {
+ cerr << ii << ' '
+ << colorTable_[ii].count << ' '
+ << (unsigned short)(colorTable_[ii].red) << ' '
+ << (unsigned short)colorTable_[ii].green << ' '
+ << (unsigned short)colorTable_[ii].blue << endl;
+ }
+ }
+}
+
+void TkAGIF::alg1(Pixel* pixels)
+{
+ int totalColors =11;
+ int maxColors = 4096;
+ Color cc[maxColors];
+ memset(cc,0,sizeof(Color)*maxColors);
+
+ initColorTable(cc);
+
// Scan and sort all colors
{
Pixel* dst = pixels;
@@ -377,9 +562,9 @@ int TkAGIF::add(int argc, const char* argv[])
// first try all known colors
int done =0;
for (int kk=0; kk<totalColors; kk++) {
- if (ALMOST(dst->red, cc[kk].red) &&
- ALMOST(dst->green, cc[kk].green) &&
- ALMOST(dst->blue, cc[kk].blue)) {
+ if (dst->red == cc[kk].red &&
+ dst->green == cc[kk].green &&
+ dst->blue == cc[kk].blue) {
cc[kk].count++;
done =1;
break;
@@ -411,6 +596,9 @@ int TkAGIF::add(int argc, const char* argv[])
resolution_ =8;
colorTableSize_ = 1 << resolution_;
+ cerr << "Resolution: " << resolution_ << endl;
+ cerr << "ColorTableSize: " << colorTableSize_ << endl;
+ cerr << "Total Colors: " << totalColors << endl;
if (0) {
cerr << "Resolution: " << resolution_ << endl;
cerr << "ColorTableSize: " << colorTableSize_ << endl;
@@ -425,35 +613,28 @@ int TkAGIF::add(int argc, const char* argv[])
}
// build colortable
- Color ct[colorTableSize_];
- memset(ct,0,sizeof(Color)*colorTableSize_);
+ colorTable_ = new Color[colorTableSize_];
+ memset(colorTable_,0,sizeof(Color)*colorTableSize_);
for (int ii=0; ii<colorTableSize_; ii++) {
- ct[ii].count = cc[ii].count;
- ct[ii].red = cc[ii].red;
- ct[ii].green = cc[ii].green;
- ct[ii].blue = cc[ii].blue;
+ colorTable_[ii].count = cc[ii].count;
+ colorTable_[ii].red = cc[ii].red;
+ colorTable_[ii].green = cc[ii].green;
+ colorTable_[ii].blue = cc[ii].blue;
}
if (0) {
cerr << "ColorTable Size: " << colorTableSize_ << endl;
for (int ii=0; ii<colorTableSize_; ii++) {
cerr << ii << ' '
- << ct[ii].count << ' '
- << (unsigned short)(ct[ii].red) << ' '
- << (unsigned short)ct[ii].green << ' '
- << (unsigned short)ct[ii].blue << endl;
+ << colorTable_[ii].count << ' '
+ << (unsigned short)(colorTable_[ii].red) << ' '
+ << (unsigned short)colorTable_[ii].green << ' '
+ << (unsigned short)colorTable_[ii].blue << endl;
}
}
// now indexed image
- if (pict_)
- delete [] pict_;
- pict_ =NULL;
- pictCount_ =0;
-
- pict_ = new unsigned char[width_*height_];
- memset(pict_,0,width_*height_);
{
Pixel* src = pixels;
unsigned char* dst = pict_;
@@ -463,9 +644,9 @@ int TkAGIF::add(int argc, const char* argv[])
// first try all known colors
int done =0;
for (int kk=0; kk<colorTableSize_; kk++) {
- if (ALMOST(src->red, ct[kk].red) &&
- ALMOST(src->green, ct[kk].green) &&
- ALMOST(src->blue, ct[kk].blue)) {
+ if (src->red == colorTable_[kk].red &&
+ src->green == colorTable_[kk].green &&
+ src->blue == colorTable_[kk].blue) {
*dst = (unsigned char)kk;
done =1;
break;
@@ -477,10 +658,13 @@ int TkAGIF::add(int argc, const char* argv[])
int id =0;
double dd =FLT_MAX;
for (int kk=0; kk<colorTableSize_; kk++) {
- double vv =
- pow((src->red - ct[kk].red) *.3,2) +
- pow((src->green - ct[kk].green) *.59,2) +
- pow((src->blue - ct[kk].blue) *.11,2);
+ double rr = (src->red - colorTable_[kk].red);
+ double gg = (src->green - colorTable_[kk].green);
+ double bb = (src->blue - colorTable_[kk].blue);
+ // double rr = (src->red - colorTable_[kk].red)*.3;
+ // double gg = (src->green - colorTable_[kk].green)*.59;
+ // double bb = (src->blue - colorTable_[kk].blue)*.11;
+ double vv = sqrt(rr*rr+gg*gg+bb*bb);
if (vv<dd) {
id = kk;
dd = vv;
@@ -491,90 +675,6 @@ int TkAGIF::add(int argc, const char* argv[])
}
}
}
-
- // *** Local Image Descriptor ***
- {
- // Image Separator
- unsigned char img= 0x2C;
- out_->write((char*)&img,1);
-
- // Image Left Position
- unsigned short left = 0;
- out_->write((char*)&left,2);
-
- // Image Top Position
- unsigned short top = 0;
- out_->write((char*)&top,2);
-
- // Image Width
- unsigned short ww = width_;
- out_->write((char*)&ww,2);
-
- // Image Heght
- unsigned short hh = height_;
- out_->write((char*)&hh,2);
-
- // Packed Field msb to lsb
- // Local Table Flag (1): 1 local table, 0 no
- // Interlace Flag (1): 1 interlaced, 0 no
- // Sort Flag (1): 1 sorted, 0 no
- // Reserved (2):
- // Size of Local Table (3): size 2^(x+1)
- union qq {
- struct pp {
- unsigned int size: 3;
- unsigned int reserve: 2;
- unsigned int sort: 1;
- unsigned int interlace: 1;
- unsigned int ct: 1;
- } tt;
- unsigned char cc;
- };
- union qq pkg;
-
- pkg.tt.ct = 1;
- pkg.tt.interlace =0;
- pkg.tt.sort = 0;
- pkg.tt.reserve = 0;
- pkg.tt.size = resolution_-1;
-
- out_->write((char*)&pkg.cc,1);
- }
-
- // *** Local Color Table ***
- for (int ii=0; ii<colorTableSize_; ii++) {
- out_->write((char*)&ct[ii].red,1);
- out_->write((char*)&ct[ii].green,1);
- out_->write((char*)&ct[ii].blue,1);
- }
-
- // *** Image Data ***
- // noCompress();
- compress();
-
- // end of Image Data
- unsigned char end= 0x00;
- out_->write((char*)&end,1);
-
- // cleanup
- if (pict_)
- delete [] pict_;
- pict_ =NULL;
- pictCount_ =0;
-
- return TCL_OK;
-}
-
-int TkAGIF::close(int argc, const char* argv[])
-{
- // *** Trailer ***
- unsigned char end = 0x3B;
- out_->write((char*)&end,1);
-
- out_->close();
- delete out_;
-
- return TCL_OK;
}
void TkAGIF::noCompress()
diff --git a/tkagif/tkagif.h b/tkagif/tkagif.h
index a2a284c..69f0264 100644
--- a/tkagif/tkagif.h
+++ b/tkagif/tkagif.h
@@ -28,6 +28,19 @@
#define HSIZE 5003 /* 80% occupancy */
+typedef struct {
+ int count;
+ unsigned char red;
+ unsigned char green;
+ unsigned char blue;
+} Color;
+
+typedef struct {
+ unsigned char red;
+ unsigned char green;
+ unsigned char blue;
+} Pixel;
+
class TkAGIF {
private:
Tcl_Interp* interp_;
@@ -35,13 +48,13 @@ private:
ofstream* out_;
int width_;
int height_;
-
- int colorRes_;
- int colorTableSize_;
int resolution_;
unsigned char* pict_;
long pictCount_;
+
+ Color* colorTable_;
+ int colorTableSize_;
long maxCode_; // Maximum code, given numBits
int clearCode_;
@@ -60,6 +73,9 @@ private:
unsigned long currentAccumulated_;
private:
+ void initColorTable(Color*);
+ void alg1(Pixel*);
+ void alg2(Pixel*);
void noCompress();
void compress();