diff --git a/LibreMetaverse/Imaging/Targa.cs b/LibreMetaverse/Imaging/Targa.cs
index 6921467b..dec181cf 100644
--- a/LibreMetaverse/Imaging/Targa.cs
+++ b/LibreMetaverse/Imaging/Targa.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Sjofn LLC.
+ * Copyright (c) 2024-2025, Sjofn LLC.
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,7 @@ namespace OpenMetaverse.Imaging
{
public static class Targa
{
- /// Decode Truvision TGA file to
+ /// Decode Truevision TGA file to
public static SKBitmap Decode(string fileName)
{
using (var image = Pfimage.FromFile(fileName))
@@ -43,7 +43,7 @@ namespace OpenMetaverse.Imaging
}
}
- /// Decode Truvision TGA stream to
+ /// Decode Truevision TGA stream to
public static SKBitmap Decode(Stream stream)
{
using (var image = Pfimage.FromStream(stream))
@@ -100,8 +100,64 @@ namespace OpenMetaverse.Imaging
}
}
}
-
- /// Encode to Truvision TGA byte array
+
+ public static byte[] Encode(SKBitmap image)
+ {
+ if (image == null) { return null; }
+
+ var imageType = (byte)(image.ColorType == SKColorType.Gray8 || image.ColorType == SKColorType.Alpha8
+ ? 0x03 : 0x02);
+ var imageDescriptor = (byte)(image.AlphaType <= SKAlphaType.Opaque ? 0 : 0x8);
+
+ var tga = new byte[image.Width * image.Height * image.BytesPerPixel + 18];
+ var di = 0;
+ tga[di++] = 0x00; // id length
+ tga[di++] = 0x00; // colormap type = 0: no colormap
+ tga[di++] = imageType; // image type
+ tga[di++] = 0x00; // color map spec is five zeroes for no color map
+ tga[di++] = 0x00; // color map spec is five zeroes for no color map
+ tga[di++] = 0x00; // color map spec is five zeroes for no color map
+ tga[di++] = 0x00; // color map spec is five zeroes for no color map
+ tga[di++] = 0x00; // color map spec is five zeroes for no color map
+ tga[di++] = 0; // x origin = two bytes
+ tga[di++] = 0; // x origin = two bytes
+ tga[di++] = 0; // y origin = two bytes
+ tga[di++] = 0; // y origin = two bytes
+ tga[di++] = (byte)(image.Width & 0xFF); // width - low byte
+ tga[di++] = (byte)(image.Width >> 8); // width - hi byte
+ tga[di++] = (byte)(image.Height & 0xFF); // height - low byte
+ tga[di++] = (byte)(image.Height >> 8); // height - hi byte
+ tga[di++] = (byte)(image.BytesPerPixel*8); // pixel depth, includes attribute bits
+ tga[di++] = imageDescriptor; // image descriptor byte
+
+ for (var y = image.Height - 1; y >= 0; --y) // takes lines from bottom lines to top (mirrored horizontally)
+ {
+ for (var x = 0; x < image.Width; ++x)
+ {
+ var c = image.GetPixel(x, y);
+ if (image.ColorType == SKColorType.Gray8)
+ {
+ tga[di++] = c.Red;
+ } else if (image.ColorType == SKColorType.Alpha8)
+ {
+ tga[di++] = c.Alpha;
+ }
+ else
+ {
+ tga[di++] = c.Blue;
+ tga[di++] = c.Green;
+ tga[di++] = c.Red;
+
+ tga[di++] = (byte)(image.AlphaType > SKAlphaType.Opaque ? 0x0 : c.Alpha);
+ }
+
+ }
+ }
+
+ return tga;
+ }
+
+ /// Encode to Truevision TGA byte array
public static byte[] Encode(ManagedImage image)
{
var tga = new byte[image.Width * image.Height * ((image.Channels & ManagedImage.ImageChannels.Alpha) == 0 ? 3 : 4) + 32];