Package org.apache.sanselan.formats.psd

Source Code of org.apache.sanselan.formats.psd.PsdImageParser

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.sanselan.formats.psd;

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.sanselan.ImageFormat;
import org.apache.sanselan.ImageInfo;
import org.apache.sanselan.ImageParser;
import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.common.IImageMetadata;
import org.apache.sanselan.common.byteSources.ByteSource;
import org.apache.sanselan.formats.psd.dataparsers.DataParser;
import org.apache.sanselan.formats.psd.dataparsers.DataParserBitmap;
import org.apache.sanselan.formats.psd.dataparsers.DataParserCMYK;
import org.apache.sanselan.formats.psd.dataparsers.DataParserGrayscale;
import org.apache.sanselan.formats.psd.dataparsers.DataParserIndexed;
import org.apache.sanselan.formats.psd.dataparsers.DataParserLab;
import org.apache.sanselan.formats.psd.dataparsers.DataParserRGB;
import org.apache.sanselan.formats.psd.datareaders.CompressedDataReader;
import org.apache.sanselan.formats.psd.datareaders.DataReader;
import org.apache.sanselan.formats.psd.datareaders.UncompressedDataReader;
import org.apache.sanselan.util.Debug;

public class PsdImageParser extends ImageParser
{

    public PsdImageParser()
    {
        super.setByteOrder(BYTE_ORDER_MSB);
        // setDebug(true);
    }

    public String getName()
    {
        return "PSD-Custom";
    }

    public String getDefaultExtension()
    {
        return DEFAULT_EXTENSION;
    }

    private static final String DEFAULT_EXTENSION = ".psd";

    private static final String ACCEPTED_EXTENSIONS[] = { DEFAULT_EXTENSION, };

    protected String[] getAcceptedExtensions()
    {
        return ACCEPTED_EXTENSIONS;
    }

    protected ImageFormat[] getAcceptedTypes()
    {
        return new ImageFormat[] { ImageFormat.IMAGE_FORMAT_PSD, //
        };
    }

    private PSDHeaderInfo readHeader(ByteSource byteSource)
            throws ImageReadException, IOException
    {
        InputStream is = null;

        try
        {
            is = byteSource.getInputStream();

            return readHeader(is);
        } finally
        {
            try
            {
                if (is != null) {
                    is.close();
                }
            } catch (Exception e)
            {
                Debug.debug(e);
            }

        }
    }

    private PSDHeaderInfo readHeader(InputStream is) throws ImageReadException,
            IOException
    {
        readAndVerifyBytes(is, new byte[] { 56, 66, 80, 83 },
                "Not a Valid PSD File");

        int Version = read2Bytes("Version", is, "Not a Valid PSD File");

        byte Reserved[] = readByteArray("Reserved", 6, is,
                "Not a Valid PSD File");

        int Channels = read2Bytes("Channels", is, "Not a Valid PSD File");
        int Rows = read4Bytes("Rows", is, "Not a Valid PSD File");
        int Columns = read4Bytes("Columns", is, "Not a Valid PSD File");
        int Depth = read2Bytes("Depth", is, "Not a Valid PSD File");
        int Mode = read2Bytes("Mode", is, "Not a Valid PSD File");

        PSDHeaderInfo result = new PSDHeaderInfo(Version, Reserved, Channels,
                Rows, Columns, Depth, Mode);

        return result;
    }

