private void ReadFrameColors(byte[] indices, byte[] colorTable, GifImageDescriptor descriptor)
{
int imageWidth = _logicalScreenDescriptor.Width;
int imageHeight = _logicalScreenDescriptor.Height;
if (_currentFrame == null)
{
_currentFrame = new byte[imageWidth * imageHeight * 4];
}
byte[] lastFrame = null;
if (_graphicsControl != null &&
_graphicsControl.DisposalMethod == DisposalMethod.RestoreToPrevious)
{
lastFrame = new byte[imageWidth * imageHeight * 4];
Array.Copy(_currentFrame, lastFrame, lastFrame.Length);
}
int offset = 0, i = 0, index = -1;
int iPass = 0; // the interlace pass
int iInc = 8; // the interlacing line increment
int iY = 0; // the current interlaced line
int writeY = 0; // the target y offset to write to
for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++)
{
// Check if this image is interlaced.
if (descriptor.InterlaceFlag)
{
// If so then we read lines at predetermined offsets.
// When an entire image height worth of offset lines has been read we consider this a pass.
// With each pass the number of offset lines changes and the starting line changes.
if (iY >= descriptor.Height)
{
iPass++;
switch (iPass)
{
case 1:
iY = 4;
break;
case 2:
iY = 2;
iInc = 4;
break;
case 3:
iY = 1;
iInc = 2;
break;
}
}
writeY = iY + descriptor.Top;
iY += iInc;
}
else
{
writeY = y;
}
//TODO: review performance here
for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++)
{
offset = writeY * imageWidth + x;
index = indices[i];
if (_graphicsControl == null ||
_graphicsControl.TransparencyFlag == false ||
_graphicsControl.TransparencyIndex != index)
{
_currentFrame[offset * 4 + 0] = colorTable[index * 3 + 0];
_currentFrame[offset * 4 + 1] = colorTable[index * 3 + 1];
_currentFrame[offset * 4 + 2] = colorTable[index * 3 + 2];
_currentFrame[offset * 4 + 3] = (byte)255;
}
i++;
}
}
byte[] pixels = new byte[imageWidth * imageHeight * 4];
Array.Copy(_currentFrame, pixels, pixels.Length);
SimpleImage currentImage = null;
if (_image.Pixels == null)
{
currentImage = _image;
currentImage.SetPixels(imageWidth, imageHeight, pixels);
}
else
{
SimpleImage frame = new SimpleImage();
currentImage = frame;
currentImage.SetPixels(imageWidth, imageHeight, pixels);
_image.Frames.Add(frame);
}
if (_graphicsControl != null)
{
if (_graphicsControl.DelayTime > 0)
{
ExtraImageInfo extraImgInfo = currentImage.ExtraImageInfo;
if (extraImgInfo == null)
{
currentImage.ExtraImageInfo = extraImgInfo = new ExtraImageInfo();
}
extraImgInfo.DelayTime = _graphicsControl.DelayTime;
}
if (_graphicsControl.DisposalMethod == DisposalMethod.RestoreToBackground)
{
for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++)
{
for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++)
{
offset = y * imageWidth + x;
_currentFrame[offset * 4 + 0] = 0;
_currentFrame[offset * 4 + 1] = 0;
_currentFrame[offset * 4 + 2] = 0;
_currentFrame[offset * 4 + 3] = 0;
}
}
}
else if (_graphicsControl.DisposalMethod == DisposalMethod.RestoreToPrevious)
{
_currentFrame = lastFrame;
}
}
}