|
1 | | -using System.IO; |
| 1 | +using System; |
| 2 | +using System.IO; |
2 | 3 | using System.Runtime.InteropServices; |
| 4 | + |
| 5 | +using Avalonia; |
3 | 6 | using Avalonia.Media.Imaging; |
| 7 | +using Avalonia.Platform; |
| 8 | + |
4 | 9 | using Pfim; |
5 | 10 |
|
6 | 11 | namespace SourceGit.ViewModels |
@@ -64,103 +69,98 @@ private static ImageSource LoadFromStream(Stream stream, Models.ImageDecoder dec |
64 | 69 | if (size > 0) |
65 | 70 | { |
66 | 71 | 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); |
78 | 73 | else if (decoder == Models.ImageDecoder.Pfim) |
79 | | - { |
80 | | - return new ImageSource(LoadWithPfim(stream), size); |
81 | | - } |
| 74 | + return DecodeWithPfim(stream, size); |
82 | 75 | } |
83 | 76 |
|
84 | 77 | return new ImageSource(null, 0); |
85 | 78 | } |
86 | 79 |
|
87 | | - private static Bitmap LoadWithPfim(Stream stream) |
| 80 | + private static ImageSource DecodeWithAvalonia(Stream stream, long size) |
88 | 81 | { |
89 | | - var image = Pfim.Pfimage.FromStream(stream); |
90 | | - byte[] data; |
91 | | - int stride; |
92 | | - if (image.Format == ImageFormat.Rgba32) |
| 82 | + try |
93 | 83 | { |
94 | | - data = image.Data; |
95 | | - stride = image.Stride; |
| 84 | + var bitmap = new Bitmap(stream); |
| 85 | + return new ImageSource(bitmap, size); |
96 | 86 | } |
97 | | - else |
| 87 | + catch |
98 | 88 | { |
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 | + } |
102 | 92 |
|
103 | | - switch (image.Format) |
| 93 | + private static ImageSource DecodeWithPfim(Stream stream, long size) |
| 94 | + { |
| 95 | + using (var pfiImage = Pfimage.FromStream(stream)) |
| 96 | + { |
| 97 | + try |
104 | 98 | { |
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; |
121 | 117 | for (int i = 0; i < pixels; i++) |
122 | 118 | { |
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); |
127 | 125 | } |
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++) |
133 | 134 | { |
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); |
139 | 140 | } |
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 | + } |
146 | 153 |
|
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 | + } |
164 | 164 | } |
165 | 165 | } |
166 | 166 | } |
|
0 commit comments