Decodes a PhotoShop (.psd) file into one or more frames : Psd « 2D Graphics GUI « Java

Java
1. 2D Graphics GUI
2. 3D
3. Advanced Graphics
4. Ant
5. Apache Common
6. Chart
7. Collections Data Structure
8. Database SQL JDBC
9. Design Pattern
10. Development Class
11. Email
12. Event
13. File Input Output
14. Game
15. Hibernate
16. J2EE
17. J2ME
18. JDK 6
19. JSP
20. JSTL
21. Language Basics
22. Network Protocol
23. PDF RTF
24. Regular Expressions
25. Security
26. Servlets
27. Spring
28. Swing Components
29. Swing JFC
30. SWT JFace Eclipse
31. Threads
32. Tiny Application
33. Velocity
34. Web Services SOA
35. XML
Microsoft Office Word 2007 Tutorial
Java Tutorial
Java Source Code / Java Documentation
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
C# / C Sharp
C# / CSharp Tutorial
ASP.Net
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
PHP
Python
SQL Server / T-SQL
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Java » 2D Graphics GUI » PsdScreenshots 
Decodes a PhotoShop (.psd) file into one or more frames

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

/**
 * Class PSDReader - Decodes a PhotoShop (.psd) file into one or more frames.
 * Supports uncompressed or RLE-compressed RGB files only. Each layer may be
 * retrieved as a full frame BufferedImage, or as a smaller image with an offset
 * if the layer does not occupy the full frame size. Transparency in the
 * original psd file is preserved in the returned BufferedImage's. Does not
 * support additional features in PS versions higher than 3.0. Example: <br>
 
 * <pre>
 * PSDReader r = new PSDReader();
 * r.read(&quot;sample.psd&quot;);
 * int n = r.getFrameCount();
 * for (int i = 0; i &lt; n; i++) {
 *   BufferedImage image = r.getLayer(i);
 *   Point offset = r.getLayerOffset(i);
 *   // do something with image
 * }
 * </pre>
 
 * No copyright asserted on the source code of this class. May be used for any
 * purpose. Please forward any corrections to kweiner@fmsware.com.
 
 @author Kevin Weiner, FM Software.
 @version 1.1 January 2004 [bug fix; add RLE support]
 
 */
public class PSDReader {

  /**
   * File read status: No errors.
   */
  public static final int STATUS_OK = 0;

  /**
   * File read status: Error decoding file (may be partially decoded)
   */
  public static final int STATUS_FORMAT_ERROR = 1;

  /**
   * File read status: Unable to open source.
   */
  public static final int STATUS_OPEN_ERROR = 2;

  /**
   * File read status: Unsupported format
   */
  public static final int STATUS_UNSUPPORTED = 3;

  public static int ImageType = BufferedImage.TYPE_INT_ARGB;

  protected BufferedInputStream input;

  protected int frameCount;

  protected BufferedImage[] frames;

  protected int status = 0;

  protected int nChan;

  protected int width;

  protected int height;

  protected int nLayers;

  protected int miscLen;

  protected boolean hasLayers;

  protected LayerInfo[] layers;

  protected short[] lineLengths;

  protected int lineIndex;

  protected boolean rleEncoded;

  protected class LayerInfo {
    int x, y, w, h;

    int nChan;

    int[] chanID;

    int alpha;
  }

  /**
   * Gets the number of layers read from file.
   
   @return frame count
   */
  public int getFrameCount() {
    return frameCount;
  }

