Singularity/Library/PackageCache/com.unity.2d.psdimporter@6.0.7/Editor/PSDPlugin/PsdFile/RleReader.cs
2024-05-06 11:45:45 -07:00

107 lines
3.7 KiB
C#

/////////////////////////////////////////////////////////////////////////////////
//
// 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-2013 Tao Yue
//
// Portions of this file are provided under the BSD 3-clause License:
// Copyright (c) 2006, Jonas Beckeman
//
// See LICENSE.txt for complete licensing and attribution information.
//
/////////////////////////////////////////////////////////////////////////////////
using System;
using System.Diagnostics;
using System.IO;
namespace PhotoshopFile
{
internal class RleReader
{
private Stream stream;
public RleReader(Stream stream)
{
this.stream = stream;
}
/// <summary>
/// Decodes a PackBits RLE stream.
/// </summary>
/// <param name="buffer">Output buffer for decoded data.</param>
/// <param name="offset">Offset at which to begin writing.</param>
/// <param name="count">Number of bytes to decode from the stream.</param>
public int Read(byte[] buffer, int offset, int count)
{
if (!Util.CheckBufferBounds(buffer, offset, count))
throw new ArgumentOutOfRangeException();
// Pin the entire buffer now, so that we don't keep pinning and unpinning
// for each RLE packet.
var ptrBuffer = buffer;
//fixed (byte* ptrBuffer = &buffer[0])
{
int bytesLeft = count;
int bufferIdx = offset;
while (bytesLeft > 0)
{
// ReadByte returns an unsigned byte, but we want a signed byte.
var flagCounter = unchecked((sbyte)stream.ReadByte());
// Raw packet
if (flagCounter > 0)
{
var readLength = flagCounter + 1;
if (bytesLeft < readLength)
throw new RleException("Raw packet overruns the decode window.");
stream.Read(buffer, bufferIdx, readLength);
bufferIdx += readLength;
bytesLeft -= readLength;
}
// RLE packet
else if (flagCounter > -128)
{
var runLength = 1 - flagCounter;
var byteValue = (byte)stream.ReadByte();
if (runLength > bytesLeft)
throw new RleException("RLE packet overruns the decode window.");
//byte* ptr = ptrBuffer + bufferIdx;
//byte* ptrEnd = ptr + runLength;
//while (ptr < ptrEnd)
//{
// *ptr = byteValue;
// ptr++;
//}
int start = 0;
while (start < runLength)
{
ptrBuffer[bufferIdx + start] = byteValue;
start++;
}
bufferIdx += runLength;
bytesLeft -= runLength;
}
else
{
// The canonical PackBits algorithm will never emit 0x80 (-128), but
// some programs do. Simply skip over the byte.
}
}
Debug.Assert(bytesLeft == 0);
return count - bytesLeft;
}
}
}
}