1 47 package com.lowagie.text.pdf.codec; 48 49 import java.io.BufferedInputStream ; 50 import java.io.ByteArrayInputStream ; 51 import java.io.DataInputStream ; 52 import java.io.IOException ; 53 import java.io.InputStream ; 54 import java.net.URL ; 55 import java.util.ArrayList ; 56 57 import com.lowagie.text.ExceptionConverter; 58 import com.lowagie.text.Image; 59 import com.lowagie.text.ImgRaw; 60 import com.lowagie.text.Utilities; 61 import com.lowagie.text.pdf.PdfArray; 62 import com.lowagie.text.pdf.PdfDictionary; 63 import com.lowagie.text.pdf.PdfName; 64 import com.lowagie.text.pdf.PdfNumber; 65 import com.lowagie.text.pdf.PdfString; 66 67 71 public class GifImage { 72 73 protected DataInputStream in; 74 protected int width; protected int height; protected boolean gctFlag; 78 protected int bgIndex; protected int bgColor; protected int pixelAspect; 82 protected boolean lctFlag; protected boolean interlace; protected int lctSize; 86 protected int ix, iy, iw, ih; 88 protected byte[] block = new byte[256]; protected int blockSize = 0; 91 protected int dispose = 0; protected boolean transparency = false; protected int delay = 0; protected int transIndex; 97 protected static final int MaxStackSize = 4096; 99 protected short[] prefix; 101 protected byte[] suffix; 102 protected byte[] pixelStack; 103 protected byte[] pixels; 104 105 protected byte m_out[]; 106 protected int m_bpc; 107 protected int m_gbpc; 108 protected byte m_global_table[]; 109 protected byte m_local_table[]; 110 protected byte m_curr_table[]; 111 protected int m_line_stride; 112 protected byte fromData[]; 113 protected URL fromUrl; 114 115 116 protected ArrayList frames = new ArrayList (); 118 122 public GifImage(URL url) throws IOException { 123 fromUrl = url; 124 InputStream is = null; 125 try { 126 is = url.openStream(); 127 process(is); 128 } 129 finally { 130 if (is != null) { 131 is.close(); 132 } 133 } 134 } 135 136 140 public GifImage(String file) throws IOException { 141 this(Utilities.toURL(file)); 142 } 143 144 148 public GifImage(byte data[]) throws IOException { 149 fromData = data; 150 InputStream is = null; 151 try { 152 is = new ByteArrayInputStream (data); 153 process(is); 154 } 155 finally { 156 if (is != null) { 157 is.close(); 158 } 159 } 160 } 161 162 166 public GifImage(InputStream is) throws IOException { 167 process(is); 168 } 169 170 173 public int getFrameCount() { 174 return frames.size(); 175 } 176 177 181 public Image getImage(int frame) { 182 GifFrame gf = (GifFrame)frames.get(frame - 1); 183 return gf.image; 184 } 185 186 191 public int[] getFramePosition(int frame) { 192 GifFrame gf = (GifFrame)frames.get(frame - 1); 193 return new int[]{gf.ix, gf.iy}; 194 195 } 196 197 202 public int[] getLogicalScreen() { 203 return new int[]{width, height}; 204 } 205 206 void process(InputStream is) throws IOException { 207 in = new DataInputStream (new BufferedInputStream (is)); 208 readHeader(); 209 readContents(); 210 if (frames.isEmpty()) 211 throw new IOException ("The file does not contain any valid image."); 212 } 213 214 217 protected void readHeader() throws IOException { 218 String id = ""; 219 for (int i = 0; i < 6; i++) 220 id += (char)in.read(); 221 if (!id.startsWith("GIF8")) { 222 throw new IOException ("Gif signature nor found."); 223 } 224 225 readLSD(); 226 if (gctFlag) { 227 m_global_table = readColorTable(m_gbpc); 228 } 229 } 230 231 234 protected void readLSD() throws IOException { 235 236 width = readShort(); 238 height = readShort(); 239 240 int packed = in.read(); 242 gctFlag = (packed & 0x80) != 0; m_gbpc = (packed & 7) + 1; 244 bgIndex = in.read(); pixelAspect = in.read(); } 247 248 251 protected int readShort() throws IOException { 252 return in.read() | (in.read() << 8); 254 } 255 256 261 protected int readBlock() throws IOException { 262 blockSize = in.read(); 263 if (blockSize <= 0) 264 return blockSize = 0; 265 for (int k = 0; k < blockSize; ++k) { 266 int v = in.read(); 267 if (v < 0) { 268 return blockSize = k; 269 } 270 block[k] = (byte)v; 271 } 272 return blockSize; 273 } 274 275 protected byte[] readColorTable(int bpc) throws IOException { 276 int ncolors = 1 << bpc; 277 int nbytes = 3*ncolors; 278 bpc = newBpc(bpc); 279 byte table[] = new byte[(1 << bpc) * 3]; 280 in.readFully(table, 0, nbytes); 281 return table; 282 } 283 284 285 static protected int newBpc(int bpc) { 286 switch (bpc) { 287 case 1: 288 case 2: 289 case 4: 290 break; 291 case 3: 292 return 4; 293 default: 294 return 8; 295 } 296 return bpc; 297 } 298 299 protected void readContents() throws IOException { 300 boolean done = false; 302 while (!done) { 303 int code = in.read(); 304 switch (code) { 305 306 case 0x2C: readImage(); 308 break; 309 310 case 0x21: code = in.read(); 312 switch (code) { 313 314 case 0xf9: readGraphicControlExt(); 316 break; 317 318 case 0xff: readBlock(); 320 skip(); break; 322 323 default: skip(); 325 } 326 break; 327 328 default: 329 done = true; 330 break; 331 } 332 } 333 } 334 335 338 protected void readImage() throws IOException { 339 ix = readShort(); iy = readShort(); 341 iw = readShort(); 342 ih = readShort(); 343 344 int packed = in.read(); 345 lctFlag = (packed & 0x80) != 0; interlace = (packed & 0x40) != 0; lctSize = 2 << (packed & 7); m_bpc = newBpc(m_gbpc); 351 if (lctFlag) { 352 m_curr_table = readColorTable((packed & 7) + 1); m_bpc = newBpc((packed & 7) + 1); 354 } 355 else { 356 m_curr_table = m_global_table; 357 } 358 if (transparency && transIndex >= m_curr_table.length / 3) 359 transparency = false; 360 if (transparency && m_bpc == 1) { byte tp[] = new byte[12]; 362 System.arraycopy(m_curr_table, 0, tp, 0, 6); 363 m_curr_table = tp; 364 m_bpc = 2; 365 } 366 boolean skipZero = decodeImageData(); if (!skipZero) 368 skip(); 369 370 Image img = null; 371 try { 372 img = new ImgRaw(iw, ih, 1, m_bpc, m_out); 373 PdfArray colorspace = new PdfArray(); 374 colorspace.add(PdfName.INDEXED); 375 colorspace.add(PdfName.DEVICERGB); 376 int len = m_curr_table.length; 377 colorspace.add(new PdfNumber(len / 3 - 1)); 378 colorspace.add(new PdfString(m_curr_table)); 379 PdfDictionary ad = new PdfDictionary(); 380 ad.put(PdfName.COLORSPACE, colorspace); 381 img.setAdditional(ad); 382 if (transparency) { 383 img.setTransparency(new int[]{transIndex, transIndex}); 384 } 385 } 386 catch (Exception e) { 387 throw new ExceptionConverter(e); 388 } 389 img.setOriginalType(Image.ORIGINAL_GIF); 390 img.setOriginalData(fromData); 391 img.setUrl(fromUrl); 392 GifFrame gf = new GifFrame(); 393 gf.image = img; 394 gf.ix = ix; 395 gf.iy = iy; 396 frames.add(gf); 398 400 } 401 402 protected boolean decodeImageData() throws IOException { 403 int NullCode = -1; 404 int npix = iw * ih; 405 int available, clear, code_mask, code_size, end_of_information, in_code, old_code, 406 bits, code, count, i, datum, data_size, first, top, bi; 407 boolean skipZero = false; 408 409 if (prefix == null) 410 prefix = new short[MaxStackSize]; 411 if (suffix == null) 412 suffix = new byte[MaxStackSize]; 413 if (pixelStack == null) 414 pixelStack = new byte[MaxStackSize+1]; 415 416 m_line_stride = (iw * m_bpc + 7) / 8; 417 m_out = new byte[m_line_stride * ih]; 418 int pass = 1; 419 int inc = interlace ? 8 : 1; 420 int line = 0; 421 int xpos = 0; 422 423 425 data_size = in.read(); 426 clear = 1 << data_size; 427 end_of_information = clear + 1; 428 available = clear + 2; 429 old_code = NullCode; 430 code_size = data_size + 1; 431 code_mask = (1 << code_size) - 1; 432 for (code = 0; code < clear; code++) { 433 prefix[code] = 0; 434 suffix[code] = (byte) code; 435 } 436 437 439 datum = bits = count = first = top = bi = 0; 440 441 for (i = 0; i < npix; ) { 442 if (top == 0) { 443 if (bits < code_size) { 444 if (count == 0) { 446 count = readBlock(); 448 if (count <= 0) { 449 skipZero = true; 450 break; 451 } 452 bi = 0; 453 } 454 datum += (((int) block[bi]) & 0xff) << bits; 455 bits += 8; 456 bi++; 457 count--; 458 continue; 459 } 460 461 463 code = datum & code_mask; 464 datum >>= code_size; 465 bits -= code_size; 466 467 469 if ((code > available) || (code == end_of_information)) 470 break; 471 if (code == clear) { 472 code_size = data_size + 1; 474 code_mask = (1 << code_size) - 1; 475 available = clear + 2; 476 old_code = NullCode; 477 continue; 478 } 479 if (old_code == NullCode) { 480 pixelStack[top++] = suffix[code]; 481 old_code = code; 482 first = code; 483 continue; 484 } 485 in_code = code; 486 if (code == available) { 487 pixelStack[top++] = (byte) first; 488 code = old_code; 489 } 490 while (code > clear) { 491 pixelStack[top++] = suffix[code]; 492 code = prefix[code]; 493 } 494 first = ((int) suffix[code]) & 0xff; 495 496 498 if (available >= MaxStackSize) 499 break; 500 pixelStack[top++] = (byte) first; 501 prefix[available] = (short) old_code; 502 suffix[available] = (byte) first; 503 available++; 504 if (((available & code_mask) == 0) && (available < MaxStackSize)) { 505 code_size++; 506 code_mask += available; 507 } 508 old_code = in_code; 509 } 510 511 513 top--; 514 i++; 515 516 setPixel(xpos, line, pixelStack[top]); 517 ++xpos; 518 if (xpos >= iw) { 519 xpos = 0; 520 line += inc; 521 if (line >= ih) { 522 if (interlace) { 523 do { 524 pass++; 525 switch (pass) { 526 case 2: 527 line = 4; 528 break; 529 case 3: 530 line = 2; 531 inc = 4; 532 break; 533 case 4: 534 line = 1; 535 inc = 2; 536 break; 537 default: line = ih - 1; 539 inc = 0; 540 } 541 } while (line >= ih); 542 } 543 else { 544 line = ih - 1; inc = 0; 546 } 547 } 548 } 549 } 550 return skipZero; 551 } 552 553 554 protected void setPixel(int x, int y, int v) { 555 if (m_bpc == 8) { 556 int pos = x + iw * y; 557 m_out[pos] = (byte)v; 558 } 559 else { 560 int pos = m_line_stride * y + x / (8 / m_bpc); 561 int vout = v << (8 - m_bpc * (x % (8 / m_bpc))- m_bpc); 562 m_out[pos] |= vout; 563 } 564 } 565 566 569 protected void resetFrame() { 570 } 574 575 578 protected void readGraphicControlExt() throws IOException { 579 in.read(); int packed = in.read(); dispose = (packed & 0x1c) >> 2; if (dispose == 0) 583 dispose = 1; transparency = (packed & 1) != 0; 585 delay = readShort() * 10; transIndex = in.read(); in.read(); } 589 590 594 protected void skip() throws IOException { 595 do { 596 readBlock(); 597 } while (blockSize > 0); 598 } 599 600 static class GifFrame { 601 Image image; 602 int ix; 603 int iy; 604 } 605 } 606 | Popular Tags |