    private ImageContents readImageContents(InputStream is)
            throws ImageReadException, IOException
    {
        PSDHeaderInfo header = readHeader(is);

        int ColorModeDataLength = read4Bytes("ColorModeDataLength", is,
                "Not a Valid PSD File");
        skipBytes(is, ColorModeDataLength);
        // is.skip(ColorModeDataLength);
        // byte ColorModeData[] = readByteArray("ColorModeData",
        // ColorModeDataLength, is, "Not a Valid PSD File");

        int ImageResourcesLength = read4Bytes("ImageResourcesLength", is,
                "Not a Valid PSD File");
        skipBytes(is, ImageResourcesLength);
        // long skipped = is.skip(ImageResourcesLength);
        // byte ImageResources[] = readByteArray("ImageResources",
        // ImageResourcesLength, is, "Not a Valid PSD File");

        int LayerAndMaskDataLength = read4Bytes("LayerAndMaskDataLength", is,
                "Not a Valid PSD File");
        skipBytes(is, LayerAndMaskDataLength);
        // is.skip(LayerAndMaskDataLength);
        // byte LayerAndMaskData[] = readByteArray("LayerAndMaskData",
        // LayerAndMaskDataLength, is, "Not a Valid PSD File");

        int Compression = read2Bytes("Compression", is, "Not a Valid PSD File");

        // skip_bytes(is, LayerAndMaskDataLength);
        // byte ImageData[] = readByteArray("ImageData", LayerAndMaskDataLength,
        // is, "Not a Valid PSD File");

        // System.out.println("Compression: " + Compression);

        ImageContents result = new ImageContents(header, ColorModeDataLength,
        // ColorModeData,
                ImageResourcesLength,
                // ImageResources,
                LayerAndMaskDataLength,
                // LayerAndMaskData,
                Compression);

        return result;
    }

    private ArrayList readImageResourceBlocks(byte bytes[],
            int imageResourceIDs[], int maxBlocksToRead)
            throws ImageReadException, IOException
    {
        return readImageResourceBlocks(new ByteArrayInputStream(bytes),
                imageResourceIDs, maxBlocksToRead, bytes.length);
    }

    private boolean keepImageResourceBlock(int ID, int imageResourceIDs[])
    {
        if (imageResourceIDs == null)
            return true;

        for (int i = 0; i < imageResourceIDs.length; i++)
            if (ID == imageResourceIDs[i])
                return true;

        return false;
    }

    private ArrayList readImageResourceBlocks(InputStream is,
            int imageResourceIDs[], int maxBlocksToRead, int available)
            throws ImageReadException, IOException
    {
        ArrayList result = new ArrayList();

        while (available > 0)
        {
            readAndVerifyBytes(is, new byte[] { 56, 66, 73, 77 },
                    "Not a Valid PSD File");
            available -= 4;

            int id = read2Bytes("ID", is, "Not a Valid PSD File");
            available -= 2;

            int nameLength = readByte("NameLength", is, "Not a Valid PSD File");

            available -= 1;
            byte nameBytes[] = readByteArray("NameData", nameLength, is,
                    "Not a Valid PSD File");
            available -= nameLength;
            if (((nameLength + 1) % 2) != 0)
            {
                int NameDiscard = readByte("NameDiscard", is,
                        "Not a Valid PSD File");
                available -= 1;
            }
            // String Name = readPString("Name", 6, is, "Not a Valid PSD File");
            int DataSize = read4Bytes("Size", is, "Not a Valid PSD File");
            available -= 4;
            // int ActualDataSize = ((DataSize % 2) == 0)
            // ? DataSize
            // : DataSize + 1; // pad to make even

            byte Data[] = readByteArray("Data", DataSize, is,
                    "Not a Valid PSD File");
            available -= DataSize;

            if ((DataSize % 2) != 0)
            {
                int DataDiscard = readByte("DataDiscard", is,
                        "Not a Valid PSD File");
                available -= 1;
            }

            if (keepImageResourceBlock(id, imageResourceIDs))
            {
                result.add(new ImageResourceBlock(id, nameBytes, Data));

                if ((maxBlocksToRead >= 0)
                        && (result.size() >= maxBlocksToRead))
                    return result;
            }
            // debugNumber("ID", ID, 2);

        }

        return result;
    }

    private ArrayList readImageResourceBlocks(ByteSource byteSource,
            int imageResourceIDs[], int maxBlocksToRead)
            throws ImageReadException, IOException
    {
        InputStream is = null;

        try
        {
            is = byteSource.getInputStream();

            ImageContents imageContents = readImageContents(is);

            is.close();

            is = this.getInputStream(byteSource, PSD_SECTION_IMAGE_RESOURCES);
            byte ImageResources[] = readByteArray("ImageResources",
                    imageContents.ImageResourcesLength, is,
                    "Not a Valid PSD File");

            return readImageResourceBlocks(ImageResources, imageResourceIDs,
                    maxBlocksToRead);
        } finally
        {
            try
            {
                if (is != null) {
                    is.close();
                }
            } catch (Exception e)
            {
                Debug.debug(e);
            }

        }
    }

