Skip to content

Commit 8db033b

Browse files
committed
code_review: PR #1392
- fix the issue that not all channel takes 8 bits - if `PixelFormatTranscoder.Transcode` supports the same pixel formats, let it converts pixels automatically Signed-off-by: leo <[email protected]>
1 parent a2ca071 commit 8db033b

File tree

1 file changed

+80
-80
lines changed

1 file changed

+80
-80
lines changed

src/ViewModels/ImageSource.cs

Lines changed: 80 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1-
using System.IO;
1+
using System;
2+
using System.IO;
23
using System.Runtime.InteropServices;
4+
5+
using Avalonia;
36
using Avalonia.Media.Imaging;
7+
using Avalonia.Platform;
8+
49
using Pfim;
510

611
namespace SourceGit.ViewModels
@@ -64,103 +69,98 @@ private static ImageSource LoadFromStream(Stream stream, Models.ImageDecoder dec
6469
if (size > 0)
6570
{
6671
if (decoder == Models.ImageDecoder.Builtin)
67-
{
68-
try
69-
{
70-
var bitmap = new Bitmap(stream);
71-
return new ImageSource(bitmap, size);
72-
}
73-
catch
74-
{
75-
// Just ignore.
76-
}
77-
}
72+
return DecodeWithAvalonia(stream, size);
7873
else if (decoder == Models.ImageDecoder.Pfim)
79-
{
80-
return new ImageSource(LoadWithPfim(stream), size);
81-
}
74+
return DecodeWithPfim(stream, size);
8275
}
8376

8477
return new ImageSource(null, 0);
8578
}
8679

87-
private static Bitmap LoadWithPfim(Stream stream)
80+
private static ImageSource DecodeWithAvalonia(Stream stream, long size)
8881
{
89-
var image = Pfim.Pfimage.FromStream(stream);
90-
byte[] data;
91-
int stride;
92-
if (image.Format == ImageFormat.Rgba32)
82+
try
9383
{
94-
data = image.Data;
95-
stride = image.Stride;
84+
var bitmap = new Bitmap(stream);
85+
return new ImageSource(bitmap, size);
9686
}
97-
else
87+
catch
9888
{
99-
int pixels = image.Width * image.Height;
100-
data = new byte[pixels * 4];
101-
stride = image.Width * 4;
89+
return new ImageSource(null, 0);
90+
}
91+
}
10292

