using SkiaSharp; namespace JobTrackerApi.Services; public static class AvatarImageProcessor { public static byte[]? Normalize(byte[] source) { if (source.Length is 0 or > 1_000_000) return null; using var data = SKData.CreateCopy(source); using var codec = SKCodec.Create(data); if (codec is null || codec.EncodedFormat is not (SKEncodedImageFormat.Png or SKEncodedImageFormat.Jpeg or SKEncodedImageFormat.Webp)) return null; var info = codec.Info; if (info.Width is < 1 or > 2048 || info.Height is < 1 or > 2048 || (long)info.Width * info.Height > 4_000_000 || codec.FrameCount > 1) return null; using var pixels = new SKBitmap(info.Width, info.Height, SKColorType.Rgba8888, SKAlphaType.Premul); if (codec.GetPixels(pixels.Info, pixels.GetPixels()) != SKCodecResult.Success) return null; var rotated = codec.EncodedOrigin is SKEncodedOrigin.LeftTop or SKEncodedOrigin.RightTop or SKEncodedOrigin.RightBottom or SKEncodedOrigin.LeftBottom; using var oriented = new SKBitmap(rotated ? info.Height : info.Width, rotated ? info.Width : info.Height, SKColorType.Rgba8888, SKAlphaType.Premul); using (var canvas = new SKCanvas(oriented)) { switch (codec.EncodedOrigin) { case SKEncodedOrigin.TopRight: canvas.Translate(info.Width, 0); canvas.Scale(-1, 1); break; case SKEncodedOrigin.BottomRight: canvas.Translate(info.Width, info.Height); canvas.RotateDegrees(180); break; case SKEncodedOrigin.BottomLeft: canvas.Translate(0, info.Height); canvas.Scale(1, -1); break; case SKEncodedOrigin.LeftTop: canvas.RotateDegrees(90); canvas.Scale(1, -1); break; case SKEncodedOrigin.RightTop: canvas.Translate(info.Height, 0); canvas.RotateDegrees(90); break; case SKEncodedOrigin.RightBottom: canvas.Translate(info.Height, info.Width); canvas.RotateDegrees(90); canvas.Scale(-1, 1); break; case SKEncodedOrigin.LeftBottom: canvas.Translate(0, info.Width); canvas.RotateDegrees(270); break; } canvas.DrawBitmap(pixels, 0, 0, new SKSamplingOptions(SKFilterMode.Nearest), null); } // Re-encoding decoded pixels drops source metadata and trailing payloads. using var image = SKImage.FromBitmap(oriented); using var encoded = image.Encode(SKEncodedImageFormat.Png, 100); return encoded is null || encoded.Size > 1_000_000 ? null : encoded.ToArray(); } }