Browse Source

Decoder now performs faster than main

af/merge-core
James Jackson-South 10 years ago
parent
commit
4b2e408723
  1. 179
      src/ImageSharp/Formats/Gif/GifDecoderCore.cs

179
src/ImageSharp/Formats/Gif/GifDecoderCore.cs

@ -312,12 +312,11 @@ namespace ImageSharp.Formats
TColor[] lastFrame = null; TColor[] lastFrame = null;
if (this.graphicsControlExtension != null && if (this.graphicsControlExtension != null
this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToPrevious) && this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToPrevious)
{ {
lastFrame = new TColor[imageWidth * imageHeight]; lastFrame = new TColor[imageWidth * imageHeight];
// Array.Copy(this.currentFrame, lastFrame, lastFrame.Length);
using (PixelAccessor<TColor, TPacked> lastPixels = lastFrame.Lock<TColor, TPacked>(imageWidth, imageHeight)) using (PixelAccessor<TColor, TPacked> lastPixels = lastFrame.Lock<TColor, TPacked>(imageWidth, imageHeight))
using (PixelAccessor<TColor, TPacked> currentPixels = this.currentFrame.Lock<TColor, TPacked>(imageWidth, imageHeight)) using (PixelAccessor<TColor, TPacked> currentPixels = this.currentFrame.Lock<TColor, TPacked>(imageWidth, imageHeight))
{ {
@ -325,126 +324,124 @@ namespace ImageSharp.Formats
} }
} }
int offset, i = 0; int i = 0;
int interlacePass = 0; // The interlace pass int interlacePass = 0; // The interlace pass
int interlaceIncrement = 8; // The interlacing line increment int interlaceIncrement = 8; // The interlacing line increment
int interlaceY = 0; // The current interlaced line int interlaceY = 0; // The current interlaced line
for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++) // Lock the current image pixels for fast acces.
using (PixelAccessor<TColor, TPacked> currentPixels = this.currentFrame.Lock<TColor, TPacked>(imageWidth, imageHeight))
{ {
// Check if this image is interlaced. for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++)
int writeY; // the target y offset to write to
if (descriptor.InterlaceFlag)
{ {
// If so then we read lines at predetermined offsets. // Check if this image is interlaced.
// When an entire image height worth of offset lines has been read we consider this a pass. int writeY; // the target y offset to write to
// With each pass the number of offset lines changes and the starting line changes. if (descriptor.InterlaceFlag)
if (interlaceY >= descriptor.Height)
{ {
interlacePass++; // If so then we read lines at predetermined offsets.
switch (interlacePass) // 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 (interlaceY >= descriptor.Height)
{ {
case 1: interlacePass++;
interlaceY = 4; switch (interlacePass)
break; {
case 2: case 1:
interlaceY = 2; interlaceY = 4;
interlaceIncrement = 4; break;
break; case 2:
case 3: interlaceY = 2;
interlaceY = 1; interlaceIncrement = 4;
interlaceIncrement = 2; break;
break; case 3:
interlaceY = 1;
interlaceIncrement = 2;
break;
}
} }
}
writeY = interlaceY + descriptor.Top;
interlaceY += interlaceIncrement; writeY = interlaceY + descriptor.Top;
}
else
{
writeY = y;
}
for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++)
{
offset = (writeY * imageWidth) + x;
int index = indices[i];
if (this.graphicsControlExtension == null || interlaceY += interlaceIncrement;
this.graphicsControlExtension.TransparencyFlag == false || }
this.graphicsControlExtension.TransparencyIndex != index) else
{ {
// Stored in r-> g-> b-> a order. writeY = y;
int indexOffset = index * 3;
TColor pixel = default(TColor);
pixel.PackFromBytes(colorTable[indexOffset], colorTable[indexOffset + 1], colorTable[indexOffset + 2], 255);
this.currentFrame[offset] = pixel;
} }
i++; for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++)
} {
} int index = indices[i];
TColor[] pixels = new TColor[imageWidth * imageHeight];
// Array.Copy(this.currentFrame, pixels, pixels.Length); if (this.graphicsControlExtension == null
using (PixelAccessor<TColor, TPacked> newPixels = pixels.Lock<TColor, TPacked>(imageWidth, imageHeight)) || this.graphicsControlExtension.TransparencyFlag == false
using (PixelAccessor<TColor, TPacked> currentPixels = this.currentFrame.Lock<TColor, TPacked>(imageWidth, imageHeight)) || this.graphicsControlExtension.TransparencyIndex != index)
{ {
currentPixels.CopyImage(newPixels); // Stored in r-> g-> b-> a order.
} int indexOffset = index * 3;
TColor pixel = default(TColor);
pixel.PackFromBytes(colorTable[indexOffset], colorTable[indexOffset + 1], colorTable[indexOffset + 2], 255);
currentPixels[x, writeY] = pixel;
}
ImageBase<TColor, TPacked> currentImage; i++;
}
}
if (this.decodedImage.Pixels == null) TColor[] pixels = new TColor[imageWidth * imageHeight];
{
currentImage = this.decodedImage;
currentImage.SetPixels(imageWidth, imageHeight, pixels);
currentImage.Quality = colorTableLength / 3;
if (this.graphicsControlExtension != null && this.graphicsControlExtension.DelayTime > 0) using (PixelAccessor<TColor, TPacked> newPixels = pixels.Lock<TColor, TPacked>(imageWidth, imageHeight))
{ {
this.decodedImage.FrameDelay = this.graphicsControlExtension.DelayTime; currentPixels.CopyImage(newPixels);
} }
}
else
{
ImageFrame<TColor, TPacked> frame = new ImageFrame<TColor, TPacked>();
currentImage = frame; ImageBase<TColor, TPacked> currentImage;
currentImage.SetPixels(imageWidth, imageHeight, pixels);
currentImage.Quality = colorTableLength / 3;
if (this.graphicsControlExtension != null && this.graphicsControlExtension.DelayTime > 0) if (this.decodedImage.Pixels == null)
{ {
currentImage.FrameDelay = this.graphicsControlExtension.DelayTime; currentImage = this.decodedImage;
currentImage.SetPixels(imageWidth, imageHeight, pixels);
currentImage.Quality = colorTableLength / 3;
if (this.graphicsControlExtension != null && this.graphicsControlExtension.DelayTime > 0)
{
this.decodedImage.FrameDelay = this.graphicsControlExtension.DelayTime;
}
} }
else
{
ImageFrame<TColor, TPacked> frame = new ImageFrame<TColor, TPacked>();
this.decodedImage.Frames.Add(frame); currentImage = frame;
} currentImage.SetPixels(imageWidth, imageHeight, pixels);
currentImage.Quality = colorTableLength / 3;
if (this.graphicsControlExtension != null) if (this.graphicsControlExtension != null && this.graphicsControlExtension.DelayTime > 0)
{ {
if (this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToBackground) currentImage.FrameDelay = this.graphicsControlExtension.DelayTime;
}
this.decodedImage.Frames.Add(frame);
}
if (this.graphicsControlExtension != null)
{ {
for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++) if (this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToBackground)
{ {
for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++) for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++)
{ {
offset = (y * imageWidth) + x; for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++)
{
// Stored in r-> g-> b-> a order. currentPixels[x, y] = default(TColor);
this.currentFrame[offset] = default(TColor); }
} }
} }
else if (this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToPrevious)
{
this.currentFrame = lastFrame;
}
} }
else if (this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToPrevious) } // End lock
{
this.currentFrame = lastFrame;
}
}
} }
} }
} }
Loading…
Cancel
Save