  protected void setInput(InputStream stream) {
    // open input stream
    init();
    if (stream == null) {
      status = STATUS_OPEN_ERROR;
    else {
      if (stream instanceof BufferedInputStream)
        input = (BufferedInputStreamstream;
      else
        input = new BufferedInputStream(stream);
    }
  }

  protected void setInput(String name) {
    // open input file
    init();
    try {
      name = name.trim();
      if (name.startsWith("file:")) {
        name = name.substring(5);
        while (name.startsWith("/"))
          name = name.substring(1);
      }
      if (name.indexOf("://"0) {
        URL url = new URL(name);
        input = new BufferedInputStream(url.openStream());
      else {
        input = new BufferedInputStream(new FileInputStream(name));
      }
    catch (IOException e) {
      status = STATUS_OPEN_ERROR;
    }
  }

  /**
   * Gets display duration for specified frame. Always returns 0.
   
   */
  public int getDelay(int forFrame) {
    return 0;
  }

  /**
   * Gets the image contents of frame n. Note that this expands the image to the
   * full frame size (if the layer was smaller) and any subsequent use of
   * getLayer() will return the full image.
   
   @return BufferedImage representation of frame, or null if n is invalid.
   */
  public BufferedImage getFrame(int n) {
    BufferedImage im = null;
    if ((n >= 0&& (n < nLayers)) {
      im = frames[n];
      LayerInfo info = layers[n];
      if ((info.w != width|| (info.h != height)) {
        BufferedImage temp = new BufferedImage(width, height, ImageType);
        Graphics2D gc = temp.createGraphics();
        gc.drawImage(im, info.x, info.y, null);
        gc.dispose();
        im = temp;
        frames[n= im;
      }
    }
    return im;
  }

  /**
   * Gets maximum image size. Individual layers may be smaller.
   
   @return maximum image dimensions
   */
  public Dimension getFrameSize() {
    return new Dimension(width, height);
  }

  /**
   * Gets the first (or only) image read.
   
   @return BufferedImage containing first frame, or null if none.
   */
  public BufferedImage getImage() {
    return getFrame(0);
  }

  /**
   * Gets the image contents of layer n. May be smaller than full frame size -
   * use getFrameOffset() to obtain position of subimage within main image area.
   
   @return BufferedImage representation of layer, or null if n is invalid.
   */
  public BufferedImage getLayer(int n) {
    BufferedImage im = null;
    if ((n >= 0&& (n < nLayers)) {
      im = frames[n];
    }
    return im;
  }

  /**
   * Gets the subimage offset of layer n if it is smaller than the full frame
   * size.
   
   @return Point indicating offset from upper left corner of frame.
   */
  public Point getLayerOffset(int n) {
    Point p = null;
    if ((n >= 0&& (n < nLayers)) {
      int x = layers[n].x;
      int y = layers[n].y;
      p = new Point(x, y);
    }
    if (p == null) {
      p = new Point(00);
    }
    return p;
  }

  /**
   * Reads PhotoShop layers from stream.
   
   @param InputStream
   *          in PhotoShop format.
   @return read status code (0 = no errors)
   */
  public int read(InputStream stream) {
    setInput(stream);
    process();
    return status;
  }

  /**
   * Reads PhotoShop file from specified source (file or URL string)
   
   @param name
   *          String containing source
   @return read status code (0 = no errors)
   */
  public int read(String name) {
    setInput(name);
    process();
    return status;
  }

  /**
   * Closes input stream and discards contents of all frames.
   
   */
  public void reset() {
    init();
  }

  protected void close() {
    if (input != null) {
      try {
        input.close();
      catch (Exception e) {
      }
      input = null;
    }
  }

  protected boolean err() {
    return status != STATUS_OK;
  }

  protected byte[] fillBytes(int size, int value) {
    // create byte array filled with given value
    byte[] b = new byte[size];
    if (value != 0) {
      byte v = (bytevalue;
      for (int i = 0; i < size; i++) {
        b[i= v;
      }
    }
    return b;
  }

  protected void init() {
    close();
    frameCount = 0;
    frames = null;
    layers = null;
    hasLayers = true;
    status = STATUS_OK;
  }

  protected void makeDummyLayer() {
    // creat dummy layer for non-layered image
    rleEncoded = readShort() == 1;
    hasLayers = false;
    nLayers = 1;
    layers = new LayerInfo[1];
    LayerInfo layer = new LayerInfo();
    layers[0= layer;
    layer.h = height;
    layer.w = width;
    int nc = Math.min(nChan, 4);
    if (rleEncoded) {
      // get list of rle encoded line lengths for all channels
      readLineLengths(height * nc);
    }
    layer.nChan = nc;
    layer.chanID = new int[nc];
    for (int i = 0; i < nc; i++) {
      int id = i;
      if (i == 3)
        id = -1;
      layer.chanID[i= id;
    }
  }

  protected void readLineLengths(int nLines) {
    // read list of rle encoded line lengths
    lineLengths = new short[nLines];
    for (int i = 0; i < nLines; i++) {
      lineLengths[i= readShort();
    }
    lineIndex = 0;
  }

  protected BufferedImage makeImage(int w, int h, byte[] r, byte[] g, byte[] b, byte[] a) {
    // create image from given plane data
    BufferedImage im = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
    int[] data = ((DataBufferIntim.getRaster().getDataBuffer()).getData();
    int n = w * h;
    int j = 0;
    while (j < n) {
      try {
        int ac = a[j0xff;
        int rc = r[j0xff;
        int gc = g[j0xff;
        int bc = b[j0xff;
        data[j(((((ac << 8| rc<< 8| gc<< 8| bc;
      catch (Exception e) {
      }
      j++;
    }
    return im;
  }

  protected void process() {
    // decode PSD file
    if (err())
      return;
    readHeader();
    if (err())
      return;
    readLayerInfo();
    if (err())
      return;
    if (nLayers == 0) {
      makeDummyLayer();
      if (err())
        return;
    }
    readLayers();
  }

  protected int readByte() {
    // read single byte from input
    int curByte = 0;
    try {
      curByte = input.read();
    catch (IOException e) {
      status = STATUS_FORMAT_ERROR;
    }
    return curByte;
  }

  protected int readBytes(byte[] bytes, int n) {
    // read multiple bytes from input
    if (bytes == null)
      return 0;
    int r = 0;
    try {
      r = input.read(bytes, 0, n);
    catch (IOException e) {
      status = STATUS_FORMAT_ERROR;
    }
    if (r < n) {
      status = STATUS_FORMAT_ERROR;
    }
    return r;
  }

  protected void readHeader() {
    // read PSD header info
    String sig = readString(4);
    int ver = readShort();
    skipBytes(6);
    nChan = readShort();
    height = readInt();
    width = readInt();
    int depth = readShort();
    int mode = readShort();
    int cmLen = readInt();
    skipBytes(cmLen);
    int imResLen = readInt();
    skipBytes(imResLen);

    // require 8-bit RGB data
    if ((!sig.equals("8BPS")) || (ver != 1)) {
      status = STATUS_FORMAT_ERROR;
    else if ((depth != 8|| (mode != 3)) {
      status = STATUS_UNSUPPORTED;
    }
  }

  protected int readInt() {
    // read big-endian 32-bit integer
    return (((((readByte() << 8| readByte()) << 8| readByte()) << 8| readByte();
  }

  protected void readLayerInfo() {
    // read layer header info
    miscLen = readInt();
    if (miscLen == 0) {
      return// no layers, only base image
    }
    int layerInfoLen = readInt();
    nLayers = readShort();
    if (nLayers > 0) {
      layers = new LayerInfo[nLayers];
    }
    for (int i = 0; i < nLayers; i++) {
      LayerInfo info = new LayerInfo();
      layers[i= info;
      info.y = readInt();
      info.x = readInt();
      info.h = readInt() - info.y;
      info.w = readInt() - info.x;
      info.nChan = readShort();
      info.chanID = new int[info.nChan];
      for (int j = 0; j < info.nChan; j++) {
        int id = readShort();
        int size = readInt();
        info.chanID[j= id;
      }
      String s = readString(4);
      if (!s.equals("8BIM")) {
        status = STATUS_FORMAT_ERROR;
        return;
      }
      skipBytes(4)// blend mode
      info.alpha = readByte();
      int clipping = readByte();
      int flags = readByte();
      readByte()// filler
      int extraSize = readInt();
      skipBytes(extraSize);
    }
  }

  protected void readLayers() {
    // read and convert each layer to BufferedImage
    frameCount = nLayers;
    frames = new BufferedImage[nLayers];
    for (int i = 0; i < nLayers; i++) {
      LayerInfo info = layers[i];
      byte[] r = null, g = null, b = null, a = null;
      for (int j = 0; j < info.nChan; j++) {
        int id = info.chanID[j];
        switch (id) {
        case 0:
          r = readPlane(info.w, info.h);
          break;
        case 1:
          g = readPlane(info.w, info.h);
          break;
        case 2:
          b = readPlane(info.w, info.h);
          break;
        case -1:
          a = readPlane(info.w, info.h);
          break;
        default:
          readPlane(info.w, info.h);
        }
        if (err())
          break;
      }
      if (err())
        break;
      int n = info.w * info.h;
      if (r == null)
        r = fillBytes(n, 0);
      if (g == null)
        g = fillBytes(n, 0);
      if (b == null)
        b = fillBytes(n, 0);
      if (a == null)
        a = fillBytes(n, 255);

      BufferedImage im = makeImage(info.w, info.h, r, g, b, a);
      frames[i= im;
    }
    lineLengths = null;
    if ((miscLen > 0&& !err()) {
      int n = readInt()// global layer mask info len
      skipBytes(n);
    }
  }

  protected byte[] readPlane(int w, int h) {
    // read a single color plane
    byte[] b = null;
    int size = w * h;
    if (hasLayers) {
      // get RLE compression info for channel
      rleEncoded = readShort() == 1;
      if (rleEncoded) {
        // list of encoded line lengths
        readLineLengths(h);
      }
    }

    if (rleEncoded) {
      b = readPlaneCompressed(w, h);
    else {
      b = new byte[size];
      readBytes(b, size);
    }

    return b;

  }

  protected byte[] readPlaneCompressed(int w, int h) {
    byte[] b = new byte[w * h];
    byte[] s = new byte[w * 2];
    int pos = 0;
    for (int i = 0; i < h; i++) {
      if (lineIndex >= lineLengths.length) {
        status = STATUS_FORMAT_ERROR;
        return null;
      }
      int len = lineLengths[lineIndex++];
      readBytes(s, len);
      decodeRLE(s, 0, len, b, pos);
      pos += w;
    }
    return b;
  }

  protected void decodeRLE(byte[] src, int sindex, int slen, byte[] dst, int dindex) {
    try {
      int max = sindex + slen;
      while (sindex < max) {
        byte b = src[sindex++];
        int n = (intb;
        if (n < 0) {
          // dup next byte 1-n times
          n = - n;
          b = src[sindex++];
          for (int i = 0; i < n; i++) {
            dst[dindex++= b;
          }
        else {
          // copy next n+1 bytes
          n = n + 1;
          System.arraycopy(src, sindex, dst, dindex, n);
          dindex += n;
          sindex += n;
        }
      }
    catch (Exception e) {
      status = STATUS_FORMAT_ERROR;
    }
  }

  protected short readShort() {
    // read big-endian 16-bit integer
    return (short) ((readByte() << 8| readByte());
  }

  protected String readString(int len) {
    // read string of specified length
    String s = "";
    for (int i = 0; i < len; i++) {
      s = s + (charreadByte();
    }
    return s;
  }

  protected void skipBytes(int n) {
    // skip over n input bytes
    for (int i = 0; i < n; i++) {
      readByte();
    }
  }
}

           
       
Related examples in the same category
w__w_w__._j_a___v__a2s_._c__om | Contact Us
Copyright 2003 - 08 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.