///////////////////////////////////////////////////////////////////////////////// // // Photoshop PSD FileType Plugin for Paint.NET // http://psdplugin.codeplex.com/ // // This software is provided under the MIT License: // Copyright (c) 2006-2007 Frank Blumenberg // Copyright (c) 2010-2016 Tao Yue // // See LICENSE.txt for complete licensing and attribution information. // ///////////////////////////////////////////////////////////////////////////////// using System; using System.IO.Compression; using PDNWrapper; namespace PhotoshopFile.Compression { internal static class ImageDataFactory { /// /// Creates an ImageData object to compress or decompress image data. /// /// The Channel associated with the image data. /// The image data to be decompressed, or null if /// image data is to be compressed. public static ImageData Create(Channel channel, byte[] data) { var bitDepth = channel.Layer.PsdFile.BitDepth; ImageData imageData; switch (channel.ImageCompression) { case ImageCompression.Raw: imageData = new RawImage(data, channel.Rect.Size, bitDepth); break; case ImageCompression.Rle: imageData = new RleImage(data, channel.RleRowLengths, channel.Rect.Size, bitDepth); break; case ImageCompression.Zip: // Photoshop treats 32-bit Zip as 32-bit ZipPrediction imageData = (bitDepth == 32) ? CreateZipPredict(data, channel.Rect.Size, bitDepth) : new ZipImage(data, channel.Rect.Size, bitDepth); break; case ImageCompression.ZipPrediction: imageData = CreateZipPredict(data, channel.Rect.Size, bitDepth); break; default: throw new PsdInvalidException("Unknown image compression method."); } // Reverse endianness of multi-byte image data imageData = WrapEndianness(imageData); return imageData; } private static ImageData CreateZipPredict(byte[] data, Size size, int bitDepth) { switch (bitDepth) { case 16: return new ZipPredict16Image(data, size); case 32: return new ZipPredict32Image(data, size); default: throw new PsdInvalidException( "ZIP with prediction is only available for 16 and 32 bit depths."); } } private static ImageData WrapEndianness(ImageData imageData) { // Single-byte image does not require endianness reversal if (imageData.BitDepth <= 8) { return imageData; } // Bytes will be reordered by the compressor, so no wrapper is needed if ((imageData is ZipPredict16Image) || (imageData is ZipPredict32Image)) { return imageData; } return new EndianReverser(imageData); } } }