Skip to content

Commit

Permalink
Include Pfim for tga decoding support
Browse files Browse the repository at this point in the history
  • Loading branch information
cinderblocks committed Aug 7, 2024
1 parent 732638e commit 7dda98b
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 4 deletions.
4 changes: 2 additions & 2 deletions LibreMetaverse/Imaging/ManagedImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,9 @@ public ManagedImage(int width, int height, ImageChannels channels)
}

/// <summary>
/// Constructs ManagedImage class from AnyBitmap
/// Constructs ManagedImage class from <see cref="SKBitmap"/>
/// </summary>
/// <param name="bitmap">Input AnyBitmap</param>
/// <param name="bitmap">Input <see cref="SKBitmap"/></param>
public ManagedImage(SKBitmap bitmap)
{
Width = bitmap.Width;
Expand Down
102 changes: 102 additions & 0 deletions LibreMetaverse/Imaging/Targa.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
}
}
5 changes: 5 additions & 0 deletions LibreMetaverse/ImportExport/ColladalLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
using System.Xml.Serialization;
using OpenMetaverse.ImportExport.Collada14;
using OpenMetaverse.Rendering;
using Pfim;
using SkiaSharp;

namespace OpenMetaverse.ImportExport
Expand Down Expand Up @@ -126,6 +127,10 @@ void LoadImage(ModelMaterial material)
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);
Expand Down
1 change: 1 addition & 0 deletions LibreMetaverse/LibreMetaverse.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="8.0.6" />
<PackageReference Include="OggVorbisEncoder" Version="1.2.2" />
<PackageReference Include="OpenJpegDotNet-LMV" Version="2.5.0.20240712" />
<PackageReference Include="Pfim" Version="0.11.2" />
<PackageReference Include="SkiaSharp" Version="2.88.8" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="2.88.8" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,16 @@ private byte[] LoadImage(string fileName)
}
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;

Expand Down

0 comments on commit 7dda98b

Please sign in to comment.