📄 gifencoder.java
字号:
}
}
abstract class Gif89Frame {
static final int DM_UNDEFINED = 0;
static final int DM_LEAVE = 1;
static final int DM_BGCOLOR = 2;
static final int DM_REVERT = 3;
int theWidth = -1;
int theHeight = -1;
byte[] ciPixels;
private Point thePosition = new Point(0, 0);
private boolean isInterlaced;
private int csecsDelay;
private int disposalCode = DM_LEAVE;
void setPosition(Point p) {
thePosition = new Point(p);
}
void setInterlaced(boolean b) {
isInterlaced = b;
}
void setDelay(int interval) {
csecsDelay = interval;
}
void setDisposalMode(int code) {
disposalCode = code;
}
Gif89Frame() {
}
abstract Object getPixelSource();
int getWidth() {
return theWidth;
}
int getHeight() {
return theHeight;
}
byte[] getPixelSink() {
return ciPixels;
}
void encode(OutputStream os, boolean epluribus, int color_depth,
int transparent_index) throws IOException {
writeGraphicControlExtension(os, epluribus, transparent_index);
writeImageDescriptor(os);
new GifPixelsEncoder(
theWidth, theHeight, ciPixels, isInterlaced, color_depth
).encode(os);
}
private void writeGraphicControlExtension(OutputStream os, boolean epluribus,
int itransparent) throws IOException {
int transflag = itransparent == -1 ? 0 : 1;
if (transflag == 1 || epluribus) {
os.write((int) '!');
os.write(0xf9);
os.write(4);
os.write((disposalCode << 2) | transflag);
Put.leShort(csecsDelay, os);
os.write(itransparent);
os.write(0);
}
}
private void writeImageDescriptor(OutputStream os) throws IOException {
os.write((int) ',');
Put.leShort(thePosition.x, os);
Put.leShort(thePosition.y, os);
Put.leShort(theWidth, os);
Put.leShort(theHeight, os);
os.write(isInterlaced ? 0x40 : 0);
}
}
class GifPixelsEncoder {
private static final int EOF = -1;
private int imgW, imgH;
private byte[] pixAry;
private boolean wantInterlaced;
private int initCodeSize;
private int countDown;
private int xCur, yCur;
private int curPass;
GifPixelsEncoder(int width, int height, byte[] pixels, boolean interlaced,
int color_depth) {
imgW = width;
imgH = height;
pixAry = pixels;
wantInterlaced = interlaced;
initCodeSize = Math.max(2, color_depth);
}
void encode(OutputStream os) throws IOException {
os.write(initCodeSize);
countDown = imgW * imgH;
xCur = yCur = curPass = 0;
compress(initCodeSize + 1, os);
os.write(0);
}
private void bumpPosition() {
++xCur;
if (xCur == imgW) {
xCur = 0;
if (!wantInterlaced)
++yCur;
else
switch (curPass) {
case 0:
yCur += 8;
if (yCur >= imgH) {
++curPass;
yCur = 4;
}
break;
case 1:
yCur += 8;
if (yCur >= imgH) {
++curPass;
yCur = 2;
}
break;
case 2:
yCur += 4;
if (yCur >= imgH) {
++curPass;
yCur = 1;
}
break;
case 3:
yCur += 2;
break;
}
}
}
private int nextPixel() {
if (countDown == 0)
return EOF;
--countDown;
byte pix = pixAry[yCur * imgW + xCur];
bumpPosition();
return pix & 0xff;
}
static final int BITS = 12;
static final int HSIZE = 5003;
int n_bits;
int maxbits = BITS;
int maxcode;
int maxmaxcode = 1 << BITS;
final int MAXCODE(int n_bits) {
return (1 << n_bits) - 1;
}
int[] htab = new int[HSIZE];
int[] codetab = new int[HSIZE];
int hsize = HSIZE;
int free_ent = 0;
boolean clear_flg = false;
int g_init_bits;
int ClearCode;
int EOFCode;
void compress(int init_bits, OutputStream outs) throws IOException {
int fcode;
int i /* = 0 */;
int c;
int ent;
int disp;
int hsize_reg;
int hshift;
g_init_bits = init_bits;
clear_flg = false;
n_bits = g_init_bits;
maxcode = MAXCODE(n_bits);
ClearCode = 1 << (init_bits - 1);
EOFCode = ClearCode + 1;
free_ent = ClearCode + 2;
char_init();
ent = nextPixel();
hshift = 0;
for (fcode = hsize; fcode < 65536; fcode *= 2)
++hshift;
hshift = 8 - hshift;
hsize_reg = hsize;
cl_hash(hsize_reg);
output(ClearCode, outs);
outer_loop:
while ((c = nextPixel()) != EOF) {
fcode = (c << maxbits) + ent;
i = (c << hshift) ^ ent;
if (htab[i] == fcode) {
ent = codetab[i];
continue;
} else if (htab[i] >= 0) {
disp = hsize_reg - i;
if (i == 0)
disp = 1;
do {
if ((i -= disp) < 0)
i += hsize_reg;
if (htab[i] == fcode) {
ent = codetab[i];
continue outer_loop;
}
} while (htab[i] >= 0);
}
output(ent, outs);
ent = c;
if (free_ent < maxmaxcode) {
codetab[i] = free_ent++;
htab[i] = fcode;
} else
cl_block(outs);
}
output(ent, outs);
output(EOFCode, outs);
}
int cur_accum = 0;
int cur_bits = 0;
int masks[] = {0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
0x001F, 0x003F, 0x007F, 0x00FF,
0x01FF, 0x03FF, 0x07FF, 0x0FFF,
0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF};
void output(int code, OutputStream outs) throws IOException {
cur_accum &= masks[cur_bits];
if (cur_bits > 0)
cur_accum |= (code << cur_bits);
else
cur_accum = code;
cur_bits += n_bits;
while (cur_bits >= 8) {
char_out((byte) (cur_accum & 0xff), outs);
cur_accum >>= 8;
cur_bits -= 8;
}
if (free_ent > maxcode || clear_flg) {
if (clear_flg) {
maxcode = MAXCODE(n_bits = g_init_bits);
clear_flg = false;
} else {
++n_bits;
if (n_bits == maxbits)
maxcode = maxmaxcode;
else
maxcode = MAXCODE(n_bits);
}
}
if (code == EOFCode) {
while (cur_bits > 0) {
char_out((byte) (cur_accum & 0xff), outs);
cur_accum >>= 8;
cur_bits -= 8;
}
flush_char(outs);
}
}
void cl_block(OutputStream outs) throws IOException {
cl_hash(hsize);
free_ent = ClearCode + 2;
clear_flg = true;
output(ClearCode, outs);
}
void cl_hash(int hsize) {
for (int i = 0; i < hsize; ++i)
htab[i] = -1;
}
int a_count;
void char_init() {
a_count = 0;
}
byte[] accum = new byte[256];
void char_out(byte c, OutputStream outs) throws IOException {
accum[a_count++] = c;
if (a_count >= 254)
flush_char(outs);
}
void flush_char(OutputStream outs) throws IOException {
if (a_count > 0) {
outs.write(a_count);
outs.write(accum, 0, a_count);
a_count = 0;
}
}
}
class IndexGif89Frame extends Gif89Frame {
IndexGif89Frame(int width, int height, byte ci_pixels[]) {
theWidth = width;
theHeight = height;
ciPixels = new byte[theWidth * theHeight];
System.arraycopy(ci_pixels, 0, ciPixels, 0, ciPixels.length);
}
Object getPixelSource() {
return ciPixels;
}
}
final class Put {
static void ascii(String s, OutputStream os) throws IOException {
byte[] bytes = new byte[s.length()];
for (int i = 0; i < bytes.length; ++i)
bytes[i] = (byte) s.charAt(i);
os.write(bytes);
}
static void leShort(int i16, OutputStream os) throws IOException {
os.write(i16 & 0xff);
os.write(i16 >> 8 & 0xff);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -