ImageDataFactory.cs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Photoshop PSD FileType Plugin for Paint.NET
  4. // http://psdplugin.codeplex.com/
  5. //
  6. // This software is provided under the MIT License:
  7. // Copyright (c) 2006-2007 Frank Blumenberg
  8. // Copyright (c) 2010-2016 Tao Yue
  9. //
  10. // See LICENSE.txt for complete licensing and attribution information.
  11. //
  12. /////////////////////////////////////////////////////////////////////////////////
  13. using System;
  14. using System.IO.Compression;
  15. using System.Drawing;
  16. namespace PhotoshopFile.Compression
  17. {
  18. public static class ImageDataFactory
  19. {
  20. /// <summary>
  21. /// Creates an ImageData object to compress or decompress image data.
  22. /// </summary>
  23. /// <param name="channel">The Channel associated with the image data.</param>
  24. /// <param name="data">The image data to be decompressed, or null if
  25. /// image data is to be compressed.</param>
  26. public static ImageData Create(Channel channel, byte[] data)
  27. {
  28. var bitDepth = channel.Layer.PsdFile.BitDepth;
  29. ImageData imageData;
  30. switch (channel.ImageCompression)
  31. {
  32. case ImageCompression.Raw:
  33. imageData = new RawImage(data, channel.Rect.Size, bitDepth);
  34. break;
  35. case ImageCompression.Rle:
  36. imageData = new RleImage(data, channel.RleRowLengths,
  37. channel.Rect.Size, bitDepth);
  38. break;
  39. case ImageCompression.Zip:
  40. // Photoshop treats 32-bit Zip as 32-bit ZipPrediction
  41. imageData = (bitDepth == 32)
  42. ? CreateZipPredict(data, channel.Rect.Size, bitDepth)
  43. : new ZipImage(data, channel.Rect.Size, bitDepth);
  44. break;
  45. case ImageCompression.ZipPrediction:
  46. imageData = CreateZipPredict(data, channel.Rect.Size, bitDepth);
  47. break;
  48. default:
  49. throw new PsdInvalidException("Unknown image compression method.");
  50. }
  51. // Reverse endianness of multi-byte image data
  52. imageData = WrapEndianness(imageData);
  53. return imageData;
  54. }
  55. private static ImageData CreateZipPredict(byte[] data, Size size,
  56. int bitDepth)
  57. {
  58. switch (bitDepth)
  59. {
  60. case 16:
  61. return new ZipPredict16Image(data, size);
  62. case 32:
  63. return new ZipPredict32Image(data, size);
  64. default:
  65. throw new PsdInvalidException(
  66. "ZIP with prediction is only available for 16 and 32 bit depths.");
  67. }
  68. }
  69. private static ImageData WrapEndianness(ImageData imageData)
  70. {
  71. // Single-byte image does not require endianness reversal
  72. if (imageData.BitDepth <= 8)
  73. {
  74. return imageData;
  75. }
  76. // Bytes will be reordered by the compressor, so no wrapper is needed
  77. if ((imageData is ZipPredict16Image) || (imageData is ZipPredict32Image))
  78. {
  79. return imageData;
  80. }
  81. return new EndianReverser(imageData);
  82. }
  83. }
  84. }