|
|
|
@ -42,9 +42,9 @@ namespace ImageSharp.Formats |
|
|
|
private int globalColorTableLength; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The next frame.
|
|
|
|
/// The previous frame.
|
|
|
|
/// </summary>
|
|
|
|
private ImageFrame<TColor> nextFrame; |
|
|
|
private ImageFrame<TColor> previousFrame; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The area to restore.
|
|
|
|
@ -319,7 +319,7 @@ namespace ImageSharp.Formats |
|
|
|
|
|
|
|
ImageBase<TColor> image; |
|
|
|
|
|
|
|
if (this.nextFrame == null) |
|
|
|
if (this.previousFrame == null) |
|
|
|
{ |
|
|
|
image = this.decodedImage; |
|
|
|
|
|
|
|
@ -333,10 +333,10 @@ namespace ImageSharp.Formats |
|
|
|
if (this.graphicsControlExtension != null && |
|
|
|
this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToPrevious) |
|
|
|
{ |
|
|
|
previousFrame = this.nextFrame; |
|
|
|
previousFrame = this.previousFrame; |
|
|
|
} |
|
|
|
|
|
|
|
currentFrame = this.nextFrame.Clone(); |
|
|
|
currentFrame = this.previousFrame.Clone(); |
|
|
|
|
|
|
|
image = currentFrame; |
|
|
|
|
|
|
|
@ -357,85 +357,70 @@ namespace ImageSharp.Formats |
|
|
|
|
|
|
|
using (PixelAccessor<TColor> pixelAccessor = image.Lock()) |
|
|
|
{ |
|
|
|
using (PixelArea<TColor> pixelRow = new PixelArea<TColor>(imageWidth, ComponentOrder.XYZW)) |
|
|
|
for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++) |
|
|
|
{ |
|
|
|
for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++) |
|
|
|
// Check if this image is interlaced.
|
|
|
|
int writeY; // the target y offset to write to
|
|
|
|
if (descriptor.InterlaceFlag) |
|
|
|
{ |
|
|
|
// Check if this image is interlaced.
|
|
|
|
int writeY; // the target y offset to write to
|
|
|
|
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 (interlaceY >= descriptor.Height) |
|
|
|
{ |
|
|
|
// 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 (interlaceY >= descriptor.Height) |
|
|
|
interlacePass++; |
|
|
|
switch (interlacePass) |
|
|
|
{ |
|
|
|
interlacePass++; |
|
|
|
switch (interlacePass) |
|
|
|
{ |
|
|
|
case 1: |
|
|
|
interlaceY = 4; |
|
|
|
break; |
|
|
|
case 2: |
|
|
|
interlaceY = 2; |
|
|
|
interlaceIncrement = 4; |
|
|
|
break; |
|
|
|
case 3: |
|
|
|
interlaceY = 1; |
|
|
|
interlaceIncrement = 2; |
|
|
|
break; |
|
|
|
} |
|
|
|
case 1: |
|
|
|
interlaceY = 4; |
|
|
|
break; |
|
|
|
case 2: |
|
|
|
interlaceY = 2; |
|
|
|
interlaceIncrement = 4; |
|
|
|
break; |
|
|
|
case 3: |
|
|
|
interlaceY = 1; |
|
|
|
interlaceIncrement = 2; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
writeY = interlaceY + descriptor.Top; |
|
|
|
writeY = interlaceY + descriptor.Top; |
|
|
|
|
|
|
|
interlaceY += interlaceIncrement; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
writeY = y; |
|
|
|
} |
|
|
|
interlaceY += interlaceIncrement; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
writeY = y; |
|
|
|
} |
|
|
|
|
|
|
|
pixelAccessor.CopyTo(pixelRow, writeY, descriptor.Left); |
|
|
|
for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++) |
|
|
|
{ |
|
|
|
int index = indices[i]; |
|
|
|
|
|
|
|
byte* pixelBase = pixelRow.PixelBase; |
|
|
|
for (int x = 0; x < descriptor.Width; x++) |
|
|
|
if (this.graphicsControlExtension == null || |
|
|
|
this.graphicsControlExtension.TransparencyFlag == false || |
|
|
|
this.graphicsControlExtension.TransparencyIndex != index) |
|
|
|
{ |
|
|
|
int index = indices[i]; |
|
|
|
|
|
|
|
if (this.graphicsControlExtension == null || |
|
|
|
this.graphicsControlExtension.TransparencyFlag == false || |
|
|
|
this.graphicsControlExtension.TransparencyIndex != index) |
|
|
|
{ |
|
|
|
int indexOffset = index * 3; |
|
|
|
*(pixelBase + 0) = colorTable[indexOffset]; |
|
|
|
*(pixelBase + 1) = colorTable[indexOffset + 1]; |
|
|
|
*(pixelBase + 2) = colorTable[indexOffset + 2]; |
|
|
|
*(pixelBase + 3) = 255; |
|
|
|
|
|
|
|
// TODO: This is actually 200us faster in benchmarking.
|
|
|
|
// int indexOffset = index * 3;
|
|
|
|
// TColor pixel = default(TColor);
|
|
|
|
// pixel.PackFromBytes(colorTable[indexOffset], colorTable[indexOffset + 1], colorTable[indexOffset + 2], 255);
|
|
|
|
// currentPixels[x, writeY] = pixel;
|
|
|
|
} |
|
|
|
int indexOffset = index * 3; |
|
|
|
|
|
|
|
i++; |
|
|
|
pixelBase += 4; |
|
|
|
TColor pixel = default(TColor); |
|
|
|
pixel.PackFromBytes(colorTable[indexOffset], colorTable[indexOffset + 1], colorTable[indexOffset + 2], 255); |
|
|
|
pixelAccessor[x, writeY] = pixel; |
|
|
|
} |
|
|
|
|
|
|
|
pixelAccessor.CopyFrom(pixelRow, writeY, descriptor.Left); |
|
|
|
i++; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (previousFrame != null) |
|
|
|
{ |
|
|
|
this.nextFrame = previousFrame; |
|
|
|
this.previousFrame = previousFrame; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
this.nextFrame = currentFrame == null ? this.decodedImage.ToFrame() : currentFrame.Clone(); |
|
|
|
this.previousFrame = currentFrame == null ? this.decodedImage.ToFrame() : currentFrame; |
|
|
|
|
|
|
|
if (this.graphicsControlExtension != null && |
|
|
|
this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToBackground) |
|
|
|
|