ZipImage.cs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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 PDNWrapper;
  15. using System.IO;
  16. using System.IO.Compression;
  17. namespace PhotoshopFile.Compression
  18. {
  19. internal class ZipImage : ImageData
  20. {
  21. private MemoryStream zipDataStream;
  22. private DeflateStream zipStream;
  23. protected override bool AltersWrittenData
  24. {
  25. get { return false; }
  26. }
  27. public ZipImage(byte[] data, Size size, int bitDepth)
  28. : base(size, bitDepth)
  29. {
  30. if (data == null)
  31. {
  32. InitCompress();
  33. }
  34. else
  35. {
  36. InitDecompress(data);
  37. }
  38. }
  39. private void InitCompress()
  40. {
  41. zipDataStream = new MemoryStream();
  42. // Write 2-byte zlib (RFC 1950) header
  43. //
  44. // CMF Compression Method and flags:
  45. // CM 0:3 = 8 = deflate
  46. // CINFO 4:7 = 4 = undefined, RFC 1950 only defines CINFO = 8
  47. //
  48. // FLG Flags:
  49. // FCHECK 0:4 = 9 = check bits for CMF and FLG
  50. // FDICT 5 = 0 = no preset dictionary
  51. // FLEVEL 6:7 = 2 = default compression level
  52. zipDataStream.WriteByte(0x48);
  53. zipDataStream.WriteByte(0x89);
  54. zipStream = new DeflateStream(zipDataStream, CompressionMode.Compress,
  55. true);
  56. }
  57. private void InitDecompress(byte[] data)
  58. {
  59. zipDataStream = new MemoryStream(data);
  60. // .NET implements Deflate (RFC 1951) but not zlib (RFC 1950),
  61. // so we have to skip the first two bytes.
  62. zipDataStream.ReadByte();
  63. zipDataStream.ReadByte();
  64. zipStream = new DeflateStream(zipDataStream, CompressionMode.Decompress,
  65. true);
  66. }
  67. internal override void Read(byte[] buffer)
  68. {
  69. var bytesToRead = (long)Size.Height * BytesPerRow;
  70. Util.CheckByteArrayLength(bytesToRead);
  71. var bytesRead = zipStream.Read(buffer, 0, (int)bytesToRead);
  72. if (bytesRead != bytesToRead)
  73. {
  74. throw new Exception("ZIP stream was not fully decompressed.");
  75. }
  76. }
  77. public override byte[] ReadCompressed()
  78. {
  79. // Write out the last block. (Flush leaves the last block open.)
  80. zipStream.Close();
  81. // Do not write the zlib header when the image data is empty
  82. var result = (zipDataStream.Length == 2)
  83. ? new byte[0]
  84. : zipDataStream.ToArray();
  85. return result;
  86. }
  87. }
  88. }