PageRenderTime 30ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/j2se/JavaSE(LGame-0.3.2 &LAE-1.1)/LGame-0.3.2(OpenGL)/src/core/org/loon/framework/javase/game/action/sprite/GIFDecoder.java

http://loon-simple.googlecode.com/
Java | 607 lines | 500 code | 87 blank | 20 comment | 111 complexity | 4d92a4f53ef9f876d961a855681a5150 MD5 | raw file
  1. package org.loon.framework.javase.game.action.sprite;
  2. import java.awt.Color;
  3. import java.awt.Rectangle;
  4. import java.io.BufferedInputStream;
  5. import java.io.IOException;
  6. import java.io.InputStream;
  7. import java.util.ArrayList;
  8. import org.loon.framework.javase.game.core.geom.RectBox;
  9. import org.loon.framework.javase.game.core.graphics.LImage;
  10. import org.loon.framework.javase.game.core.graphics.device.LGraphics;
  11. import org.loon.framework.javase.game.core.resource.Resources;
  12. /**
  13. * Copyright 2008 - 2009
  14. *
  15. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  16. * use this file except in compliance with the License. You may obtain a copy of
  17. * the License at
  18. *
  19. * http://www.apache.org/licenses/LICENSE-2.0
  20. *
  21. * Unless required by applicable law or agreed to in writing, software
  22. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  23. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  24. * License for the specific language governing permissions and limitations under
  25. * the License.
  26. *
  27. * @project loonframework
  28. * @author chenpeng
  29. * @email??šceponline@yahoo.com.cn
  30. * @version 0.1
  31. */
  32. class GIFDecoder {
  33. public static final int STATUS_OK = 0;
  34. public static final int STATUS_FORMAT_ERROR = 1;
  35. public static final int STATUS_OPEN_ERROR = 2;
  36. protected BufferedInputStream in;
  37. protected int status;
  38. protected int width, height;
  39. protected boolean gctFlag;
  40. protected int gctSize;
  41. protected int loopCount = 1;
  42. protected int[] gct, lct, act;
  43. protected int bgIndex, bgColor, lastBgColor, pixelAspect;
  44. protected boolean lctFlag;
  45. protected boolean interlace;
  46. protected int lctSize;
  47. protected int ix, iy, iw, ih;
  48. protected Rectangle lastRect;
  49. protected LImage image;
  50. protected LImage lastImage;
  51. protected byte[] block = new byte[256];
  52. protected int blockSize = 0;
  53. protected int dispose = 0;
  54. protected int lastDispose = 0;
  55. protected boolean transparency = false;
  56. protected int delay = 0;
  57. protected int transIndex;
  58. protected static final int MaxStackSize = 4096;
  59. protected short[] prefix;
  60. protected byte[] suffix;
  61. protected byte[] pixelStack;
  62. protected byte[] pixels;
  63. protected ArrayList<GifFrame> frames;
  64. protected int frameCount;
  65. static class GifFrame {
  66. public GifFrame(LImage im, int del) {
  67. image = im;
  68. delay = del;
  69. }
  70. public LImage image;
  71. public int delay;
  72. }
  73. public int getDelay(int n) {
  74. delay = -1;
  75. if ((n >= 0) && (n < frameCount)) {
  76. delay = ((GifFrame) frames.get(n)).delay;
  77. }
  78. return delay;
  79. }
  80. public int getFrameCount() {
  81. return frameCount;
  82. }
  83. public LImage getImage() {
  84. return getFrame(0);
  85. }
  86. public int getLoopCount() {
  87. return loopCount;
  88. }
  89. protected void setPixels() {
  90. int[] dest = image.getPixels();
  91. if (lastDispose > 0) {
  92. if (lastDispose == 3) {
  93. int n = frameCount - 2;
  94. if (n > 0) {
  95. lastImage = getFrame(n - 1);
  96. } else {
  97. lastImage = null;
  98. }
  99. }
  100. if (lastImage != null) {
  101. int[] prev = lastImage.getPixels();
  102. image.setPixels(prev, width, height);
  103. if (lastDispose == 2) {
  104. LGraphics g = image.getLGraphics();
  105. Color c = null;
  106. if (transparency) {
  107. c = new Color(0, 0, 0, 0);
  108. } else {
  109. c = new Color(lastBgColor);
  110. }
  111. g.setColor(c);
  112. g.fill(lastRect);
  113. g.dispose();
  114. }
  115. }
  116. }
  117. int pass = 1;
  118. int inc = 8;
  119. int iline = 0;
  120. for (int i = 0; i < ih; i++) {
  121. int line = i;
  122. if (interlace) {
  123. if (iline >= ih) {
  124. pass++;
  125. switch (pass) {
  126. case 2:
  127. iline = 4;
  128. break;
  129. case 3:
  130. iline = 2;
  131. inc = 4;
  132. break;
  133. case 4:
  134. iline = 1;
  135. inc = 2;
  136. }
  137. }
  138. line = iline;
  139. iline += inc;
  140. }
  141. line += iy;
  142. if (line < height) {
  143. int k = line * width;
  144. int dx = k + ix;
  145. int dlim = dx + iw;
  146. if ((k + width) < dlim) {
  147. dlim = k + width;
  148. }
  149. int sx = i * iw;
  150. while (dx < dlim) {
  151. int index = ((int) pixels[sx++]) & 0xff;
  152. int c = act[index];
  153. if (c != 0) {
  154. dest[dx] = c;
  155. }
  156. dx++;
  157. }
  158. }
  159. }
  160. image.setPixels(dest, width, height);
  161. }
  162. public LImage getFrame(int n) {
  163. LImage im = null;
  164. if ((n >= 0) && (n < frameCount)) {
  165. im = ((GifFrame) frames.get(n)).image;
  166. }
  167. return im;
  168. }
  169. public RectBox getFrameSize() {
  170. return new RectBox(0, 0, width, height);
  171. }
  172. public int read(BufferedInputStream is) {
  173. init();
  174. if (is != null) {
  175. in = is;
  176. readHeader();
  177. if (!err()) {
  178. readContents();
  179. if (frameCount < 0) {
  180. status = STATUS_FORMAT_ERROR;
  181. }
  182. }
  183. } else {
  184. status = STATUS_OPEN_ERROR;
  185. }
  186. try {
  187. is.close();
  188. } catch (IOException e) {
  189. }
  190. return status;
  191. }
  192. public int read(InputStream is) {
  193. init();
  194. if (is != null) {
  195. if (!(is instanceof BufferedInputStream)) {
  196. is = new BufferedInputStream(is);
  197. }
  198. in = (BufferedInputStream) is;
  199. readHeader();
  200. if (!err()) {
  201. readContents();
  202. if (frameCount < 0) {
  203. status = STATUS_FORMAT_ERROR;
  204. }
  205. }
  206. } else {
  207. status = STATUS_OPEN_ERROR;
  208. }
  209. try {
  210. is.close();
  211. } catch (IOException e) {
  212. }
  213. return status;
  214. }
  215. public int read(String fileName) {
  216. status = STATUS_OK;
  217. InputStream in = Resources.getResourceAsStream(fileName);
  218. if (in != null) {
  219. status = read(in);
  220. } else {
  221. status = STATUS_OPEN_ERROR;
  222. }
  223. return status;
  224. }
  225. protected void decodeImageData() {
  226. int NullCode = -1;
  227. int npix = iw * ih;
  228. 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;
  229. if ((pixels == null) || (pixels.length < npix)) {
  230. pixels = new byte[npix];
  231. }
  232. if (prefix == null)
  233. prefix = new short[MaxStackSize];
  234. if (suffix == null)
  235. suffix = new byte[MaxStackSize];
  236. if (pixelStack == null)
  237. pixelStack = new byte[MaxStackSize + 1];
  238. data_size = read();
  239. clear = 1 << data_size;
  240. end_of_information = clear + 1;
  241. available = clear + 2;
  242. old_code = NullCode;
  243. code_size = data_size + 1;
  244. code_mask = (1 << code_size) - 1;
  245. for (code = 0; code < clear; code++) {
  246. prefix[code] = 0;
  247. suffix[code] = (byte) code;
  248. }
  249. datum = bits = count = first = top = pi = bi = 0;
  250. for (i = 0; i < npix;) {
  251. if (top == 0) {
  252. if (bits < code_size) {
  253. if (count == 0) {
  254. count = readBlock();
  255. if (count <= 0)
  256. break;
  257. bi = 0;
  258. }
  259. datum += (((int) block[bi]) & 0xff) << bits;
  260. bits += 8;
  261. bi++;
  262. count--;
  263. continue;
  264. }
  265. code = datum & code_mask;
  266. datum >>= code_size;
  267. bits -= code_size;
  268. if ((code > available) || (code == end_of_information))
  269. break;
  270. if (code == clear) {
  271. code_size = data_size + 1;
  272. code_mask = (1 << code_size) - 1;
  273. available = clear + 2;
  274. old_code = NullCode;
  275. continue;
  276. }
  277. if (old_code == NullCode) {
  278. pixelStack[top++] = suffix[code];
  279. old_code = code;
  280. first = code;
  281. continue;
  282. }
  283. in_code = code;
  284. if (code == available) {
  285. pixelStack[top++] = (byte) first;
  286. code = old_code;
  287. }
  288. while (code > clear) {
  289. pixelStack[top++] = suffix[code];
  290. code = prefix[code];
  291. }
  292. first = ((int) suffix[code]) & 0xff;
  293. if (available >= MaxStackSize)
  294. break;
  295. pixelStack[top++] = (byte) first;
  296. prefix[available] = (short) old_code;
  297. suffix[available] = (byte) first;
  298. available++;
  299. if (((available & code_mask) == 0)
  300. && (available < MaxStackSize)) {
  301. code_size++;
  302. code_mask += available;
  303. }
  304. old_code = in_code;
  305. }
  306. top--;
  307. pixels[pi++] = pixelStack[top];
  308. i++;
  309. }
  310. for (i = pi; i < npix; i++) {
  311. pixels[i] = 0;
  312. }
  313. }
  314. protected boolean err() {
  315. return status != STATUS_OK;
  316. }
  317. protected void init() {
  318. status = STATUS_OK;
  319. frameCount = 0;
  320. frames = new ArrayList<GifFrame>();
  321. gct = null;
  322. lct = null;
  323. }
  324. protected int read() {
  325. int curByte = 0;
  326. try {
  327. curByte = in.read();
  328. } catch (IOException e) {
  329. status = STATUS_FORMAT_ERROR;
  330. }
  331. return curByte;
  332. }
  333. protected int readBlock() {
  334. blockSize = read();
  335. int n = 0;
  336. if (blockSize > 0) {
  337. try {
  338. int count = 0;
  339. while (n < blockSize) {
  340. count = in.read(block, n, blockSize - n);
  341. if (count == -1)
  342. break;
  343. n += count;
  344. }
  345. } catch (IOException e) {
  346. }
  347. if (n < blockSize) {
  348. status = STATUS_FORMAT_ERROR;
  349. }
  350. }
  351. return n;
  352. }
  353. protected int[] readColorTable(int ncolors) {
  354. int nbytes = 3 * ncolors;
  355. int[] tab = null;
  356. byte[] c = new byte[nbytes];
  357. int n = 0;
  358. try {
  359. n = in.read(c);
  360. } catch (IOException e) {
  361. }
  362. if (n < nbytes) {
  363. status = STATUS_FORMAT_ERROR;
  364. } else {
  365. tab = new int[256];
  366. int i = 0;
  367. int j = 0;
  368. while (i < ncolors) {
  369. int r = ((int) c[j++]) & 0xff;
  370. int g = ((int) c[j++]) & 0xff;
  371. int b = ((int) c[j++]) & 0xff;
  372. tab[i++] = 0xff000000 | (r << 16) | (g << 8) | b;
  373. }
  374. }
  375. return tab;
  376. }
  377. protected void readContents() {
  378. boolean done = false;
  379. while (!(done || err())) {
  380. int code = read();
  381. switch (code) {
  382. case 0x2C:
  383. readImage();
  384. break;
  385. case 0x21:
  386. code = read();
  387. switch (code) {
  388. case 0xf9:
  389. readGraphicControlExt();
  390. break;
  391. case 0xff:
  392. readBlock();
  393. String app = "";
  394. for (int i = 0; i < 11; i++) {
  395. app += (char) block[i];
  396. }
  397. if (app.equals("NETSCAPE2.0")) {
  398. readNetscapeExt();
  399. } else
  400. skip();
  401. break;
  402. default:
  403. skip();
  404. }
  405. break;
  406. case 0x3b:
  407. done = true;
  408. break;
  409. case 0x00:
  410. break;
  411. default:
  412. status = STATUS_FORMAT_ERROR;
  413. }
  414. }
  415. }
  416. protected void readGraphicControlExt() {
  417. read();
  418. int packed = read();
  419. dispose = (packed & 0x1c) >> 2;
  420. if (dispose == 0) {
  421. dispose = 1;
  422. }
  423. transparency = (packed & 1) != 0;
  424. delay = readShort() * 10;
  425. transIndex = read();
  426. read();
  427. }
  428. protected void readHeader() {
  429. String id = "";
  430. for (int i = 0; i < 6; i++) {
  431. id += (char) read();
  432. }
  433. if (!id.startsWith("GIF")) {
  434. status = STATUS_FORMAT_ERROR;
  435. return;
  436. }
  437. readLSD();
  438. if (gctFlag && !err()) {
  439. gct = readColorTable(gctSize);
  440. bgColor = gct[bgIndex];
  441. }
  442. }
  443. protected void readImage() {
  444. ix = readShort();
  445. iy = readShort();
  446. iw = readShort();
  447. ih = readShort();
  448. int packed = read();
  449. lctFlag = (packed & 0x80) != 0;
  450. interlace = (packed & 0x40) != 0;
  451. lctSize = 2 << (packed & 7);
  452. if (lctFlag) {
  453. lct = readColorTable(lctSize);
  454. act = lct;
  455. } else {
  456. act = gct;
  457. if (bgIndex == transIndex)
  458. bgColor = 0;
  459. }
  460. int save = 0;
  461. if (transparency) {
  462. save = act[transIndex];
  463. act[transIndex] = 0;
  464. }
  465. if (act == null) {
  466. status = STATUS_FORMAT_ERROR;
  467. }
  468. if (err())
  469. return;
  470. decodeImageData();
  471. skip();
  472. if (err())
  473. return;
  474. frameCount++;
  475. image = new LImage(width, height, true);
  476. setPixels();
  477. frames.add(new GifFrame(image, delay));
  478. if (transparency) {
  479. act[transIndex] = save;
  480. }
  481. resetFrame();
  482. }
  483. protected void readLSD() {
  484. width = readShort();
  485. height = readShort();
  486. int packed = read();
  487. gctFlag = (packed & 0x80) != 0;
  488. gctSize = 2 << (packed & 7);
  489. bgIndex = read();
  490. pixelAspect = read();
  491. }
  492. protected void readNetscapeExt() {
  493. do {
  494. readBlock();
  495. if (block[0] == 1) {
  496. int b1 = ((int) block[1]) & 0xff;
  497. int b2 = ((int) block[2]) & 0xff;
  498. loopCount = (b2 << 8) | b1;
  499. }
  500. } while ((blockSize > 0) && !err());
  501. }
  502. protected int readShort() {
  503. return read() | (read() << 8);
  504. }
  505. protected void resetFrame() {
  506. lastDispose = dispose;
  507. lastRect = new Rectangle(ix, iy, iw, ih);
  508. lastImage = image;
  509. lastBgColor = bgColor;
  510. dispose = 0;
  511. transparency = false;
  512. delay = 0;
  513. lct = null;
  514. }
  515. protected void skip() {
  516. do {
  517. readBlock();
  518. } while ((blockSize > 0) && !err());
  519. }
  520. }