解码一图像(.PSD)的文件到一个或多个帧 : PSD格式 « 图形用户界面 « Java

En
Java
1. 图形用户界面
2. 三维图形动画
3. 高级图形
4. 蚂蚁编译
5. Apache类库
6. 统计图
7. 
8. 集合数据结构
9. 数据类型
10. 数据库JDBC
11. 设计模式
12. 开发相关类
13. EJB3
14. 电子邮件
15. 事件
16. 文件输入输出
17. 游戏
18. 泛型
19. GWT
20. Hibernate
21. 本地化
22. J2EE平台
23. 基于J2ME
24. JDK-6
25. JNDI的LDAP
26. JPA
27. JSP技术
28. JSTL
29. 语言基础知识
30. 网络协议
31. PDF格式RTF格式
32. 映射
33. 常规表达式
34. 脚本
35. 安全
36. Servlets
37. Spring
38. Swing组件
39. 图形用户界面
40. SWT-JFace-Eclipse
41. 线程
42. 应用程序
43. Velocity
44. Web服务SOA
45. 可扩展标记语言
Java 教程
Java » 图形用户界面 » PSD格式屏幕截图 
解码一图像(.PSD)的文件到一个或多个帧

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
www.java2java.com | Contact Us
Copyright 2010 - 2030 Java Source and Support. All rights reserved.
All other trademarks are property of their respective owners.