    private static final int PSD_SECTION_HEADER = 0;
    private static final int PSD_SECTION_COLOR_MODE = 1;
    private static final int PSD_SECTION_IMAGE_RESOURCES = 2;
    private static final int PSD_SECTION_LAYER_AND_MASK_DATA = 3;
    private static final int PSD_SECTION_IMAGE_DATA = 4;

    private static final int PSD_HEADER_LENGTH = 26;

    private InputStream getInputStream(ByteSource byteSource, int section)
            throws ImageReadException, IOException
    {
        InputStream is = byteSource.getInputStream();

        if (section == PSD_SECTION_HEADER)
            return is;

        skipBytes(is, PSD_HEADER_LENGTH);
        // is.skip(kHeaderLength);

        int ColorModeDataLength = read4Bytes("ColorModeDataLength", is,
                "Not a Valid PSD File");

        if (section == PSD_SECTION_COLOR_MODE)
            return is;

        skipBytes(is, ColorModeDataLength);
        // byte ColorModeData[] = readByteArray("ColorModeData",
        // ColorModeDataLength, is, "Not a Valid PSD File");

        int ImageResourcesLength = read4Bytes("ImageResourcesLength", is,
                "Not a Valid PSD File");

        if (section == PSD_SECTION_IMAGE_RESOURCES)
            return is;

        skipBytes(is, ImageResourcesLength);
        // byte ImageResources[] = readByteArray("ImageResources",
        // ImageResourcesLength, is, "Not a Valid PSD File");

        int LayerAndMaskDataLength = read4Bytes("LayerAndMaskDataLength", is,
                "Not a Valid PSD File");

        if (section == PSD_SECTION_LAYER_AND_MASK_DATA)
            return is;

        skipBytes(is, LayerAndMaskDataLength);
        // byte LayerAndMaskData[] = readByteArray("LayerAndMaskData",
        // LayerAndMaskDataLength, is, "Not a Valid PSD File");

        int Compression = read2Bytes("Compression", is, "Not a Valid PSD File");

        // byte ImageData[] = readByteArray("ImageData",
        // LayerAndMaskDataLength, is, "Not a Valid PSD File");

        if (section == PSD_SECTION_IMAGE_DATA)
            return is;

        throw new ImageReadException("getInputStream: Unknown Section: "
                + section);
    }

    private byte[] getData(ByteSource byteSource, int section)
            throws ImageReadException, IOException
    {
        InputStream is = null;

        try
        {
            is = byteSource.getInputStream();

            // PSDHeaderInfo header = readHeader(is);
            if (section == PSD_SECTION_HEADER)
                return readByteArray("Header", PSD_HEADER_LENGTH, is,
                        "Not a Valid PSD File");
            skipBytes(is, PSD_HEADER_LENGTH);

            int ColorModeDataLength = read4Bytes("ColorModeDataLength", is,
                    "Not a Valid PSD File");

            if (section == PSD_SECTION_COLOR_MODE)
                return readByteArray("ColorModeData", ColorModeDataLength, is,
                        "Not a Valid PSD File");

            skipBytes(is, ColorModeDataLength);
            // byte ColorModeData[] = readByteArray("ColorModeData",
            // ColorModeDataLength, is, "Not a Valid PSD File");

            int ImageResourcesLength = read4Bytes("ImageResourcesLength", is,
                    "Not a Valid PSD File");

            if (section == PSD_SECTION_IMAGE_RESOURCES)
                return readByteArray("ImageResources", ImageResourcesLength,
                        is, "Not a Valid PSD File");

            skipBytes(is, ImageResourcesLength);
            // byte ImageResources[] = readByteArray("ImageResources",
            // ImageResourcesLength, is, "Not a Valid PSD File");

            int LayerAndMaskDataLength = read4Bytes("LayerAndMaskDataLength",
                    is, "Not a Valid PSD File");

            if (section == PSD_SECTION_LAYER_AND_MASK_DATA)
                return readByteArray("LayerAndMaskData",
                        LayerAndMaskDataLength, is, "Not a Valid PSD File");

            skipBytes(is, LayerAndMaskDataLength);
            // byte LayerAndMaskData[] = readByteArray("LayerAndMaskData",
            // LayerAndMaskDataLength, is, "Not a Valid PSD File");

            int Compression = read2Bytes("Compression", is,
                    "Not a Valid PSD File");

            // byte ImageData[] = readByteArray("ImageData",
            // LayerAndMaskDataLength, is, "Not a Valid PSD File");

            // if (section == kPSD_SECTION_IMAGE_DATA)
            // return readByteArray("LayerAndMaskData", LayerAndMaskDataLength,
            // is,
            // "Not a Valid PSD File");

        } finally
        {
            try
            {
                if (is != null) {
                    is.close();
                }
            } catch (Exception e)
            {
                Debug.debug(e);
            }

        }
        throw new ImageReadException("getInputStream: Unknown Section: "
                + section);
    }

