Advertisement
Guest User

Untitled

a guest
May 29th, 2015
278
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 25.67 KB | None | 0 0
  1. /**
  2. * Copyright (c) 2013 Xcellent Creations, Inc.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining
  5. * a copy of this software and associated documentation files (the
  6. * "Software"), to deal in the Software without restriction, including
  7. * without limitation the rights to use, copy, modify, merge, publish,
  8. * distribute, sublicense, and/or sell copies of the Software, and to
  9. * permit persons to whom the Software is furnished to do so, subject to
  10. * the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be
  13. * included in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  19. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  20. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  21. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. package com.example.decoder;
  24.  
  25. import android.graphics.Bitmap;
  26. import android.util.Log;
  27.  
  28. import java.io.ByteArrayOutputStream;
  29. import java.io.IOException;
  30. import java.io.InputStream;
  31. import java.nio.BufferUnderflowException;
  32. import java.nio.ByteBuffer;
  33. import java.nio.ByteOrder;
  34. import java.util.ArrayList;
  35.  
  36. /**
  37. * Reads frame data from a GIF image source and decodes it into individual frames
  38. * for animation purposes. Image data can be read from either and InputStream source
  39. * or a byte[].
  40. *
  41. * This class is optimized for running animations with the frames, there
  42. * are no methods to get individual frame images, only to decode the next frame in the
  43. * animation sequence. Instead, it lowers its memory footprint by only housing the minimum
  44. * data necessary to decode the next frame in the animation sequence.
  45. *
  46. * The animation must be manually moved forward using {@link #advance()} before requesting the next
  47. * frame. This method must also be called before you request the first frame or an error will
  48. * occur.
  49. *
  50. * Implementation adapted from sample code published in Lyons. (2004). <em>Java for Programmers</em>,
  51. * republished under the MIT Open Source License
  52. */
  53. public class GifDecoder {
  54. private static final String TAG = GifDecoder.class.getSimpleName();
  55.  
  56. /**
  57. * File read status: No errors.
  58. */
  59. public static final int STATUS_OK = 0;
  60. /**
  61. * File read status: Error decoding file (may be partially decoded)
  62. */
  63. public static final int STATUS_FORMAT_ERROR = 1;
  64. /**
  65. * File read status: Unable to open source.
  66. */
  67. public static final int STATUS_OPEN_ERROR = 2;
  68. /**
  69. * max decoder pixel stack size
  70. */
  71. protected static final int MAX_STACK_SIZE = 4096;
  72.  
  73. /**
  74. * GIF Disposal Method meaning take no action
  75. */
  76. private static final int DISPOSAL_UNSPECIFIED = 0;
  77. /**
  78. * GIF Disposal Method meaning leave canvas from previous frame
  79. */
  80. private static final int DISPOSAL_NONE = 1;
  81. /**
  82. * GIF Disposal Method meaning clear canvas to background color
  83. */
  84. private static final int DISPOSAL_BACKGROUND = 2;
  85. /**
  86. * GIF Disposal Method meaning clear canvas to frame before last
  87. */
  88. private static final int DISPOSAL_PREVIOUS = 3;
  89.  
  90. /**
  91. * Global status code of GIF data parsing
  92. */
  93. protected int status;
  94.  
  95. //Global File Header values and parsing flags
  96. protected int width; // full image width
  97. protected int height; // full image height
  98. protected boolean gctFlag; // global color table used
  99. protected int gctSize; // size of global color table
  100. protected int loopCount = 1; // iterations; 0 = repeat forever
  101. protected int[] gct; // global color table
  102. protected int[] act; // active color table
  103. protected int bgIndex; // background color index
  104. protected int bgColor; // background color
  105. protected int pixelAspect; // pixel aspect ratio
  106. protected boolean lctFlag; // local color table flag
  107. protected int lctSize; // local color table size
  108.  
  109. // Raw GIF data from input source
  110. protected ByteBuffer rawData;
  111.  
  112. // Raw data read working array
  113. protected byte[] block = new byte[256]; // current data block
  114. protected int blockSize = 0; // block size last graphic control extension info
  115.  
  116. // LZW decoder working arrays
  117. protected short[] prefix;
  118. protected byte[] suffix;
  119. protected byte[] pixelStack;
  120. protected byte[] mainPixels;
  121. protected int[] mainScratch, copyScratch;
  122.  
  123. protected ArrayList<GifFrame> frames; // frames read from current file
  124. protected GifFrame currentFrame;
  125. protected Bitmap previousImage, currentImage, renderImage;
  126.  
  127. protected int framePointer;
  128. protected int frameCount;
  129.  
  130. /**
  131. * Inner model class housing metadata for each frame
  132. */
  133. private static class GifFrame {
  134. public int ix, iy, iw, ih;
  135. /* Control Flags */
  136. public boolean interlace;
  137. public boolean transparency;
  138. /* Disposal Method */
  139. public int dispose;
  140. /* Transparency Index */
  141. public int transIndex;
  142. /* Delay, in ms, to next frame */
  143. public int delay;
  144. /* Index in the raw buffer where we need to start reading to decode */
  145. public int bufferFrameStart;
  146. /* Local Color Table */
  147. public int[] lct;
  148. }
  149.  
  150. /**
  151. * Move the animation frame counter forward
  152. */
  153. public void advance() {
  154. framePointer = (framePointer + 1) % frameCount;
  155. }
  156.  
  157. /**
  158. * Gets display duration for specified frame.
  159. *
  160. * @param n int index of frame
  161. * @return delay in milliseconds
  162. */
  163. public int getDelay(int n) {
  164. int delay = -1;
  165. if ((n >= 0) && (n < frameCount)) {
  166. delay = frames.get(n).delay;
  167. }
  168. return delay;
  169. }
  170.  
  171. /**
  172. * Gets display duration for the upcoming frame
  173. */
  174. public int getNextDelay() {
  175. if (frameCount <=0 || framePointer < 0) {
  176. return -1;
  177. }
  178.  
  179. return getDelay(framePointer);
  180. }
  181.  
  182. /**
  183. * Gets the number of frames read from file.
  184. *
  185. * @return frame count
  186. */
  187. public int getFrameCount() {
  188. return frameCount;
  189. }
  190.  
  191. /**
  192. * Gets the current index of the animation frame, or -1 if animation hasn't not yet started
  193. *
  194. * @return frame index
  195. */
  196. public int getCurrentFrameIndex() {
  197. return framePointer;
  198. }
  199.  
  200. /**
  201. * Gets the "Netscape" iteration count, if any. A count of 0 means repeat indefinitiely.
  202. *
  203. * @return iteration count if one was specified, else 1.
  204. */
  205. public int getLoopCount() {
  206. return loopCount;
  207. }
  208.  
  209. /**
  210. * Get the next frame in the animation sequence.
  211. *
  212. * @return Bitmap representation of frame
  213. */
  214. public Bitmap getNextFrame() {
  215. if (frameCount <= 0 || framePointer < 0 || currentImage == null) {
  216. return null;
  217. }
  218.  
  219. GifFrame frame = frames.get(framePointer);
  220.  
  221. //Set the appropriate color table
  222. if (frame.lct == null) {
  223. act = gct;
  224. } else {
  225. act = frame.lct;
  226. if (bgIndex == frame.transIndex) {
  227. bgColor = 0;
  228. }
  229. }
  230.  
  231. int save = 0;
  232. if (frame.transparency) {
  233. save = act[frame.transIndex];
  234. act[frame.transIndex] = 0; // set transparent color if specified
  235. }
  236. if (act == null) {
  237. Log.w(TAG, "No Valid Color Table");
  238. status = STATUS_FORMAT_ERROR; // no color table defined
  239. return null;
  240. }
  241.  
  242. setPixels(framePointer); // transfer pixel data to image
  243.  
  244. // Reset the transparent pixel in the color table
  245. if (frame.transparency) {
  246. act[frame.transIndex] = save;
  247. }
  248.  
  249. return currentImage;
  250. }
  251.  
  252. /**
  253. * Reads GIF image from stream
  254. *
  255. * @param is containing GIF file.
  256. * @return read status code (0 = no errors)
  257. */
  258. public int read(InputStream is, int contentLength) {
  259. long startTime = System.currentTimeMillis();
  260. if (is != null) {
  261. try {
  262. int capacity = (contentLength > 0) ? (contentLength + 4096) : 4096;
  263. ByteArrayOutputStream buffer = new ByteArrayOutputStream(capacity);
  264. int nRead;
  265. byte[] data = new byte[16384];
  266. while ((nRead = is.read(data, 0, data.length)) != -1) {
  267. buffer.write(data, 0, nRead);
  268. }
  269. buffer.flush();
  270.  
  271. read(buffer.toByteArray());
  272. } catch (IOException e) {
  273. Log.w(TAG, "Error reading data from stream", e);
  274. }
  275. } else {
  276. status = STATUS_OPEN_ERROR;
  277. }
  278.  
  279. try {
  280. is.close();
  281. } catch (Exception e) {
  282. Log.w(TAG, "Error closing stream", e);
  283. }
  284.  
  285. return status;
  286. }
  287.  
  288. /**
  289. * Reads GIF image from byte array
  290. *
  291. * @param data containing GIF file.
  292. * @return read status code (0 = no errors)
  293. */
  294. public int read(byte[] data) {
  295. init();
  296. if (data != null) {
  297. //Initiliaze the raw data buffer
  298. rawData = ByteBuffer.wrap(data);
  299. rawData.rewind();
  300. rawData.order(ByteOrder.LITTLE_ENDIAN);
  301.  
  302. readHeader();
  303. if (!err()) {
  304. readContents();
  305. if (frameCount < 0) {
  306. status = STATUS_FORMAT_ERROR;
  307. }
  308. }
  309. } else {
  310. status = STATUS_OPEN_ERROR;
  311. }
  312.  
  313. return status;
  314. }
  315.  
  316. /**
  317. * Creates new frame image from current data (and previous frames as specified by their disposition codes).
  318. */
  319. protected void setPixels(int frameIndex) {
  320. GifFrame currentFrame = frames.get(frameIndex);
  321. GifFrame previousFrame = null;
  322. int previousIndex = frameIndex - 1;
  323. if (previousIndex >= 0) {
  324. previousFrame = frames.get(previousIndex);
  325. }
  326.  
  327. // final location of blended pixels
  328. final int[] dest = mainScratch;
  329.  
  330. // fill in starting image contents based on last image's dispose code
  331. if (previousFrame != null && previousFrame.dispose > DISPOSAL_UNSPECIFIED) {
  332. if (previousFrame.dispose == DISPOSAL_NONE && currentImage != null) {
  333. // Start with the current image
  334. currentImage.getPixels(dest, 0, width, 0, 0, width, height);
  335. }
  336. if (previousFrame.dispose == DISPOSAL_BACKGROUND) {
  337. // Start with a canvas filled with the background color
  338. int c = 0;
  339. if (!currentFrame.transparency) {
  340. c = bgColor;
  341. }
  342. for (int i = 0; i < previousFrame.ih; i++) {
  343. int n1 = (previousFrame.iy + i) * width + previousFrame.ix;
  344. int n2 = n1 + previousFrame.iw;
  345. for (int k = n1; k < n2; k++) {
  346. dest[k] = c;
  347. }
  348. }
  349. }
  350. if (previousFrame.dispose == DISPOSAL_PREVIOUS && previousImage != null) {
  351. // Start with the previous frame
  352. previousImage.getPixels(dest, 0, width, 0, 0, width, height);
  353. }
  354. }
  355.  
  356. //Decode pixels for this frame into the global pixels[] scratch
  357. decodeBitmapData(currentFrame, mainPixels); // decode pixel data
  358.  
  359. // copy each source line to the appropriate place in the destination
  360. int pass = 1;
  361. int inc = 8;
  362. int iline = 0;
  363. for (int i = 0; i < currentFrame.ih; i++) {
  364. int line = i;
  365. if (currentFrame.interlace) {
  366. if (iline >= currentFrame.ih) {
  367. pass++;
  368. switch (pass) {
  369. case 2:
  370. iline = 4;
  371. break;
  372. case 3:
  373. iline = 2;
  374. inc = 4;
  375. break;
  376. case 4:
  377. iline = 1;
  378. inc = 2;
  379. break;
  380. default:
  381. break;
  382. }
  383. }
  384. line = iline;
  385. iline += inc;
  386. }
  387. line += currentFrame.iy;
  388. if (line < height) {
  389. int k = line * width;
  390. int dx = k + currentFrame.ix; // start of line in dest
  391. int dlim = dx + currentFrame.iw; // end of dest line
  392. if ((k + width) < dlim) {
  393. dlim = k + width; // past dest edge
  394. }
  395. int sx = i * currentFrame.iw; // start of line in source
  396. while (dx < dlim) {
  397. // map color and insert in destination
  398. int index = ((int) mainPixels[sx++]) & 0xff;
  399. int c = act[index];
  400. if (c != 0) {
  401. dest[dx] = c;
  402. }
  403. dx++;
  404. }
  405. }
  406. }
  407.  
  408. //Copy pixels into previous image
  409. currentImage.getPixels(copyScratch, 0, width, 0, 0, width, height);
  410. previousImage.setPixels(copyScratch, 0, width, 0, 0, width, height);
  411. //Set pixels for current image
  412. currentImage.setPixels(dest, 0, width, 0, 0, width, height);
  413. }
  414.  
  415. /**
  416. * Decodes LZW image data into pixel array. Adapted from John Cristy's BitmapMagick.
  417. */
  418. protected void decodeBitmapData(GifFrame frame, byte[] dstPixels) {
  419. long startTime = System.currentTimeMillis();
  420. long stepOne, stepTwo, stepThree;
  421. if (frame != null) {
  422. //Jump to the frame start position
  423. rawData.position(frame.bufferFrameStart);
  424. }
  425.  
  426. int nullCode = -1;
  427. int npix = (frame == null) ? width * height : frame.iw * frame.ih;
  428. int available, clear, code_mask, code_size, end_of_information, in_code, old_code, bits, code, count, i, datum, data_size, first, top, bi, pi;
  429.  
  430. if (dstPixels == null || dstPixels.length < npix) {
  431. dstPixels = new byte[npix]; // allocate new pixel array
  432. }
  433. if (prefix == null) {
  434. prefix = new short[MAX_STACK_SIZE];
  435. }
  436. if (suffix == null) {
  437. suffix = new byte[MAX_STACK_SIZE];
  438. }
  439. if (pixelStack == null) {
  440. pixelStack = new byte[MAX_STACK_SIZE + 1];
  441. }
  442.  
  443. // Initialize GIF data stream decoder.
  444. data_size = read();
  445. clear = 1 << data_size;
  446. end_of_information = clear + 1;
  447. available = clear + 2;
  448. old_code = nullCode;
  449. code_size = data_size + 1;
  450. code_mask = (1 << code_size) - 1;
  451. for (code = 0; code < clear; code++) {
  452. prefix[code] = 0; // XXX ArrayIndexOutOfBoundsException
  453. suffix[code] = (byte) code;
  454. }
  455.  
  456. // Decode GIF pixel stream.
  457. datum = bits = count = first = top = pi = bi = 0;
  458. for (i = 0; i < npix; ) {
  459. if (top == 0) {
  460. if (bits < code_size) {
  461. // Load bytes until there are enough bits for a code.
  462. if (count == 0) {
  463. // Read a new data block.
  464. count = readBlock();
  465. if (count <= 0) {
  466. break;
  467. }
  468. bi = 0;
  469. }
  470. datum += (((int) block[bi]) & 0xff) << bits;
  471. bits += 8;
  472. bi++;
  473. count--;
  474. continue;
  475. }
  476. // Get the next code.
  477. code = datum & code_mask;
  478. datum >>= code_size;
  479. bits -= code_size;
  480. // Interpret the code
  481. if ((code > available) || (code == end_of_information)) {
  482. break;
  483. }
  484. if (code == clear) {
  485. // Reset decoder.
  486. code_size = data_size + 1;
  487. code_mask = (1 << code_size) - 1;
  488. available = clear + 2;
  489. old_code = nullCode;
  490. continue;
  491. }
  492. if (old_code == nullCode) {
  493. pixelStack[top++] = suffix[code];
  494. old_code = code;
  495. first = code;
  496. continue;
  497. }
  498. in_code = code;
  499. if (code == available) {
  500. pixelStack[top++] = (byte) first;
  501. code = old_code;
  502. }
  503. while (code > clear) {
  504. pixelStack[top++] = suffix[code];
  505. code = prefix[code];
  506. }
  507. first = ((int) suffix[code]) & 0xff;
  508. // Add a new string to the string table,
  509. if (available >= MAX_STACK_SIZE) {
  510. break;
  511. }
  512. pixelStack[top++] = (byte) first;
  513. prefix[available] = (short) old_code;
  514. suffix[available] = (byte) first;
  515. available++;
  516. if (((available & code_mask) == 0) && (available < MAX_STACK_SIZE)) {
  517. code_size++;
  518. code_mask += available;
  519. }
  520. old_code = in_code;
  521. }
  522. // Pop a pixel off the pixel stack.
  523. top--;
  524. dstPixels[pi++] = pixelStack[top];
  525. i++;
  526. }
  527.  
  528. for (i = pi; i < npix; i++) {
  529. dstPixels[i] = 0; // clear missing pixels
  530. }
  531. }
  532.  
  533. /**
  534. * Returns true if an error was encountered during reading/decoding
  535. */
  536. protected boolean err() {
  537. return status != STATUS_OK;
  538. }
  539.  
  540. /**
  541. * Initializes or re-initializes reader
  542. */
  543. protected void init() {
  544. status = STATUS_OK;
  545. frameCount = 0;
  546. framePointer = -1;
  547. frames = new ArrayList<GifFrame>();
  548. gct = null;
  549. }
  550.  
  551. /**
  552. * Reads a single byte from the input stream.
  553. */
  554. protected int read() {
  555. int curByte = 0;
  556. try {
  557. curByte = (rawData.get() & 0xFF);
  558. } catch (Exception e) {
  559. status = STATUS_FORMAT_ERROR;
  560. }
  561. return curByte;
  562. }
  563.  
  564. /**
  565. * Reads next variable length block from input.
  566. *
  567. * @return number of bytes stored in "buffer"
  568. */
  569. protected int readBlock() {
  570. blockSize = read();
  571. int n = 0;
  572. if (blockSize > 0) {
  573. try {
  574. int count;
  575. while (n < blockSize) {
  576. count = blockSize - n;
  577. rawData.get(block, n, count);
  578.  
  579. n += count;
  580. }
  581. } catch (Exception e) {
  582. Log.w(TAG, "Error Reading Block", e);
  583. status = STATUS_FORMAT_ERROR;
  584. }
  585. }
  586. return n;
  587. }
  588.  
  589. /**
  590. * Reads color table as 256 RGB integer values
  591. *
  592. * @param ncolors int number of colors to read
  593. * @return int array containing 256 colors (packed ARGB with full alpha)
  594. */
  595. protected int[] readColorTable(int ncolors) {
  596. int nbytes = 3 * ncolors;
  597. int[] tab = null;
  598. byte[] c = new byte[nbytes];
  599.  
  600. try {
  601. rawData.get(c);
  602.  
  603. tab = new int[256]; // max size to avoid bounds checks
  604. int i = 0;
  605. int j = 0;
  606. while (i < ncolors) {
  607. int r = ((int) c[j++]) & 0xff;
  608. int g = ((int) c[j++]) & 0xff;
  609. int b = ((int) c[j++]) & 0xff;
  610. tab[i++] = 0xff000000 | (r << 16) | (g << 8) | b;
  611. }
  612. } catch (BufferUnderflowException e) {
  613. Log.w(TAG, "Format Error Reading Color Table", e);
  614. status = STATUS_FORMAT_ERROR;
  615. }
  616.  
  617. return tab;
  618. }
  619.  
  620. /**
  621. * Main file parser. Reads GIF content blocks.
  622. */
  623. protected void readContents() {
  624. // read GIF file content blocks
  625. boolean done = false;
  626. while (!(done || err())) {
  627. int code = read();
  628. switch (code) {
  629. case 0x2C: // image separator
  630. readBitmap();
  631. break;
  632. case 0x21: // extension
  633. code = read();
  634. switch (code) {
  635. case 0xf9: // graphics control extension
  636. //Start a new frame
  637. currentFrame = new GifFrame();
  638. readGraphicControlExt();
  639. break;
  640. case 0xff: // application extension
  641. readBlock();
  642. String app = "";
  643. for (int i = 0; i < 11; i++) {
  644. app += (char) block[i];
  645. }
  646. if (app.equals("NETSCAPE2.0")) {
  647. readNetscapeExt();
  648. } else {
  649. skip(); // don't care
  650. }
  651. break;
  652. case 0xfe:// comment extension
  653. skip();
  654. break;
  655. case 0x01:// plain text extension
  656. skip();
  657. break;
  658. default: // uninteresting extension
  659. skip();
  660. }
  661. break;
  662. case 0x3b: // terminator
  663. done = true;
  664. break;
  665. case 0x00: // bad byte, but keep going and see what happens break;
  666. default:
  667. status = STATUS_FORMAT_ERROR;
  668. }
  669. }
  670. }
  671.  
  672. /**
  673. * Reads GIF file header information.
  674. */
  675. protected void readHeader() {
  676. String id = "";
  677. for (int i = 0; i < 6; i++) {
  678. id += (char) read();
  679. }
  680. if (!id.startsWith("GIF")) {
  681. status = STATUS_FORMAT_ERROR;
  682. return;
  683. }
  684. readLSD();
  685. if (gctFlag && !err()) {
  686. gct = readColorTable(gctSize);
  687. bgColor = gct[bgIndex];
  688. }
  689. }
  690.  
  691. /**
  692. * Reads Graphics Control Extension values
  693. */
  694. protected void readGraphicControlExt() {
  695. read(); // block size
  696. int packed = read(); // packed fields
  697. currentFrame.dispose = (packed & 0x1c) >> 2; // disposal method
  698. if (currentFrame.dispose == 0) {
  699. currentFrame.dispose = 1; // elect to keep old image if discretionary
  700. }
  701. currentFrame.transparency = (packed & 1) != 0;
  702. currentFrame.delay = readShort() * 10; // delay in milliseconds
  703. currentFrame.transIndex = read(); // transparent color index
  704. read(); // block terminator
  705. }
  706.  
  707. /**
  708. * Reads next frame image
  709. */
  710. protected void readBitmap() {
  711. currentFrame.ix = readShort(); // (sub)image position & size
  712. currentFrame.iy = readShort();
  713. currentFrame.iw = readShort();
  714. currentFrame.ih = readShort();
  715.  
  716. int packed = read();
  717. lctFlag = (packed & 0x80) != 0; // 1 - local color table flag interlace
  718. lctSize = (int) Math.pow(2, (packed & 0x07) + 1);
  719. // 3 - sort flag
  720. // 4-5 - reserved lctSize = 2 << (packed & 7); // 6-8 - local color
  721. // table size
  722. currentFrame.interlace = (packed & 0x40) != 0;
  723. if (lctFlag) {
  724. currentFrame.lct = readColorTable(lctSize); // read table
  725. } else {
  726. currentFrame.lct = null; //No local color table
  727. }
  728.  
  729. currentFrame.bufferFrameStart = rawData.position(); //Save this as the decoding position pointer
  730.  
  731. decodeBitmapData(null, mainPixels); // false decode pixel data to advance buffer
  732. skip();
  733. if (err()) {
  734. return;
  735. }
  736.  
  737. frameCount++;
  738. frames.add(currentFrame); // add image to frame
  739. }
  740.  
  741. /**
  742. * Reads Logical Screen Descriptor
  743. */
  744. protected void readLSD() {
  745. // logical screen size
  746. width = readShort();
  747. height = readShort();
  748. // packed fields
  749. int packed = read();
  750. gctFlag = (packed & 0x80) != 0; // 1 : global color table flag
  751. // 2-4 : color resolution
  752. // 5 : gct sort flag
  753. gctSize = 2 << (packed & 7); // 6-8 : gct size
  754. bgIndex = read(); // background color index
  755. pixelAspect = read(); // pixel aspect ratio
  756.  
  757. //Now that we know the size, init scratch arrays
  758. mainPixels = new byte[width * height];
  759. mainScratch = new int[width * height];
  760. copyScratch = new int[width * height];
  761.  
  762. previousImage = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
  763. currentImage = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
  764. }
  765.  
  766. /**
  767. * Reads Netscape extenstion to obtain iteration count
  768. */
  769. protected void readNetscapeExt() {
  770. do {
  771. readBlock();
  772. if (block[0] == 1) {
  773. // loop count sub-block
  774. int b1 = ((int) block[1]) & 0xff;
  775. int b2 = ((int) block[2]) & 0xff;
  776. loopCount = (b2 << 8) | b1;
  777. }
  778. } while ((blockSize > 0) && !err());
  779. }
  780.  
  781. /**
  782. * Reads next 16-bit value, LSB first
  783. */
  784. protected int readShort() {
  785. // read 16-bit value
  786. return rawData.getShort();
  787. }
  788.  
  789. /**
  790. * Skips variable length blocks up to and including next zero length block.
  791. */
  792. protected void skip() {
  793. do {
  794. readBlock();
  795. } while ((blockSize > 0) && !err());
  796. }
  797. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement