mirror of
https://fastgit.cc/github.com/sourcegit-scm/sourcegit
synced 2026-04-30 13:51:53 +08:00
feature: supports to view .tiff images
Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
@@ -7,6 +7,7 @@ using Avalonia;
|
||||
using Avalonia.Media.Imaging;
|
||||
using Avalonia.Platform;
|
||||
|
||||
using BitMiracle.LibTiff.Classic;
|
||||
using Pfim;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
@@ -39,6 +40,9 @@ namespace SourceGit.ViewModels
|
||||
case ".tga":
|
||||
case ".dds":
|
||||
return Models.ImageDecoder.Pfim;
|
||||
case ".tif":
|
||||
case ".tiff":
|
||||
return Models.ImageDecoder.Tiff;
|
||||
default:
|
||||
return Models.ImageDecoder.None;
|
||||
}
|
||||
@@ -70,10 +74,22 @@ namespace SourceGit.ViewModels
|
||||
var size = stream.Length;
|
||||
if (size > 0)
|
||||
{
|
||||
if (decoder == Models.ImageDecoder.Builtin)
|
||||
return DecodeWithAvalonia(stream, size);
|
||||
else if (decoder == Models.ImageDecoder.Pfim)
|
||||
return DecodeWithPfim(stream, size);
|
||||
try
|
||||
{
|
||||
switch (decoder)
|
||||
{
|
||||
case Models.ImageDecoder.Builtin:
|
||||
return DecodeWithAvalonia(stream, size);
|
||||
case Models.ImageDecoder.Pfim:
|
||||
return DecodeWithPfim(stream, size);
|
||||
case Models.ImageDecoder.Tiff:
|
||||
return DecodeWithTiff(stream, size);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.Out.WriteLine(e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
return new ImageSource(null, 0);
|
||||
@@ -81,75 +97,83 @@ namespace SourceGit.ViewModels
|
||||
|
||||
private static ImageSource DecodeWithAvalonia(Stream stream, long size)
|
||||
{
|
||||
try
|
||||
{
|
||||
var bitmap = new Bitmap(stream);
|
||||
return new ImageSource(bitmap, size);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new ImageSource(null, 0);
|
||||
}
|
||||
var bitmap = new Bitmap(stream);
|
||||
return new ImageSource(bitmap, size);
|
||||
}
|
||||
|
||||
private static ImageSource DecodeWithPfim(Stream stream, long size)
|
||||
{
|
||||
try
|
||||
using (var pfiImage = Pfimage.FromStream(stream))
|
||||
{
|
||||
using (var pfiImage = Pfimage.FromStream(stream))
|
||||
var data = pfiImage.Data;
|
||||
var stride = pfiImage.Stride;
|
||||
|
||||
var pixelFormat = PixelFormats.Bgra8888;
|
||||
var alphaFormat = AlphaFormat.Opaque;
|
||||
switch (pfiImage.Format)
|
||||
{
|
||||
var data = pfiImage.Data;
|
||||
var stride = pfiImage.Stride;
|
||||
case ImageFormat.Rgb8:
|
||||
pixelFormat = PixelFormats.Gray8;
|
||||
break;
|
||||
case ImageFormat.R5g5b5:
|
||||
case ImageFormat.R5g5b5a1:
|
||||
pixelFormat = PixelFormats.Bgr555;
|
||||
break;
|
||||
case ImageFormat.R5g6b5:
|
||||
pixelFormat = PixelFormats.Bgr565;
|
||||
break;
|
||||
case ImageFormat.Rgb24:
|
||||
pixelFormat = PixelFormats.Bgr24;
|
||||
break;
|
||||
case ImageFormat.Rgba16:
|
||||
var pixels2 = pfiImage.DataLen / 2;
|
||||
data = new byte[pixels2 * 4];
|
||||
stride = pfiImage.Width * 4;
|
||||
for (var i = 0; i < pixels2; i++)
|
||||
{
|
||||
var src = BitConverter.ToUInt16(pfiImage.Data, i * 2);
|
||||
data[i * 4 + 0] = (byte)Math.Round((src & 0x0F) / 15F * 255); // B
|
||||
data[i * 4 + 1] = (byte)Math.Round(((src >> 4) & 0x0F) / 15F * 255); // G
|
||||
data[i * 4 + 2] = (byte)Math.Round(((src >> 8) & 0x0F) / 15F * 255); // R
|
||||
data[i * 4 + 3] = (byte)Math.Round(((src >> 12) & 0x0F) / 15F * 255); // A
|
||||
}
|
||||
|
||||
var pixelFormat = PixelFormats.Bgra8888;
|
||||
var alphaFormat = AlphaFormat.Opaque;
|
||||
switch (pfiImage.Format)
|
||||
{
|
||||
case ImageFormat.Rgb8:
|
||||
pixelFormat = PixelFormats.Gray8;
|
||||
break;
|
||||
case ImageFormat.R5g5b5:
|
||||
case ImageFormat.R5g5b5a1:
|
||||
pixelFormat = PixelFormats.Bgr555;
|
||||
break;
|
||||
case ImageFormat.R5g6b5:
|
||||
pixelFormat = PixelFormats.Bgr565;
|
||||
break;
|
||||
case ImageFormat.Rgb24:
|
||||
pixelFormat = PixelFormats.Bgr24;
|
||||
break;
|
||||
case ImageFormat.Rgba16:
|
||||
var pixels2 = pfiImage.DataLen / 2;
|
||||
data = new byte[pixels2 * 4];
|
||||
stride = pfiImage.Width * 4;
|
||||
for (var i = 0; i < pixels2; i++)
|
||||
{
|
||||
var src = BitConverter.ToUInt16(pfiImage.Data, i * 2);
|
||||
data[i * 4 + 0] = (byte)Math.Round((src & 0x0F) / 15F * 255); // B
|
||||
data[i * 4 + 1] = (byte)Math.Round(((src >> 4) & 0x0F) / 15F * 255); // G
|
||||
data[i * 4 + 2] = (byte)Math.Round(((src >> 8) & 0x0F) / 15F * 255); // R
|
||||
data[i * 4 + 3] = (byte)Math.Round(((src >> 12) & 0x0F) / 15F * 255); // A
|
||||
}
|
||||
|
||||
alphaFormat = AlphaFormat.Premul;
|
||||
break;
|
||||
case ImageFormat.Rgba32:
|
||||
alphaFormat = AlphaFormat.Premul;
|
||||
break;
|
||||
default:
|
||||
return new ImageSource(null, 0);
|
||||
}
|
||||
|
||||
var ptr = Marshal.UnsafeAddrOfPinnedArrayElement(data, 0);
|
||||
var pixelSize = new PixelSize(pfiImage.Width, pfiImage.Height);
|
||||
var dpi = new Vector(96, 96);
|
||||
var bitmap = new Bitmap(pixelFormat, alphaFormat, ptr, pixelSize, dpi, stride);
|
||||
return new ImageSource(bitmap, size);
|
||||
alphaFormat = AlphaFormat.Premul;
|
||||
break;
|
||||
case ImageFormat.Rgba32:
|
||||
alphaFormat = AlphaFormat.Premul;
|
||||
break;
|
||||
default:
|
||||
return new ImageSource(null, 0);
|
||||
}
|
||||
|
||||
var ptr = Marshal.UnsafeAddrOfPinnedArrayElement(data, 0);
|
||||
var pixelSize = new PixelSize(pfiImage.Width, pfiImage.Height);
|
||||
var dpi = new Vector(96, 96);
|
||||
var bitmap = new Bitmap(pixelFormat, alphaFormat, ptr, pixelSize, dpi, stride);
|
||||
return new ImageSource(bitmap, size);
|
||||
}
|
||||
catch
|
||||
}
|
||||
|
||||
private static ImageSource DecodeWithTiff(Stream stream, long size)
|
||||
{
|
||||
using (var tiff = Tiff.ClientOpen($"{Guid.NewGuid()}.tif", "r", stream, new TiffStream()))
|
||||
{
|
||||
return new ImageSource(null, 0);
|
||||
if (tiff == null)
|
||||
return new ImageSource(null, 0);
|
||||
|
||||
var width = tiff.GetField(TiffTag.IMAGEWIDTH)[0].ToInt();
|
||||
var height = tiff.GetField(TiffTag.IMAGELENGTH)[0].ToInt();
|
||||
var pixels = new int[width * height];
|
||||
|
||||
// Currently only supports image when its `BITSPERSAMPLE` is one in [1,2,4,8,16]
|
||||
tiff.ReadRGBAImageOriented(width, height, pixels, Orientation.TOPLEFT);
|
||||
|
||||
var ptr = Marshal.UnsafeAddrOfPinnedArrayElement(pixels, 0);
|
||||
var pixelSize = new PixelSize(width, height);
|
||||
var dpi = new Vector(96, 96);
|
||||
var bitmap = new Bitmap(PixelFormats.Rgba8888, AlphaFormat.Premul, ptr, pixelSize, dpi, width * 4);
|
||||
return new ImageSource(bitmap, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user