    private ImageContents readImageContents(ByteSource byteSource)
            throws ImageReadException, IOException
    {
        InputStream is = null;

        try
        {
            is = byteSource.getInputStream();

            ImageContents imageContents = readImageContents(is);
            return imageContents;
        } finally
        {
            try
            {
                if (is != null) {
                    is.close();
                }
            } catch (Exception e)
            {
                Debug.debug(e);
            }

        }

    }

    public final static int IMAGE_RESOURCE_ID_ICC_PROFILE = 0x040F;

    public byte[] getICCProfileBytes(ByteSource byteSource, Map params)
            throws ImageReadException, IOException
    {
        ArrayList blocks = readImageResourceBlocks(byteSource,
                new int[] { IMAGE_RESOURCE_ID_ICC_PROFILE, }, 1);

        if ((blocks == null) || (blocks.size() < 1))
            return null;

        ImageResourceBlock irb = (ImageResourceBlock) blocks.get(0);
        byte bytes[] = irb.data;
        if ((bytes == null) || (bytes.length < 1))
            return null;
        return bytes;
    }

    public Dimension getImageSize(ByteSource byteSource, Map params)
            throws ImageReadException, IOException
    {
        PSDHeaderInfo bhi = readHeader(byteSource);
        if (bhi == null)
            throw new ImageReadException("PSD: couldn't read header");

        return new Dimension(bhi.Columns, bhi.Rows);

    }

    public byte[] embedICCProfile(byte image[], byte profile[])
    {
        return null;
    }

    public boolean embedICCProfile(File src, File dst, byte profile[])
    {
        return false;
    }

    public IImageMetadata getMetadata(ByteSource byteSource, Map params)
            throws ImageReadException, IOException
    {
        return null;
    }

    private int getChannelsPerMode(int mode)
    {
        switch (mode)
        {
        case 0: // Bitmap
            return 1;
        case 1: // Grayscale
            return 1;
        case 2: // Indexed
            return -1;
        case 3: // RGB
            return 3;
        case 4: // CMYK
            return 4;
        case 7: // Multichannel
            return -1;
        case 8: // Duotone
            return -1;
        case 9: // Lab
            return 4;
        default:
            return -1;

        }
    }

