ZipPredict16Image.cs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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-2017 Tao Yue
  9. //
  10. // See LICENSE.txt for complete licensing and attribution information.
  11. //
  12. /////////////////////////////////////////////////////////////////////////////////
  13. using System;
  14. using System.Drawing;
  15. using System.IO.Compression;
  16. namespace PhotoshopFile.Compression
  17. {
  18. public class ZipPredict16Image : ImageData
  19. {
  20. private ImageData zipImage;
  21. protected override bool AltersWrittenData => true;
  22. public ZipPredict16Image(byte[] zipData, Size size)
  23. : base(size, 16)
  24. {
  25. // 16-bitdepth images are delta-encoded word-by-word. The deltas
  26. // are thus big-endian and must be reversed for further processing.
  27. var zipRawImage = new ZipImage(zipData, size, 16);
  28. zipImage = new EndianReverser(zipRawImage);
  29. }
  30. internal override void Read(byte[] buffer)
  31. {
  32. if (buffer.Length == 0)
  33. {
  34. return;
  35. }
  36. zipImage.Read(buffer);
  37. unsafe
  38. {
  39. fixed (byte* ptrData = &buffer[0])
  40. {
  41. Unpredict((UInt16*)ptrData);
  42. }
  43. }
  44. }
  45. public override byte[] ReadCompressed()
  46. {
  47. return zipImage.ReadCompressed();
  48. }
  49. internal override void WriteInternal(byte[] array)
  50. {
  51. if (array.Length == 0)
  52. {
  53. return;
  54. }
  55. unsafe
  56. {
  57. fixed (byte* ptrData = &array[0])
  58. {
  59. Predict((UInt16*)ptrData);
  60. }
  61. }
  62. zipImage.WriteInternal(array);
  63. }
  64. unsafe private void Predict(UInt16* ptrData)
  65. {
  66. // Delta-encode each row
  67. for (int i = 0; i < Size.Height; i++)
  68. {
  69. UInt16* ptrDataRow = ptrData;
  70. UInt16* ptrDataRowEnd = ptrDataRow + Size.Width;
  71. // Start with the last column in the row
  72. ptrData = ptrDataRowEnd - 1;
  73. while (ptrData > ptrDataRow)
  74. {
  75. *ptrData -= *(ptrData - 1);
  76. ptrData--;
  77. }
  78. ptrData = ptrDataRowEnd;
  79. }
  80. }
  81. /// <summary>
  82. /// Unpredicts the decompressed, native-endian image data.
  83. /// </summary>
  84. unsafe private void Unpredict(UInt16* ptrData)
  85. {
  86. // Delta-decode each row
  87. for (int i = 0; i < Size.Height; i++)
  88. {
  89. UInt16* ptrDataRowEnd = ptrData + Size.Width;
  90. // Start with column index 1 on each row
  91. ptrData++;
  92. while (ptrData < ptrDataRowEnd)
  93. {
  94. *ptrData += *(ptrData - 1);
  95. ptrData++;
  96. }
  97. // Advance pointer to the next row
  98. ptrData = ptrDataRowEnd;
  99. }
  100. }
  101. }
  102. }