|
|
@@ -1,5 +1,7 @@
|
|
|
using System;
|
|
|
+using System.Runtime.InteropServices;
|
|
|
using Avalonia.Platform;
|
|
|
+using Avalonia.Platform.Internal;
|
|
|
namespace Avalonia.Media.Imaging;
|
|
|
|
|
|
internal static unsafe class PixelFormatTranscoder
|
|
|
@@ -15,140 +17,14 @@ internal static unsafe class PixelFormatTranscoder
|
|
|
PixelFormat destFormat,
|
|
|
AlphaFormat destAlphaFormat)
|
|
|
{
|
|
|
- var reader = GetReader(srcFormat);
|
|
|
- var writer = GetWriter(destFormat);
|
|
|
+ var pixelCount = srcSize.Width * srcSize.Height;
|
|
|
+ var bufferSize = pixelCount * Marshal.SizeOf<Rgba8888Pixel>();
|
|
|
+ using var blob = new UnmanagedBlob(bufferSize);
|
|
|
+
|
|
|
+ var pixels = new Span<Rgba8888Pixel>((void*)blob.Address, pixelCount);
|
|
|
|
|
|
- var w = srcSize.Width;
|
|
|
- var h = srcSize.Height;
|
|
|
+ PixelFormatReader.Read(pixels, source, srcSize, sourceStride, srcFormat);
|
|
|
|
|
|
- for (var y = 0; y < h; y++)
|
|
|
- {
|
|
|
- reader.Reset(source + sourceStride * y);
|
|
|
-
|
|
|
- writer.Reset(dest + destStride * y);
|
|
|
-
|
|
|
- for (var x = 0; x < w; x++)
|
|
|
- {
|
|
|
- writer.WriteNext(GetConvertedPixel(reader.ReadNext(), srcAlphaFormat, destAlphaFormat));
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private static Rgba8888Pixel GetConvertedPixel(Rgba8888Pixel pixel, AlphaFormat sourceAlpha, AlphaFormat destAlpha)
|
|
|
- {
|
|
|
- if (sourceAlpha != destAlpha)
|
|
|
- {
|
|
|
- if (sourceAlpha == AlphaFormat.Premul && destAlpha != AlphaFormat.Premul)
|
|
|
- {
|
|
|
- return ConvertFromPremultiplied(pixel);
|
|
|
- }
|
|
|
-
|
|
|
- if (sourceAlpha != AlphaFormat.Premul && destAlpha == AlphaFormat.Premul)
|
|
|
- {
|
|
|
- return ConvertToPremultiplied(pixel);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return pixel;
|
|
|
- }
|
|
|
-
|
|
|
- private static Rgba8888Pixel ConvertToPremultiplied(Rgba8888Pixel pixel)
|
|
|
- {
|
|
|
- var factor = pixel.A / 255F;
|
|
|
-
|
|
|
- return new Rgba8888Pixel
|
|
|
- {
|
|
|
- R = (byte)(pixel.R * factor),
|
|
|
- G = (byte)(pixel.G * factor),
|
|
|
- B = (byte)(pixel.B * factor),
|
|
|
- A = pixel.A
|
|
|
- };
|
|
|
- }
|
|
|
-
|
|
|
- private static Rgba8888Pixel ConvertFromPremultiplied(Rgba8888Pixel pixel)
|
|
|
- {
|
|
|
- var factor = 1F / (pixel.A / 255F);
|
|
|
-
|
|
|
- return new Rgba8888Pixel
|
|
|
- {
|
|
|
- R = (byte)(pixel.R * factor),
|
|
|
- G = (byte)(pixel.G * factor),
|
|
|
- B = (byte)(pixel.B * factor),
|
|
|
- A = pixel.A
|
|
|
- };
|
|
|
- }
|
|
|
-
|
|
|
- private static IPixelFormatReader GetReader(PixelFormat format)
|
|
|
- {
|
|
|
- switch (format.FormatEnum)
|
|
|
- {
|
|
|
- case PixelFormatEnum.Rgb565:
|
|
|
- return new PixelFormatReader.Bgr565PixelFormatReader();
|
|
|
- case PixelFormatEnum.Rgba8888:
|
|
|
- return new PixelFormatReader.Rgba8888PixelFormatReader();
|
|
|
- case PixelFormatEnum.Bgra8888:
|
|
|
- return new PixelFormatReader.Bgra8888PixelFormatReader();
|
|
|
- case PixelFormatEnum.BlackWhite:
|
|
|
- return new PixelFormatReader.BlackWhitePixelFormatReader();
|
|
|
- case PixelFormatEnum.Gray2:
|
|
|
- return new PixelFormatReader.Gray2PixelFormatReader();
|
|
|
- case PixelFormatEnum.Gray4:
|
|
|
- return new PixelFormatReader.Gray4PixelFormatReader();
|
|
|
- case PixelFormatEnum.Gray8:
|
|
|
- return new PixelFormatReader.Gray8PixelFormatReader();
|
|
|
- case PixelFormatEnum.Gray16:
|
|
|
- return new PixelFormatReader.Gray16PixelFormatReader();
|
|
|
- case PixelFormatEnum.Gray32Float:
|
|
|
- return new PixelFormatReader.Gray32FloatPixelFormatReader();
|
|
|
- case PixelFormatEnum.Rgba64:
|
|
|
- return new PixelFormatReader.Rgba64PixelFormatReader();
|
|
|
- case PixelFormatEnum.Rgb24:
|
|
|
- return new PixelFormatReader.Rgb24PixelFormatReader();
|
|
|
- case PixelFormatEnum.Bgr24:
|
|
|
- return new PixelFormatReader.Bgr24PixelFormatReader();
|
|
|
- case PixelFormatEnum.Bgr555:
|
|
|
- return new PixelFormatReader.Bgr555PixelFormatReader();
|
|
|
- case PixelFormatEnum.Bgr565:
|
|
|
- return new PixelFormatReader.Bgr565PixelFormatReader();
|
|
|
- default:
|
|
|
- throw new NotSupportedException($"Pixel format {format} is not supported");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private static IPixelFormatWriter GetWriter(PixelFormat format)
|
|
|
- {
|
|
|
- switch (format.FormatEnum)
|
|
|
- {
|
|
|
- case PixelFormatEnum.Rgb565:
|
|
|
- return new PixelFormatWriter.Bgr565PixelFormatWriter();
|
|
|
- case PixelFormatEnum.Rgba8888:
|
|
|
- return new PixelFormatWriter.Rgba8888PixelFormatWriter();
|
|
|
- case PixelFormatEnum.Bgra8888:
|
|
|
- return new PixelFormatWriter.Bgra8888PixelFormatWriter();
|
|
|
- case PixelFormatEnum.BlackWhite:
|
|
|
- return new PixelFormatWriter.BlackWhitePixelFormatWriter();
|
|
|
- case PixelFormatEnum.Gray2:
|
|
|
- return new PixelFormatWriter.Gray2PixelFormatWriter();
|
|
|
- case PixelFormatEnum.Gray4:
|
|
|
- return new PixelFormatWriter.Gray4PixelFormatWriter();
|
|
|
- case PixelFormatEnum.Gray8:
|
|
|
- return new PixelFormatWriter.Gray8PixelFormatWriter();
|
|
|
- case PixelFormatEnum.Gray16:
|
|
|
- return new PixelFormatWriter.Gray16PixelFormatWriter();
|
|
|
- case PixelFormatEnum.Gray32Float:
|
|
|
- return new PixelFormatWriter.Gray32FloatPixelFormatWriter();
|
|
|
- case PixelFormatEnum.Rgba64:
|
|
|
- return new PixelFormatWriter.Rgba64PixelFormatWriter();
|
|
|
- case PixelFormatEnum.Rgb24:
|
|
|
- return new PixelFormatWriter.Rgb24PixelFormatWriter();
|
|
|
- case PixelFormatEnum.Bgr24:
|
|
|
- return new PixelFormatWriter.Bgr24PixelFormatWriter();
|
|
|
- case PixelFormatEnum.Bgr555:
|
|
|
- return new PixelFormatWriter.Bgr555PixelFormatWriter();
|
|
|
- case PixelFormatEnum.Bgr565:
|
|
|
- return new PixelFormatWriter.Bgr565PixelFormatWriter();
|
|
|
- default:
|
|
|
- throw new NotSupportedException($"Pixel format {format} is not supported");
|
|
|
- }
|
|
|
+ PixelFormatWriter.Write(pixels, dest, srcSize, destStride, destFormat, destAlphaFormat, srcAlphaFormat);
|
|
|
}
|
|
|
}
|