    public ImageInfo getImageInfo(ByteSource byteSource, Map params)
            throws ImageReadException, IOException
    {
        ImageContents imageContents = readImageContents(byteSource);
        // ImageContents imageContents = readImage(byteSource, false);

        if (imageContents == null)
            throw new ImageReadException("PSD: Couldn't read blocks");

        PSDHeaderInfo header = imageContents.header;
        if (header == null)
            throw new ImageReadException("PSD: Couldn't read Header");

        int Width = header.Columns;
        int Height = header.Rows;

        ArrayList Comments = new ArrayList();
        // TODO: comments...

        int BitsPerPixel = header.Depth * getChannelsPerMode(header.Mode);
        // System.out.println("header.Depth: " + header.Depth);
        // System.out.println("header.Mode: " + header.Mode);
        // System.out.println("getChannelsPerMode(header.Mode): " +
        // getChannelsPerMode(header.Mode));
        if (BitsPerPixel < 0)
            BitsPerPixel = 0;
        ImageFormat Format = ImageFormat.IMAGE_FORMAT_PSD;
        String FormatName = "Photoshop";
        String MimeType = "image/x-photoshop";
        // we ought to count images, but don't yet.
        int NumberOfImages = -1;
        // not accurate ... only reflects first
        boolean isProgressive = false;

        int PhysicalWidthDpi = 72;
        float PhysicalWidthInch = (float) ((double) Width / (double) PhysicalWidthDpi);
        int PhysicalHeightDpi = 72;
        float PhysicalHeightInch = (float) ((double) Height / (double) PhysicalHeightDpi);

        String FormatDetails = "Psd";

        boolean isTransparent = false; // TODO: inaccurate.
        boolean usesPalette = header.Mode == COLOR_MODE_INDEXED;
        int ColorType = ImageInfo.COLOR_TYPE_UNKNOWN;

        String compressionAlgorithm;
        switch (imageContents.Compression)
        {
        case 0:
            compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_NONE;
            break;
        case 1:
            compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_PSD;
            break;
        default:
            compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_UNKNOWN;
        }

        ImageInfo result = new ImageInfo(FormatDetails, BitsPerPixel, Comments,
                Format, FormatName, Height, MimeType, NumberOfImages,
                PhysicalHeightDpi, PhysicalHeightInch, PhysicalWidthDpi,
                PhysicalWidthInch, Width, isProgressive, isTransparent,
                usesPalette, ColorType, compressionAlgorithm);

        return result;
    }

    // TODO not used
    private ImageResourceBlock findImageResourceBlock(ArrayList blocks, int ID)
    {
        for (int i = 0; i < blocks.size(); i++)
        {
            ImageResourceBlock block = (ImageResourceBlock) blocks.get(i);

            if (block.id == ID)
                return block;
        }
        return null;
    }

    public boolean dumpImageFile(PrintWriter pw, ByteSource byteSource)
            throws ImageReadException, IOException
    {
        pw.println("gif.dumpImageFile");

        {
            ImageInfo fImageData = getImageInfo(byteSource);
            if (fImageData == null)
                return false;

            fImageData.toString(pw, "");
        }
        {
            ImageContents imageContents = readImageContents(byteSource);

            imageContents.dump(pw);
            imageContents.header.dump(pw);

            ArrayList blocks = readImageResourceBlocks(byteSource,
            // fImageContents.ImageResources,
                    null, -1);

            pw.println("blocks.size(): " + blocks.size());

            // System.out.println("gif.blocks: " + blocks.blocks.size());
            for (int i = 0; i < blocks.size(); i++)
            {
                ImageResourceBlock block = (ImageResourceBlock) blocks.get(i);
                pw.println("\t" + i + " (" + Integer.toHexString(block.id)
                        + ", " + "'"
                        + new String(block.nameData)
                        + "' ("
                        + block.nameData.length
                        + "), "
                        // + block.getClass().getName()
                        // + ", "
                        + " data: " + block.data.length + " type: '"
                        + new PSDConstants().getDescription(block.id) + "' "
                        + ")");

            }

        }

        pw.println("");

        return true;
    }

    private static final int COLOR_MODE_INDEXED = 2;

