<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://www.jexp.ru/index.php?action=history&amp;feed=atom&amp;title=Java%2F2D_Graphics_GUI%2FPsd</id>
		<title>Java/2D Graphics GUI/Psd - История изменений</title>
		<link rel="self" type="application/atom+xml" href="http://www.jexp.ru/index.php?action=history&amp;feed=atom&amp;title=Java%2F2D_Graphics_GUI%2FPsd"/>
		<link rel="alternate" type="text/html" href="http://www.jexp.ru/index.php?title=Java/2D_Graphics_GUI/Psd&amp;action=history"/>
		<updated>2026-04-18T23:10:53Z</updated>
		<subtitle>История изменений этой страницы в вики</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://www.jexp.ru/index.php?title=Java/2D_Graphics_GUI/Psd&amp;diff=8157&amp;oldid=prev</id>
		<title>Admin: 1 версия</title>
		<link rel="alternate" type="text/html" href="http://www.jexp.ru/index.php?title=Java/2D_Graphics_GUI/Psd&amp;diff=8157&amp;oldid=prev"/>
				<updated>2010-06-01T06:55:26Z</updated>
		
		<summary type="html">&lt;p&gt;1 версия&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr style=&quot;vertical-align: top;&quot; lang=&quot;ru&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: white; color:black; text-align: center;&quot;&gt;← Предыдущая&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: white; color:black; text-align: center;&quot;&gt;Версия 06:55, 1 июня 2010&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; style=&quot;text-align: center;&quot; lang=&quot;ru&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(нет различий)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>http://www.jexp.ru/index.php?title=Java/2D_Graphics_GUI/Psd&amp;diff=8156&amp;oldid=prev</id>
		<title> в 18:01, 31 мая 2010</title>
		<link rel="alternate" type="text/html" href="http://www.jexp.ru/index.php?title=Java/2D_Graphics_GUI/Psd&amp;diff=8156&amp;oldid=prev"/>
				<updated>2010-05-31T18:01:46Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== Decodes a PhotoShop (.psd) file into one or more frames ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
import java.awt.Dimension;&lt;br /&gt;
import java.awt.Graphics2D;&lt;br /&gt;
import java.awt.Point;&lt;br /&gt;
import java.awt.image.BufferedImage;&lt;br /&gt;
import java.awt.image.DataBufferInt;&lt;br /&gt;
import java.io.BufferedInputStream;&lt;br /&gt;
import java.io.FileInputStream;&lt;br /&gt;
import java.io.IOException;&lt;br /&gt;
import java.io.InputStream;&lt;br /&gt;
import java.net.URL;&lt;br /&gt;
/**&lt;br /&gt;
 * Class PSDReader - Decodes a PhotoShop (.psd) file into one or more frames.&lt;br /&gt;
 * Supports uncompressed or RLE-compressed RGB files only. Each layer may be&lt;br /&gt;
 * retrieved as a full frame BufferedImage, or as a smaller image with an offset&lt;br /&gt;
 * if the layer does not occupy the full frame size. Transparency in the&lt;br /&gt;
 * original psd file is preserved in the returned BufferedImage&amp;quot;s. Does not&lt;br /&gt;
 * support additional features in PS versions higher than 3.0. Example: &amp;lt;br&amp;gt;&lt;br /&gt;
 * &lt;br /&gt;
 * &amp;lt;pre&amp;gt;&lt;br /&gt;
 * PSDReader r = new PSDReader();&lt;br /&gt;
 * r.read(&amp;amp;quot;sample.psd&amp;amp;quot;);&lt;br /&gt;
 * int n = r.getFrameCount();&lt;br /&gt;
 * for (int i = 0; i &amp;amp;lt; n; i++) {&lt;br /&gt;
 *   BufferedImage image = r.getLayer(i);&lt;br /&gt;
 *   Point offset = r.getLayerOffset(i);&lt;br /&gt;
 *   // do something with image&lt;br /&gt;
 * }&lt;br /&gt;
 * &amp;lt;/pre&amp;gt;&lt;br /&gt;
 * &lt;br /&gt;
 * No copyright asserted on the source code of this class. May be used for any&lt;br /&gt;
 * purpose. Please forward any corrections to kweiner@fmsware.ru.&lt;br /&gt;
 * &lt;br /&gt;
 * @author Kevin Weiner, FM Software.&lt;br /&gt;
 * @version 1.1 January 2004 [bug fix; add RLE support]&lt;br /&gt;
 * &lt;br /&gt;
 */&lt;br /&gt;
