/////////////////////////////////////////////////////////////////////////////////
//
// 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);
}
}
}