Skip to content

Commit ddff78b

Browse files
authored
Merge pull request #125 from iron-software/DW-30-optimize-ExtractAlphaData-and-PrepareByteArray
Dw 30 optimize extract alpha data and prepare byte array
2 parents ffd50f0 + 3872ae2 commit ddff78b

File tree

1 file changed

+37
-17
lines changed
  • IronSoftware.Drawing/IronSoftware.Drawing.Common

1 file changed

+37
-17
lines changed

IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -828,20 +828,25 @@ public byte[] ExtractAlphaData()
828828
{
829829
if (BitsPerPixel == 32)
830830
{
831-
var alpha = new List<byte>(Image.Width * Image.Height);
831+
var alpha = new byte[Image.Width * Image.Height];
832+
int alphaIndex = 0;
832833
using var rgbaImage = Image is Image<SixLabors.ImageSharp.PixelFormats.Rgba32> image
833834
? image
834835
: Image.CloneAs<SixLabors.ImageSharp.PixelFormats.Rgba32>();
835836
rgbaImage.ProcessPixelRows(accessor =>
836837
{
837838
for (int y = 0; y < accessor.Height; y++)
838839
{
839-
Span<SixLabors.ImageSharp.PixelFormats.Rgba32> pixelRow = accessor.GetRowSpan(y);
840-
841-
for (int x = 0; x < pixelRow.Length; x++)
840+
// Get the row as a span of Rgba32.
841+
Span<Rgba32> pixelRow = accessor.GetRowSpan(y);
842+
// Interpret the row as a span of bytes.
843+
Span<byte> rowBytes = MemoryMarshal.AsBytes(pixelRow);
844+
845+
// Each pixel is 4 bytes: R, G, B, A.
846+
// The alpha channel is the fourth byte (index 3, 7, 11, ...).
847+
for (int i = 3; i < rowBytes.Length; i += 4)
842848
{
843-
SixLabors.ImageSharp.PixelFormats.Rgba32 pixel = pixelRow[x];
844-
alpha.Add(pixel.A);
849+
alpha[alphaIndex++] = rowBytes[i];
845850
}
846851
}
847852
});
@@ -2332,20 +2337,35 @@ private bool IsThumbnail(Tiff tiff)
23322337

23332338
private ReadOnlySpan<byte> PrepareByteArray(Image<Rgba32> bmp, int[] raster, int width, int height)
23342339
{
2335-
byte[] bits = new byte[GetStride(bmp) * height];
2340+
int stride = GetStride(bmp);
2341+
byte[] bits = new byte[stride * height];
23362342

2337-
for (int y = 0; y < height; y++)
2343+
// If no extra padding exists, copy entire rows at once.
2344+
if (stride == width * 4 && true)
23382345
{
2339-
int rasterOffset = y * width;
2340-
int bitsOffset = (height - y - 1) * GetStride(bmp);
2341-
2342-
for (int x = 0; x < width; x++)
2346+
int bytesPerRow = stride;
2347+
for (int y = 0; y < height; y++)
2348+
{
2349+
int srcByteIndex = y * bytesPerRow;
2350+
int destByteIndex = (height - y - 1) * bytesPerRow;
2351+
Buffer.BlockCopy(raster, srcByteIndex, bits, destByteIndex, bytesPerRow);
2352+
}
2353+
}
2354+
else
2355+
{
2356+
// Fallback to per-pixel processing if stride includes padding.
2357+
for (int y = 0; y < height; y++)
23432358
{
2344-
int rgba = raster[rasterOffset++];
2345-
bits[bitsOffset++] = (byte)(rgba & 0xff); // R
2346-
bits[bitsOffset++] = (byte)((rgba >> 8) & 0xff); // G
2347-
bits[bitsOffset++] = (byte)((rgba >> 16) & 0xff); // B
2348-
bits[bitsOffset++] = (byte)((rgba >> 24) & 0xff); // A
2359+
int rasterOffset = y * width;
2360+
int bitsOffset = (height - y - 1) * stride;
2361+
for (int x = 0; x < width; x++)
2362+
{
2363+
int rgba = raster[rasterOffset++];
2364+
bits[bitsOffset++] = (byte)(rgba & 0xff); // R
2365+
bits[bitsOffset++] = (byte)((rgba >> 8) & 0xff); // G
2366+
bits[bitsOffset++] = (byte)((rgba >> 16) & 0xff); // B
2367+
bits[bitsOffset++] = (byte)((rgba >> 24) & 0xff); // A
2368+
}
23492369
}
23502370
}
23512371

0 commit comments

Comments
 (0)