103-
switch (image.Format)
93+
private static ImageSource DecodeWithPfim(Stream stream, long size)
94+
{
95+
using (var pfiImage = Pfimage.FromStream(stream))
96+
{
97+
try
10498
{
105-
case ImageFormat.Rgba16:
106-
case ImageFormat.R5g5b5a1:
107-
{
108-
for (int i = 0; i < pixels; i++)
109-
{
110-
data[i * 4 + 0] = image.Data[i * 4 + 2]; // B
111-
data[i * 4 + 1] = image.Data[i * 4 + 1]; // G
112-
data[i * 4 + 2] = image.Data[i * 4 + 0]; // R
113-
data[i * 4 + 3] = image.Data[i * 4 + 3]; // A
114-
}
115-
}
116-
break;
117-
case ImageFormat.R5g5b5:
118-
case ImageFormat.R5g6b5:
119-
case ImageFormat.Rgb24:
120-
{
99+
var data = pfiImage.Data;
100+
var stride = pfiImage.Stride;
101+
102+
var pixelFormat = PixelFormats.Rgba8888;
103+
var alphaFormat = AlphaFormat.Opaque;
104+
switch (pfiImage.Format)
105+
{
106+
case ImageFormat.Rgb8:
107+
pixelFormat = PixelFormats.Gray8;
108+
break;
109+
case ImageFormat.R5g6b5:
110+
pixelFormat = PixelFormats.Rgb565;
111+
break;
112+
case ImageFormat.Rgba16:
113+
var pixels = pfiImage.DataLen / 2;
114+
var newSize = pfiImage.DataLen * 2;
115+
data = new byte[newSize];
116+
stride = 4 * pfiImage.Width;
121117
for (int i = 0; i < pixels; i++)
122118
{
123-
data[i * 4 + 0] = image.Data[i * 3 + 2]; // B
124-
data[i * 4 + 1] = image.Data[i * 3 + 1]; // G
125-
data[i * 4 + 2] = image.Data[i * 3 + 0]; // R
126-
data[i * 4 + 3] = 255; // A
119+
var rg = pfiImage.Data[i * 2];
120+
var ba = pfiImage.Data[i * 2 + 1];
121+
data[i * 4 + 0] = (byte)Math.Round((rg >> 4) / 15.0 * 255);
122+
data[i * 4 + 1] = (byte)Math.Round((rg & 0xF) / 15.0 * 255);
123+
data[i * 4 + 2] = (byte)Math.Round((ba >> 4) / 15.0 * 255);
124+
data[i * 4 + 3] = (byte)Math.Round((ba & 0xF) / 15.0 * 255);
127125
}
128-
}
129-
break;
130-
case ImageFormat.Rgb8:
131-
{
132-
for (int i = 0; i < pixels; i++)
126+
alphaFormat = AlphaFormat.Premul;
127+
break;
128+
case ImageFormat.R5g5b5a1:
129+
var pixels2 = pfiImage.DataLen / 2;
130+
var newSize2 = pfiImage.DataLen * 2;
131+
data = new byte[newSize2];
132+
stride = 4 * pfiImage.Width;
133+
for (int i = 0; i < pixels2; i++)
133134
{
134-
var color = image.Data[i];
135-
data[i * 4 + 0] = color;
136-
data[i * 4 + 1] = color;
137-
data[i * 4 + 2] = color;
138-
data[i * 4 + 3] = 255;
135+
var v = (int)pfiImage.Data[i * 2] << 8 + pfiImage.Data[i * 2 + 1];
136+
data[i * 4 + 0] = (byte)Math.Round(((v & 0b1111100000000000) >> 11) / 31.0 * 255);
137+
data[i * 4 + 1] = (byte)Math.Round(((v & 0b11111000000) >> 6) / 31.0 * 255);
138+
data[i * 4 + 2] = (byte)Math.Round(((v & 0b111110) >> 1) / 31.0 * 255);
139+
data[i * 4 + 3] = (byte)((v & 1) == 1 ? 255 : 0);
139140
}
140-
}
141-
break;
142-
default:
143-
return null;
144-
}
145-
}
141+
alphaFormat = AlphaFormat.Premul;
142+
break;
143+
case ImageFormat.Rgb24:
144+
pixelFormat = PixelFormats.Rgb24;
145+
break;
146+
case ImageFormat.Rgba32:
147+
pixelFormat = PixelFormat.Rgba8888;
148+
alphaFormat = AlphaFormat.Premul;
149+
break;
150+
default:
151+
return new ImageSource(null, 0);
152+
}
146153

147-
// Pin the array and pass the pointer to Bitmap
148-
var handle = GCHandle.Alloc(data, GCHandleType.Pinned);
149-
try
150-
{
151-
var ptr = Marshal.UnsafeAddrOfPinnedArrayElement(data, 0);
152-
var bitmap = new Bitmap(
153-
Avalonia.Platform.PixelFormat.Bgra8888,
154-
Avalonia.Platform.AlphaFormat.Unpremul,
155-
ptr,
156-
new Avalonia.PixelSize(image.Width, image.Height),
157-
new Avalonia.Vector(96, 96),
158-
stride);
159-
return bitmap;
160-
}
161-
finally
162-
{
163-
handle.Free();
154+
var ptr = Marshal.UnsafeAddrOfPinnedArrayElement(pfiImage.Data, 0);
155+
var pixelSize = new PixelSize(pfiImage.Width, pfiImage.Height);
156+
var dpi = new Vector(96, 96);
157+
var bitmap = new Bitmap(pixelFormat, alphaFormat, ptr, pixelSize, dpi, stride);
158+
return new ImageSource(bitmap, size);
159+
}
160+
catch
161+
{
162+
return new ImageSource(null, 0);
163+
}
164164
}
165165
}
166166
}

0 commit comments

Comments
 (0)