暫無描述
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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-2013 Tao Yue
  9. //
  10. // Portions of this file are provided under the BSD 3-clause License:
  11. // Copyright (c) 2006, Jonas Beckeman
  12. //
  13. // See LICENSE.txt for complete licensing and attribution information.
  14. //
  15. /////////////////////////////////////////////////////////////////////////////////
  16. using System;
  17. using System.Diagnostics;
  18. using System.IO;
  19. namespace PhotoshopFile
  20. {
  21. internal class RleReader
  22. {
  23. private Stream stream;
  24. public RleReader(Stream stream)
  25. {
  26. this.stream = stream;
  27. }
  28. /// <summary>
  29. /// Decodes a PackBits RLE stream.
  30. /// </summary>
  31. /// <param name="buffer">Output buffer for decoded data.</param>
  32. /// <param name="offset">Offset at which to begin writing.</param>
  33. /// <param name="count">Number of bytes to decode from the stream.</param>
  34. public int Read(byte[] buffer, int offset, int count)
  35. {
  36. if (!Util.CheckBufferBounds(buffer, offset, count))
  37. throw new ArgumentOutOfRangeException();
  38. // Pin the entire buffer now, so that we don't keep pinning and unpinning
  39. // for each RLE packet.
  40. var ptrBuffer = buffer;
  41. //fixed (byte* ptrBuffer = &buffer[0])
  42. {
  43. int bytesLeft = count;
  44. int bufferIdx = offset;
  45. while (bytesLeft > 0)
  46. {
  47. // ReadByte returns an unsigned byte, but we want a signed byte.
  48. var flagCounter = unchecked((sbyte)stream.ReadByte());
  49. // Raw packet
  50. if (flagCounter > 0)
  51. {
  52. var readLength = flagCounter + 1;
  53. if (bytesLeft < readLength)
  54. throw new RleException("Raw packet overruns the decode window.");
  55. stream.Read(buffer, bufferIdx, readLength);
  56. bufferIdx += readLength;
  57. bytesLeft -= readLength;
  58. }
  59. // RLE packet
  60. else if (flagCounter > -128)
  61. {
  62. var runLength = 1 - flagCounter;
  63. var byteValue = (byte)stream.ReadByte();
  64. if (runLength > bytesLeft)
  65. throw new RleException("RLE packet overruns the decode window.");
  66. //byte* ptr = ptrBuffer + bufferIdx;
  67. //byte* ptrEnd = ptr + runLength;
  68. //while (ptr < ptrEnd)
  69. //{
  70. // *ptr = byteValue;
  71. // ptr++;
  72. //}
  73. int start = 0;
  74. while (start < runLength)
  75. {
  76. ptrBuffer[bufferIdx + start] = byteValue;
  77. start++;
  78. }
  79. bufferIdx += runLength;
  80. bytesLeft -= runLength;
  81. }
  82. else
  83. {
  84. // The canonical PackBits algorithm will never emit 0x80 (-128), but
  85. // some programs do. Simply skip over the byte.
  86. }
  87. }
  88. Debug.Assert(bytesLeft == 0);
  89. return count - bytesLeft;
  90. }
  91. }
  92. }
  93. }