diff --git a/LibreMetaverse/Imaging/ManagedImage.cs b/LibreMetaverse/Imaging/ManagedImage.cs index 83eb502d..4529a4d8 100644 --- a/LibreMetaverse/Imaging/ManagedImage.cs +++ b/LibreMetaverse/Imaging/ManagedImage.cs @@ -114,9 +114,9 @@ namespace OpenMetaverse.Imaging } /// - /// Constructs ManagedImage class from AnyBitmap + /// Constructs ManagedImage class from /// - /// Input AnyBitmap + /// Input public ManagedImage(SKBitmap bitmap) { Width = bitmap.Width; diff --git a/LibreMetaverse/Imaging/Targa.cs b/LibreMetaverse/Imaging/Targa.cs new file mode 100644 index 00000000..013ddda8 --- /dev/null +++ b/LibreMetaverse/Imaging/Targa.cs @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2024, Sjofn LLC. + * All rights reserved. + * + * - Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * - Neither the name of the openmetaverse.co nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.IO; +using System.Runtime.InteropServices; +using Pfim; +using SkiaSharp; + +namespace OpenMetaverse.Imaging +{ + public class Targa + { + public static SKBitmap Decode(string fileName) + { + using (var image = Pfimage.FromFile(fileName)) + { + return Decode(image); + } + } + + public static SKBitmap Decode(Stream stream) + { + using (var image = Pfimage.FromStream(stream)) + { + return Decode(image); + } + } + + private static SKBitmap Decode(IImage image) + { + SKColorType colorType; + var data = image.Data; + var dataLen = image.DataLen; + var stride = image.Stride; + switch (image.Format) + { + case ImageFormat.Rgb8: + colorType = SKColorType.Gray8; + break; + case ImageFormat.R5g6b5: // needs swizzled + colorType = SKColorType.Rgb565; + break; + case ImageFormat.Rgba16: // needs swizzled + colorType = SKColorType.Argb4444; + break; + case ImageFormat.Rgb24: // skia doesn't support 24-bit (boo!), upscale to 32-bit + var pixels = image.DataLen / 3; + dataLen = pixels * 4; + data = new byte[dataLen]; + for (var i = 0; i < pixels; ++i) + { + data[i * 4] = image.Data[i * 3]; + data[i * 4 + 1] = image.Data[i * 3 + 1]; + data[i * 4 + 2] = image.Data[i * 3 + 2]; + data[i * 4 + 3] = 255; + } + stride = image.Width * 4; + colorType = SKColorType.Bgra8888; + break; + case ImageFormat.Rgba32: + colorType = SKColorType.Bgra8888; + break; + default: + throw new ArgumentException($"Cannot interpret format: {image.Format}"); + } + var imageInfo = new SKImageInfo(image.Width, image.Height, colorType); + var handle = GCHandle.Alloc(data, GCHandleType.Pinned); + var ptr = Marshal.UnsafeAddrOfPinnedArrayElement(data, 0); + using (var skdata = SKData.Create(ptr, dataLen, (address, context) => handle.Free())) + { + using (var skImage = SKImage.FromPixels(imageInfo, skdata, stride)) + { + return SKBitmap.FromImage(skImage); + } + } + } + } +} \ No newline at end of file diff --git a/LibreMetaverse/ImportExport/ColladalLoader.cs b/LibreMetaverse/ImportExport/ColladalLoader.cs index 3d29707d..90c876c9 100644 --- a/LibreMetaverse/ImportExport/ColladalLoader.cs +++ b/LibreMetaverse/ImportExport/ColladalLoader.cs @@ -35,6 +35,7 @@ using System.Linq; using System.Xml.Serialization; using OpenMetaverse.ImportExport.Collada14; using OpenMetaverse.Rendering; +using Pfim; using SkiaSharp; namespace OpenMetaverse.ImportExport @@ -126,6 +127,10 @@ namespace OpenMetaverse.ImportExport case ".j2c": material.TextureData = File.ReadAllBytes(fname); return; + case ".tga": + case ".targa": + bitmap = Imaging.Targa.Decode(fname); + break; default: var img = SKImage.FromEncodedData(fname); bitmap = SKBitmap.FromImage(img); diff --git a/LibreMetaverse/LibreMetaverse.csproj b/LibreMetaverse/LibreMetaverse.csproj index 67031ea5..ecbccd2e 100644 --- a/LibreMetaverse/LibreMetaverse.csproj +++ b/LibreMetaverse/LibreMetaverse.csproj @@ -47,6 +47,7 @@ + diff --git a/Programs/examples/TestClient/Commands/Inventory/UploadImageCommand.cs b/Programs/examples/TestClient/Commands/Inventory/UploadImageCommand.cs index c9a4af7c..31278b50 100644 --- a/Programs/examples/TestClient/Commands/Inventory/UploadImageCommand.cs +++ b/Programs/examples/TestClient/Commands/Inventory/UploadImageCommand.cs @@ -113,8 +113,16 @@ namespace OpenMetaverse.TestClient } else { - var img = SKImage.FromEncodedData(fileName); - bitmap = SKBitmap.FromImage(img); + if (lowfilename.EndsWith(".tga") || lowfilename.EndsWith(".targa")) + { + bitmap = Imaging.Targa.Decode(fileName); + } + else + { + var img = SKImage.FromEncodedData(fileName); + bitmap = SKBitmap.FromImage(img); + } + int oldwidth = bitmap.Width; int oldheight = bitmap.Height;