5 import java.awt.image.*;
40 private boolean interlace =
false;
41 private int width, height;
42 private byte[] pixels;
43 private byte[] r, g, b;
44 private int pixelIndex;
45 private int numPixels;
46 private int transparentPixel = -1;
57 public GifEncoder(
int width,
int height, byte[] pixels, byte[] r, byte[] g, byte[] b) {
61 this.r = r; this.g = g; this.b = b;
64 numPixels = width*height;
70 width = img.getWidth(null);
71 height = img.getHeight(null);
72 pixels =
new byte[width * height];
73 PixelGrabber pg =
new PixelGrabber(img, 0, 0, width, height,
false);
76 }
catch (InterruptedException e) {
77 System.err.println(e);
79 ColorModel cm = pg.getColorModel();
80 if (cm instanceof IndexColorModel)
82 pixels = (byte[])(pg.getPixels());
84 IndexColorModel icm = (IndexColorModel)cm;
85 setTransparentPixel(icm.getTransparentPixel());
88 throw new IllegalArgumentException(
"Image must be 8-bit");
89 IndexColorModel m = (IndexColorModel)cm;
90 int mapSize = m.getMapSize();
91 r =
new byte[mapSize];
92 g =
new byte[mapSize];
93 b =
new byte[mapSize];
99 numPixels = width*height;
104 public void write(OutputStream out)
throws IOException {
106 int numColors = r.length;
110 else if (numColors<=4)
112 else if (numColors<=16)
117 int ColorMapSize = 1 << BitsPerPixel;
118 byte[] reds =
new byte[ColorMapSize];
119 byte[] grns =
new byte[ColorMapSize];
120 byte[] blus =
new byte[ColorMapSize];
121 for (
int i=0; i<numColors; i++) {
128 GIFEncode(out, width, height, interlace, (byte) 0,
129 getTransparentPixel(), BitsPerPixel, reds, grns, blus);
133 public void setTransparentPixel(
int pixel) {
134 transparentPixel = pixel;
138 public int getTransparentPixel() {
139 return transparentPixel;
142 static void writeString(OutputStream out, String str)
throws IOException
144 byte[] buf = str.getBytes();
156 OutputStream outs,
int Width,
int Height,
boolean Interlace, byte Background,
int Transparent,
int BitsPerPixel, byte[] Red, byte[] Green, byte[] Blue )
166 this.Height = Height;
167 this.Interlace = Interlace;
168 ColorMapSize = 1 << BitsPerPixel;
169 LeftOfs = TopOfs = 0;
172 if ( BitsPerPixel <= 1 )
175 InitCodeSize = BitsPerPixel;
178 writeString( outs,
"GIF89a" );
181 Putword( Width, outs );
182 Putword( Height, outs );
187 B |= (byte) ( ( 8 - 1 ) << 4 );
190 B |= (byte) ( ( BitsPerPixel - 1 ) );
196 Putbyte( Background, outs );
204 Putbyte( (byte) 0, outs );
207 for ( i = 0; i < ColorMapSize; ++i )
209 Putbyte( Red[i], outs );
210 Putbyte( Green[i], outs );
211 Putbyte( Blue[i], outs );
215 if ( Transparent != -1 )
217 Putbyte( (byte)
'!', outs );
218 Putbyte( (byte) 0xf9, outs );
219 Putbyte( (byte) 4, outs );
220 Putbyte( (byte) 1, outs );
221 Putbyte( (byte) 0, outs );
222 Putbyte( (byte) 0, outs );
223 Putbyte( (byte) Transparent, outs );
224 Putbyte( (byte) 0, outs );
228 Putbyte( (byte)
',', outs );
231 Putword( LeftOfs, outs );
232 Putword( TopOfs, outs );
233 Putword( Width, outs );
234 Putword( Height, outs );
238 Putbyte( (byte) 0x40, outs );
240 Putbyte( (byte) 0x00, outs );
243 Putbyte( (byte) InitCodeSize, outs );
246 compress( InitCodeSize+1, outs );
249 Putbyte( (byte) 0, outs );
252 Putbyte( (byte)
';', outs );
256 static final int EOF = -1;
259 int GIFNextPixel() throws IOException {
260 if (pixelIndex==numPixels)
263 return ((byte[])pixels)[pixelIndex++] & 0xff;
268 void Putword(
int w, OutputStream outs )
throws IOException
270 Putbyte( (byte) ( w & 0xff ), outs );
271 Putbyte( (byte) ( ( w >> 8 ) & 0xff ), outs );
275 void Putbyte( byte b, OutputStream outs )
throws IOException
288 static final int BITS = 12;
290 static final int HSIZE = 5003;
306 int maxmaxcode = 1 << BITS;
308 final int MAXCODE(
int n_bits )
310 return ( 1 << n_bits ) - 1;
313 int[] htab =
new int[HSIZE];
314 int[] codetab =
new int[HSIZE];
322 boolean clear_flg =
false;
341 void compress(
int init_bits, OutputStream outs )
throws IOException
352 g_init_bits = init_bits;
356 n_bits = g_init_bits;
357 maxcode = MAXCODE( n_bits );
359 ClearCode = 1 << ( init_bits - 1 );
360 EOFCode = ClearCode + 1;
361 free_ent = ClearCode + 2;
365 ent = GIFNextPixel();
368 for ( fcode = hsize; fcode < 65536; fcode *= 2 )
373 cl_hash( hsize_reg );
375 output( ClearCode, outs );
378 while ( (c = GIFNextPixel()) != EOF )
380 fcode = ( c << maxbits ) + ent;
381 i = ( c << hshift ) ^ ent;
383 if ( htab[i] == fcode )
388 else if ( htab[i] >= 0 )
390 disp = hsize_reg - i;
395 if ( (i -= disp) < 0 )
398 if ( htab[i] == fcode )
404 while ( htab[i] >= 0 );
408 if ( free_ent < maxmaxcode )
410 codetab[i] = free_ent++;
418 output( EOFCode, outs );
439 int masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
440 0x001F, 0x003F, 0x007F, 0x00FF,
441 0x01FF, 0x03FF, 0x07FF, 0x0FFF,
442 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
444 void output(
int code, OutputStream outs )
throws IOException
446 cur_accum &= masks[cur_bits];
449 cur_accum |= ( code << cur_bits );
455 while ( cur_bits >= 8 )
457 char_out( (byte) ( cur_accum & 0xff ), outs );
464 if ( free_ent > maxcode || clear_flg )
468 maxcode = MAXCODE(n_bits = g_init_bits);
474 if ( n_bits == maxbits )
475 maxcode = maxmaxcode;
477 maxcode = MAXCODE(n_bits);
481 if ( code == EOFCode )
484 while ( cur_bits > 0 )
486 char_out( (byte) ( cur_accum & 0xff ), outs );
498 void cl_block( OutputStream outs )
throws IOException
501 free_ent = ClearCode + 2;
504 output( ClearCode, outs );
508 void cl_hash(
int hsize )
510 for (
int i = 0; i < hsize; ++i )
526 byte[] accum =
new byte[256];
530 void char_out( byte c, OutputStream outs )
throws IOException
532 accum[a_count++] = c;
533 if ( a_count >= 254 )
538 void flush_char( OutputStream outs )
throws IOException
542 outs.write( a_count );
543 outs.write( accum, 0, a_count );
550 class GifEncoderHashitem {
554 public boolean isTransparent;
556 public GifEncoderHashitem(
int rgb,
int count,
int index,
boolean isTransparent) {
560 this.isTransparent = isTransparent;