public class PSDReader {&lt;br /&gt;
  /**&lt;br /&gt;
   * File read status: No errors.&lt;br /&gt;
   */&lt;br /&gt;
  public static final int STATUS_OK = 0;&lt;br /&gt;
  /**&lt;br /&gt;
   * File read status: Error decoding file (may be partially decoded)&lt;br /&gt;
   */&lt;br /&gt;
  public static final int STATUS_FORMAT_ERROR = 1;&lt;br /&gt;
  /**&lt;br /&gt;
   * File read status: Unable to open source.&lt;br /&gt;
   */&lt;br /&gt;
  public static final int STATUS_OPEN_ERROR = 2;&lt;br /&gt;
  /**&lt;br /&gt;
   * File read status: Unsupported format&lt;br /&gt;
   */&lt;br /&gt;
  public static final int STATUS_UNSUPPORTED = 3;&lt;br /&gt;
  public static int ImageType = BufferedImage.TYPE_INT_ARGB;&lt;br /&gt;
  protected BufferedInputStream input;&lt;br /&gt;
  protected int frameCount;&lt;br /&gt;
  protected BufferedImage[] frames;&lt;br /&gt;
  protected int status = 0;&lt;br /&gt;
  protected int nChan;&lt;br /&gt;
  protected int width;&lt;br /&gt;
  protected int height;&lt;br /&gt;
  protected int nLayers;&lt;br /&gt;
  protected int miscLen;&lt;br /&gt;
  protected boolean hasLayers;&lt;br /&gt;
  protected LayerInfo[] layers;&lt;br /&gt;
  protected short[] lineLengths;&lt;br /&gt;
  protected int lineIndex;&lt;br /&gt;
  protected boolean rleEncoded;&lt;br /&gt;
  protected class LayerInfo {&lt;br /&gt;
    int x, y, w, h;&lt;br /&gt;
    int nChan;&lt;br /&gt;
    int[] chanID;&lt;br /&gt;
    int alpha;&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * Gets the number of layers read from file.&lt;br /&gt;
   * &lt;br /&gt;
   * @return frame count&lt;br /&gt;
   */&lt;br /&gt;
  public int getFrameCount() {&lt;br /&gt;
    return frameCount;&lt;br /&gt;
  }&lt;br /&gt;
  protected void setInput(InputStream stream) {&lt;br /&gt;
    // open input stream&lt;br /&gt;
    init();&lt;br /&gt;
    if (stream == null) {&lt;br /&gt;
      status = STATUS_OPEN_ERROR;&lt;br /&gt;
    } else {&lt;br /&gt;
      if (stream instanceof BufferedInputStream)&lt;br /&gt;
        input = (BufferedInputStream) stream;&lt;br /&gt;
      else&lt;br /&gt;
        input = new BufferedInputStream(stream);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  protected void setInput(String name) {&lt;br /&gt;
    // open input file&lt;br /&gt;
    init();&lt;br /&gt;
    try {&lt;br /&gt;
      name = name.trim();&lt;br /&gt;
      if (name.startsWith(&amp;quot;file:&amp;quot;)) {&lt;br /&gt;
        name = name.substring(5);&lt;br /&gt;
        while (name.startsWith(&amp;quot;/&amp;quot;))&lt;br /&gt;
          name = name.substring(1);&lt;br /&gt;
      }&lt;br /&gt;
      if (name.indexOf(&amp;quot;://&amp;quot;) &amp;gt; 0) {&lt;br /&gt;
        URL url = new URL(name);&lt;br /&gt;
        input = new BufferedInputStream(url.openStream());&lt;br /&gt;
      } else {&lt;br /&gt;
        input = new BufferedInputStream(new FileInputStream(name));&lt;br /&gt;
      }&lt;br /&gt;
    } catch (IOException e) {&lt;br /&gt;
      status = STATUS_OPEN_ERROR;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * Gets display duration for specified frame. Always returns 0.&lt;br /&gt;
   * &lt;br /&gt;
   */&lt;br /&gt;
  public int getDelay(int forFrame) {&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * Gets the image contents of frame n. Note that this expands the image to the&lt;br /&gt;
   * full frame size (if the layer was smaller) and any subsequent use of&lt;br /&gt;
   * getLayer() will return the full image.&lt;br /&gt;
   * &lt;br /&gt;
   * @return BufferedImage representation of frame, or null if n is invalid.&lt;br /&gt;
   */&lt;br /&gt;
  public BufferedImage getFrame(int n) {&lt;br /&gt;
    BufferedImage im = null;&lt;br /&gt;
    if ((n &amp;gt;= 0) &amp;amp;&amp;amp; (n &amp;lt; nLayers)) {&lt;br /&gt;
      im = frames[n];&lt;br /&gt;
      LayerInfo info = layers[n];&lt;br /&gt;
      if ((info.w != width) || (info.h != height)) {&lt;br /&gt;
        BufferedImage temp = new BufferedImage(width, height, ImageType);&lt;br /&gt;
        Graphics2D gc = temp.createGraphics();&lt;br /&gt;
        gc.drawImage(im, info.x, info.y, null);&lt;br /&gt;
        gc.dispose();&lt;br /&gt;
        im = temp;&lt;br /&gt;
        frames[n] = im;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    return im;&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * Gets maximum image size. Individual layers may be smaller.&lt;br /&gt;
   * &lt;br /&gt;
   * @return maximum image dimensions&lt;br /&gt;
   */&lt;br /&gt;
  public Dimension getFrameSize() {&lt;br /&gt;
    return new Dimension(width, height);&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * Gets the first (or only) image read.&lt;br /&gt;
   * &lt;br /&gt;
   * @return BufferedImage containing first frame, or null if none.&lt;br /&gt;
   */&lt;br /&gt;
  public BufferedImage getImage() {&lt;br /&gt;
    return getFrame(0);&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * Gets the image contents of layer n. May be smaller than full frame size -&lt;br /&gt;
   * use getFrameOffset() to obtain position of subimage within main image area.&lt;br /&gt;
   * &lt;br /&gt;
   * @return BufferedImage representation of layer, or null if n is invalid.&lt;br /&gt;
   */&lt;br /&gt;
  public BufferedImage getLayer(int n) {&lt;br /&gt;
    BufferedImage im = null;&lt;br /&gt;
    if ((n &amp;gt;= 0) &amp;amp;&amp;amp; (n &amp;lt; nLayers)) {&lt;br /&gt;
      im = frames[n];&lt;br /&gt;
    }&lt;br /&gt;
    return im;&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * Gets the subimage offset of layer n if it is smaller than the full frame&lt;br /&gt;
   * size.&lt;br /&gt;
   * &lt;br /&gt;
   * @return Point indicating offset from upper left corner of frame.&lt;br /&gt;
   */&lt;br /&gt;
  public Point getLayerOffset(int n) {&lt;br /&gt;
    Point p = null;&lt;br /&gt;
    if ((n &amp;gt;= 0) &amp;amp;&amp;amp; (n &amp;lt; nLayers)) {&lt;br /&gt;
      int x = layers[n].x;&lt;br /&gt;
      int y = layers[n].y;&lt;br /&gt;
      p = new Point(x, y);&lt;br /&gt;
    }&lt;br /&gt;
    if (p == null) {&lt;br /&gt;
      p = new Point(0, 0);&lt;br /&gt;
    }&lt;br /&gt;
    return p;&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * Reads PhotoShop layers from stream.&lt;br /&gt;
   * &lt;br /&gt;
   * @param InputStream&lt;br /&gt;
   *          in PhotoShop format.&lt;br /&gt;
   * @return read status code (0 = no errors)&lt;br /&gt;
   */&lt;br /&gt;
  public int read(InputStream stream) {&lt;br /&gt;
    setInput(stream);&lt;br /&gt;
    process();&lt;br /&gt;
    return status;&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * Reads PhotoShop file from specified source (file or URL string)&lt;br /&gt;
   * &lt;br /&gt;
   * @param name&lt;br /&gt;
   *          String containing source&lt;br /&gt;
   * @return read status code (0 = no errors)&lt;br /&gt;
   */&lt;br /&gt;
  public int read(String name) {&lt;br /&gt;
    setInput(name);&lt;br /&gt;
    process();&lt;br /&gt;
    return status;&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * Closes input stream and discards contents of all frames.&lt;br /&gt;
   * &lt;br /&gt;
   */&lt;br /&gt;
  public void reset() {&lt;br /&gt;
    init();&lt;br /&gt;
  }&lt;br /&gt;
  protected void close() {&lt;br /&gt;
    if (input != null) {&lt;br /&gt;
      try {&lt;br /&gt;
        input.close();&lt;br /&gt;
      } catch (Exception e) {&lt;br /&gt;
      }&lt;br /&gt;
      input = null;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  protected boolean err() {&lt;br /&gt;
    return status != STATUS_OK;&lt;br /&gt;
  }&lt;br /&gt;
  protected byte[] fillBytes(int size, int value) {&lt;br /&gt;
    // create byte array filled with given value&lt;br /&gt;
    byte[] b = new byte[size];&lt;br /&gt;
    if (value != 0) {&lt;br /&gt;
      byte v = (byte) value;&lt;br /&gt;
      for (int i = 0; i &amp;lt; size; i++) {&lt;br /&gt;
        b[i] = v;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    return b;&lt;br /&gt;
  }&lt;br /&gt;
  protected void init() {&lt;br /&gt;
    close();&lt;br /&gt;
    frameCount = 0;&lt;br /&gt;
    frames = null;&lt;br /&gt;
    layers = null;&lt;br /&gt;
    hasLayers = true;&lt;br /&gt;
    status = STATUS_OK;&lt;br /&gt;
  }&lt;br /&gt;
  protected void makeDummyLayer() {&lt;br /&gt;
    // creat dummy layer for non-layered image&lt;br /&gt;
    rleEncoded = readShort() == 1;&lt;br /&gt;
    hasLayers = false;&lt;br /&gt;
    nLayers = 1;&lt;br /&gt;
    layers = new LayerInfo[1];&lt;br /&gt;
    LayerInfo layer = new LayerInfo();&lt;br /&gt;
    layers[0] = layer;&lt;br /&gt;
    layer.h = height;&lt;br /&gt;
    layer.w = width;&lt;br /&gt;
    int nc = Math.min(nChan, 4);&lt;br /&gt;
    if (rleEncoded) {&lt;br /&gt;
      // get list of rle encoded line lengths for all channels&lt;br /&gt;
      readLineLengths(height * nc);&lt;br /&gt;
    }&lt;br /&gt;
    layer.nChan = nc;&lt;br /&gt;
    layer.chanID = new int[nc];&lt;br /&gt;
    for (int i = 0; i &amp;lt; nc; i++) {&lt;br /&gt;
      int id = i;&lt;br /&gt;
      if (i == 3)&lt;br /&gt;
        id = -1;&lt;br /&gt;
      layer.chanID[i] = id;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  protected void readLineLengths(int nLines) {&lt;br /&gt;
    // read list of rle encoded line lengths&lt;br /&gt;
    lineLengths = new short[nLines];&lt;br /&gt;
    for (int i = 0; i &amp;lt; nLines; i++) {&lt;br /&gt;
      lineLengths[i] = readShort();&lt;br /&gt;
    }&lt;br /&gt;
    lineIndex = 0;&lt;br /&gt;
  }&lt;br /&gt;
  protected BufferedImage makeImage(int w, int h, byte[] r, byte[] g, byte[] b, byte[] a) {&lt;br /&gt;
    // create image from given plane data&lt;br /&gt;
    BufferedImage im = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);&lt;br /&gt;
    int[] data = ((DataBufferInt) im.getRaster().getDataBuffer()).getData();&lt;br /&gt;
    int n = w * h;&lt;br /&gt;
    int j = 0;&lt;br /&gt;
    while (j &amp;lt; n) {&lt;br /&gt;
      try {&lt;br /&gt;
        int ac = a[j] &amp;amp; 0xff;&lt;br /&gt;
        int rc = r[j] &amp;amp; 0xff;&lt;br /&gt;
        int gc = g[j] &amp;amp; 0xff;&lt;br /&gt;
        int bc = b[j] &amp;amp; 0xff;&lt;br /&gt;
        data[j] = (((((ac &amp;lt;&amp;lt; 8) | rc) &amp;lt;&amp;lt; 8) | gc) &amp;lt;&amp;lt; 8) | bc;&lt;br /&gt;
      } catch (Exception e) {&lt;br /&gt;
      }&lt;br /&gt;
      j++;&lt;br /&gt;
    }&lt;br /&gt;
    return im;&lt;br /&gt;
  }&lt;br /&gt;
  protected void process() {&lt;br /&gt;
    // decode PSD file&lt;br /&gt;
    if (err())&lt;br /&gt;
      return;&lt;br /&gt;
    readHeader();&lt;br /&gt;
    if (err())&lt;br /&gt;
      return;&lt;br /&gt;
    readLayerInfo();&lt;br /&gt;
    if (err())&lt;br /&gt;
      return;&lt;br /&gt;
    if (nLayers == 0) {&lt;br /&gt;
      makeDummyLayer();&lt;br /&gt;
      if (err())&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    readLayers();&lt;br /&gt;
  }&lt;br /&gt;
  protected int readByte() {&lt;br /&gt;
    // read single byte from input&lt;br /&gt;
    int curByte = 0;&lt;br /&gt;
    try {&lt;br /&gt;
      curByte = input.read();&lt;br /&gt;
    } catch (IOException e) {&lt;br /&gt;
      status = STATUS_FORMAT_ERROR;&lt;br /&gt;
    }&lt;br /&gt;
    return curByte;&lt;br /&gt;
  }&lt;br /&gt;
  protected int readBytes(byte[] bytes, int n) {&lt;br /&gt;
    // read multiple bytes from input&lt;br /&gt;
    if (bytes == null)&lt;br /&gt;
      return 0;&lt;br /&gt;
    int r = 0;&lt;br /&gt;
    try {&lt;br /&gt;
      r = input.read(bytes, 0, n);&lt;br /&gt;
    } catch (IOException e) {&lt;br /&gt;
      status = STATUS_FORMAT_ERROR;&lt;br /&gt;
    }&lt;br /&gt;
    if (r &amp;lt; n) {&lt;br /&gt;
      status = STATUS_FORMAT_ERROR;&lt;br /&gt;
    }&lt;br /&gt;
    return r;&lt;br /&gt;
  }&lt;br /&gt;
  protected void readHeader() {&lt;br /&gt;
    // read PSD header info&lt;br /&gt;
    String sig = readString(4);&lt;br /&gt;
    int ver = readShort();&lt;br /&gt;
    skipBytes(6);&lt;br /&gt;
    nChan = readShort();&lt;br /&gt;
    height = readInt();&lt;br /&gt;
    width = readInt();&lt;br /&gt;
    int depth = readShort();&lt;br /&gt;
    int mode = readShort();&lt;br /&gt;
    int cmLen = readInt();&lt;br /&gt;
    skipBytes(cmLen);&lt;br /&gt;
    int imResLen = readInt();&lt;br /&gt;
    skipBytes(imResLen);&lt;br /&gt;
    // require 8-bit RGB data&lt;br /&gt;
    if ((!sig.equals(&amp;quot;8BPS&amp;quot;)) || (ver != 1)) {&lt;br /&gt;
      status = STATUS_FORMAT_ERROR;&lt;br /&gt;
    } else if ((depth != 8) || (mode != 3)) {&lt;br /&gt;
      status = STATUS_UNSUPPORTED;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  protected int readInt() {&lt;br /&gt;
    // read big-endian 32-bit integer&lt;br /&gt;
    return (((((readByte() &amp;lt;&amp;lt; 8) | readByte()) &amp;lt;&amp;lt; 8) | readByte()) &amp;lt;&amp;lt; 8) | readByte();&lt;br /&gt;
  }&lt;br /&gt;
  protected void readLayerInfo() {&lt;br /&gt;
    // read layer header info&lt;br /&gt;
    miscLen = readInt();&lt;br /&gt;
    if (miscLen == 0) {&lt;br /&gt;
      return; // no layers, only base image&lt;br /&gt;
    }&lt;br /&gt;
    int layerInfoLen = readInt();&lt;br /&gt;
    nLayers = readShort();&lt;br /&gt;
    if (nLayers &amp;gt; 0) {&lt;br /&gt;
      layers = new LayerInfo[nLayers];&lt;br /&gt;
    }&lt;br /&gt;
    for (int i = 0; i &amp;lt; nLayers; i++) {&lt;br /&gt;
      LayerInfo info = new LayerInfo();&lt;br /&gt;
      layers[i] = info;&lt;br /&gt;
      info.y = readInt();&lt;br /&gt;
      info.x = readInt();&lt;br /&gt;
      info.h = readInt() - info.y;&lt;br /&gt;
      info.w = readInt() - info.x;&lt;br /&gt;
      info.nChan = readShort();&lt;br /&gt;
      info.chanID = new int[info.nChan];&lt;br /&gt;
      for (int j = 0; j &amp;lt; info.nChan; j++) {&lt;br /&gt;
        int id = readShort();&lt;br /&gt;
        int size = readInt();&lt;br /&gt;
        info.chanID[j] = id;&lt;br /&gt;
      }&lt;br /&gt;
      String s = readString(4);&lt;br /&gt;
      if (!s.equals(&amp;quot;8BIM&amp;quot;)) {&lt;br /&gt;
        status = STATUS_FORMAT_ERROR;&lt;br /&gt;
        return;&lt;br /&gt;
      }&lt;br /&gt;
      skipBytes(4); // blend mode&lt;br /&gt;
      info.alpha = readByte();&lt;br /&gt;
      int clipping = readByte();&lt;br /&gt;
      int flags = readByte();&lt;br /&gt;
      readByte(); // filler&lt;br /&gt;
      int extraSize = readInt();&lt;br /&gt;
      skipBytes(extraSize);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  protected void readLayers() {&lt;br /&gt;
    // read and convert each layer to BufferedImage&lt;br /&gt;
    frameCount = nLayers;&lt;br /&gt;
    frames = new BufferedImage[nLayers];&lt;br /&gt;
    for (int i = 0; i &amp;lt; nLayers; i++) {&lt;br /&gt;
      LayerInfo info = layers[i];&lt;br /&gt;
      byte[] r = null, g = null, b = null, a = null;&lt;br /&gt;
      for (int j = 0; j &amp;lt; info.nChan; j++) {&lt;br /&gt;
        int id = info.chanID[j];&lt;br /&gt;
        switch (id) {&lt;br /&gt;
        case 0:&lt;br /&gt;
          r = readPlane(info.w, info.h);&lt;br /&gt;
          break;&lt;br /&gt;
        case 1:&lt;br /&gt;
          g = readPlane(info.w, info.h);&lt;br /&gt;
          break;&lt;br /&gt;
        case 2:&lt;br /&gt;
          b = readPlane(info.w, info.h);&lt;br /&gt;
          break;&lt;br /&gt;
        case -1:&lt;br /&gt;
          a = readPlane(info.w, info.h);&lt;br /&gt;
          break;&lt;br /&gt;
        default:&lt;br /&gt;
          readPlane(info.w, info.h);&lt;br /&gt;
        }&lt;br /&gt;
        if (err())&lt;br /&gt;
          break;&lt;br /&gt;
      }&lt;br /&gt;
      if (err())&lt;br /&gt;
        break;&lt;br /&gt;
      int n = info.w * info.h;&lt;br /&gt;
      if (r == null)&lt;br /&gt;
        r = fillBytes(n, 0);&lt;br /&gt;
      if (g == null)&lt;br /&gt;
        g = fillBytes(n, 0);&lt;br /&gt;
      if (b == null)&lt;br /&gt;
        b = fillBytes(n, 0);&lt;br /&gt;
      if (a == null)&lt;br /&gt;
        a = fillBytes(n, 255);&lt;br /&gt;
      BufferedImage im = makeImage(info.w, info.h, r, g, b, a);&lt;br /&gt;
      frames[i] = im;&lt;br /&gt;
    }&lt;br /&gt;
    lineLengths = null;&lt;br /&gt;
    if ((miscLen &amp;gt; 0) &amp;amp;&amp;amp; !err()) {&lt;br /&gt;
      int n = readInt(); // global layer mask info len&lt;br /&gt;
      skipBytes(n);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  protected byte[] readPlane(int w, int h) {&lt;br /&gt;
    // read a single color plane&lt;br /&gt;
    byte[] b = null;&lt;br /&gt;
    int size = w * h;&lt;br /&gt;
    if (hasLayers) {&lt;br /&gt;
      // get RLE compression info for channel&lt;br /&gt;
      rleEncoded = readShort() == 1;&lt;br /&gt;
      if (rleEncoded) {&lt;br /&gt;
        // list of encoded line lengths&lt;br /&gt;
        readLineLengths(h);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    if (rleEncoded) {&lt;br /&gt;
      b = readPlaneCompressed(w, h);&lt;br /&gt;
    } else {&lt;br /&gt;
      b = new byte[size];&lt;br /&gt;
      readBytes(b, size);&lt;br /&gt;
    }&lt;br /&gt;
    return b;&lt;br /&gt;
  }&lt;br /&gt;
  protected byte[] readPlaneCompressed(int w, int h) {&lt;br /&gt;
    byte[] b = new byte[w * h];&lt;br /&gt;
    byte[] s = new byte[w * 2];&lt;br /&gt;
    int pos = 0;&lt;br /&gt;
    for (int i = 0; i &amp;lt; h; i++) {&lt;br /&gt;
      if (lineIndex &amp;gt;= lineLengths.length) {&lt;br /&gt;
        status = STATUS_FORMAT_ERROR;&lt;br /&gt;
        return null;&lt;br /&gt;
      }&lt;br /&gt;
      int len = lineLengths[lineIndex++];&lt;br /&gt;
      readBytes(s, len);&lt;br /&gt;
      decodeRLE(s, 0, len, b, pos);&lt;br /&gt;
      pos += w;&lt;br /&gt;
    }&lt;br /&gt;
    return b;&lt;br /&gt;
  }&lt;br /&gt;
  protected void decodeRLE(byte[] src, int sindex, int slen, byte[] dst, int dindex) {&lt;br /&gt;
    try {&lt;br /&gt;
      int max = sindex + slen;&lt;br /&gt;
      while (sindex &amp;lt; max) {&lt;br /&gt;
        byte b = src[sindex++];&lt;br /&gt;
        int n = (int) b;&lt;br /&gt;
        if (n &amp;lt; 0) {&lt;br /&gt;
          // dup next byte 1-n times&lt;br /&gt;
          n = 1 - n;&lt;br /&gt;
          b = src[sindex++];&lt;br /&gt;
          for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
            dst[dindex++] = b;&lt;br /&gt;
          }&lt;br /&gt;
        } else {&lt;br /&gt;
          // copy next n+1 bytes&lt;br /&gt;
          n = n + 1;&lt;br /&gt;
          System.arraycopy(src, sindex, dst, dindex, n);&lt;br /&gt;
          dindex += n;&lt;br /&gt;
          sindex += n;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    } catch (Exception e) {&lt;br /&gt;
      status = STATUS_FORMAT_ERROR;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  protected short readShort() {&lt;br /&gt;
    // read big-endian 16-bit integer&lt;br /&gt;
    return (short) ((readByte() &amp;lt;&amp;lt; 8) | readByte());&lt;br /&gt;
  }&lt;br /&gt;
  protected String readString(int len) {&lt;br /&gt;
    // read string of specified length&lt;br /&gt;
    String s = &amp;quot;&amp;quot;;&lt;br /&gt;
    for (int i = 0; i &amp;lt; len; i++) {&lt;br /&gt;
      s = s + (char) readByte();&lt;br /&gt;
    }&lt;br /&gt;
    return s;&lt;br /&gt;
  }&lt;br /&gt;
  protected void skipBytes(int n) {&lt;br /&gt;
    // skip over n input bytes&lt;br /&gt;
    for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
      readByte();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
           &lt;br /&gt;
       &amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
			</entry>

	</feed>