    public BufferedImage getBufferedImage(ByteSource byteSource, Map params)
            throws ImageReadException, IOException
    {
        ImageContents imageContents = readImageContents(byteSource);
        // ImageContents imageContents = readImage(byteSource, false);

        if (imageContents == null)
            throw new ImageReadException("PSD: Couldn't read blocks");

        PSDHeaderInfo header = imageContents.header;
        if (header == null)
            throw new ImageReadException("PSD: Couldn't read Header");

        // ImageDescriptor id = (ImageDescriptor)
        // findBlock(fImageContents.blocks,
        // kImageSeperator);
        // if (id == null)
        // throw new ImageReadException("PSD: Couldn't read Image Descriptor");
        // GraphicControlExtension gce = (GraphicControlExtension) findBlock(
        // fImageContents.blocks, kGraphicControlExtension);

        ArrayList blocks = readImageResourceBlocks(byteSource,
        // fImageContents.ImageResources,
                null, -1);

        int width = header.Columns;
        int height = header.Rows;
        // int height = header.Columns;

        // int transfer_type;

        // transfer_type = DataBuffer.TYPE_BYTE;

        boolean hasAlpha = false;
        BufferedImage result = getBufferedImageFactory(params)
                .getColorBufferedImage(width, height, hasAlpha);

        DataParser dataParser;
        switch (imageContents.header.Mode)
        {
        case 0: // bitmap
            dataParser = new DataParserBitmap();
            break;
        case 1:
        case 8: // Duotone=8;
            dataParser = new DataParserGrayscale();
            break;
        case 3:
            dataParser = new DataParserRGB();
            break;
        case 4:
            dataParser = new DataParserCMYK();
            break;
        case 9:
            dataParser = new DataParserLab();
            break;
        case COLOR_MODE_INDEXED:
            // case 2 : // Indexed=2;
        {

            byte ColorModeData[] = getData(byteSource, PSD_SECTION_COLOR_MODE);

            // ImageResourceBlock block = findImageResourceBlock(blocks,
            // 0x03EB);
            // if (block == null)
            // throw new ImageReadException(
            // "Missing: Indexed Color Image Resource Block");

            dataParser = new DataParserIndexed(ColorModeData);
            break;
        }
        case 7: // Multichannel=7;
            // fDataParser = new DataParserStub();
            // break;

            // case 1 :
            // fDataReader = new CompressedDataReader();
            // break;
        default:
            throw new ImageReadException("Unknown Mode: "
                    + imageContents.header.Mode);
        }
        DataReader fDataReader;
        switch (imageContents.Compression)
        {
        case 0:
            fDataReader = new UncompressedDataReader(dataParser);
            break;
        case 1:
            fDataReader = new CompressedDataReader(dataParser);
            break;
        default:
            throw new ImageReadException("Unknown Compression: "
                    + imageContents.Compression);
        }
        {
            InputStream is = null;

            try
            {
                is = getInputStream(byteSource, PSD_SECTION_IMAGE_DATA);
                fDataReader.readData(is, result, imageContents, this);

                fDataReader.dump();
                // is.
                // ImageContents imageContents = readImageContents(is);
                // return imageContents;
            } finally
            {
                try
                {
                    if (is != null)
                        is.close();
                } catch (Exception e)
                {
                    Debug.debug(e);
                }

            }

        }

        return result;

    }

    public final static int IMAGE_RESOURCE_ID_XMP = 0x0424;

    public final static String BLOCK_NAME_XMP = "XMP";

    /**
     * Extracts embedded XML metadata as XML string.
     * <p>
     *
     * @param byteSource
     *            File containing image data.
     * @param params
     *            Map of optional parameters, defined in SanselanConstants.
     * @return Xmp Xml as String, if present. Otherwise, returns null.
     */
    public String getXmpXml(ByteSource byteSource, Map params)
            throws ImageReadException, IOException
    {

        ImageContents imageContents = readImageContents(byteSource);

        if (imageContents == null)
            throw new ImageReadException("PSD: Couldn't read blocks");

        PSDHeaderInfo header = imageContents.header;
        if (header == null)
            throw new ImageReadException("PSD: Couldn't read Header");

        ArrayList blocks = readImageResourceBlocks(byteSource,
                new int[] { IMAGE_RESOURCE_ID_XMP, }, -1);

        if ((blocks == null) || (blocks.size() < 1))
            return null;

        List xmpBlocks = new ArrayList();
        if (false)
        {
            // TODO: for PSD 7 and later, verify "XMP" name.
            for (int i = 0; i < blocks.size(); i++)
            {
                ImageResourceBlock block = (ImageResourceBlock) blocks.get(i);
                if (!block.getName().equals(BLOCK_NAME_XMP))
                    continue;
                xmpBlocks.add(block);
            }
        } else
            xmpBlocks.addAll(blocks);

        if (xmpBlocks.size() < 1)
            return null;
        if (xmpBlocks.size() > 1)
            throw new ImageReadException(
                    "PSD contains more than one XMP block.");

        ImageResourceBlock block = (ImageResourceBlock) xmpBlocks.get(0);

        try
        {
            // segment data is UTF-8 encoded xml.
            String xml = new String(block.data, 0, block.data.length, "utf-8");
            return xml;
        } catch (UnsupportedEncodingException e)
        {
            throw new ImageReadException("Invalid JPEG XMP Segment.");
        }
    }

}
TOP

Related Classes of org.apache.sanselan.formats.psd.PsdImageParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.