@@ -85,32 +85,71 @@ public static Image ToVips(this Bitmap src)
85
85
86
86
var bands = GuessBands ( src . PixelFormat ) ;
87
87
var format = GuessBandFormat ( src . PixelFormat ) ;
88
+ var sizeofFormat = format == Enums . BandFormat . Uchar ? sizeof ( byte ) : sizeof ( ushort ) ;
88
89
89
90
var w = src . Width ;
90
91
var h = src . Height ;
92
+ var stride = w * bands * sizeofFormat ;
93
+ var size = stride * h ;
91
94
92
95
var rect = new Rectangle ( 0 , 0 , w , h ) ;
93
96
BitmapData bd = null ;
94
97
Image dst ;
95
98
try
96
99
{
97
100
bd = src . LockBits ( rect , ImageLockMode . ReadOnly , src . PixelFormat ) ;
98
- dst = Image . NewFromMemoryCopy ( bd . Scan0 , ( ulong ) ( bd . Stride * h ) , w , h , bands , format ) ;
101
+
102
+ // bd.Stride is aligned to a multiple of 4
103
+ if ( bd . Stride == stride )
104
+ {
105
+ dst = Image . NewFromMemoryCopy ( bd . Scan0 , ( ulong ) size , w , h , bands , format ) ;
106
+ }
107
+ else
108
+ {
109
+ var buffer = new byte [ size ] ;
110
+
111
+ // Copy the bytes from src to the managed array for each scanline
112
+ for ( var y = 0 ; y < h ; y ++ )
113
+ {
114
+ Marshal . Copy ( bd . Scan0 + y * bd . Stride , buffer , y * stride , stride ) ;
115
+ }
116
+
117
+ dst = Image . NewFromMemory ( buffer , w , h , bands , format ) ;
118
+ }
99
119
}
100
120
finally
101
121
{
102
122
if ( bd != null )
103
123
src . UnlockBits ( bd ) ;
104
124
}
105
125
106
- if ( bands != 3 )
126
+ if ( src . PixelFormat == PixelFormat . Format8bppIndexed )
107
127
{
108
- return dst ;
128
+ var palette = new byte [ 256 ] ;
129
+ for ( var i = 0 ; i < 256 ; i ++ )
130
+ {
131
+ if ( i >= src . Palette . Entries . Length )
132
+ break ;
133
+ palette [ i ] = src . Palette . Entries [ i ] . R ;
134
+ }
135
+
136
+ var lut = Image . NewFromArray ( palette ) ;
137
+ return dst . Maplut ( lut ) ;
109
138
}
110
139
111
- // Switch from BGR to RGB
112
- var images = dst . Bandsplit ( ) ;
113
- return images [ 2 ] . Bandjoin ( images [ 1 ] , images [ 0 ] ) ;
140
+ switch ( bands )
141
+ {
142
+ case 3 :
143
+ // Switch from BGR to RGB
144
+ var bgr = dst . Bandsplit ( ) ;
145
+ return bgr [ 2 ] . Bandjoin ( bgr [ 1 ] , bgr [ 0 ] ) ;
146
+ case 4 :
147
+ // Switch from BGRA to RGBA
148
+ var bgra = dst . Bandsplit ( ) ;
149
+ return bgra [ 2 ] . Bandjoin ( bgra [ 1 ] , bgra [ 0 ] , bgra [ 3 ] ) ;
150
+ default :
151
+ return dst ;
152
+ }
114
153
}
115
154
116
155
/// <summary>
@@ -123,6 +162,12 @@ public static Bitmap ToBitmap(this Image src)
123
162
if ( src == null )
124
163
throw new ArgumentNullException ( nameof ( src ) ) ;
125
164
165
+ // Ensure image is casted to uint8 (unsigned char)
166
+ if ( src . Bands < 3 || src . Format != Enums . BandFormat . Ushort )
167
+ {
168
+ src = src . Cast ( Enums . BandFormat . Uchar ) ;
169
+ }
170
+
126
171
PixelFormat pf ;
127
172
switch ( src . Bands )
128
173
{
@@ -143,13 +188,17 @@ public static Bitmap ToBitmap(this Image src)
143
188
: PixelFormat . Format24bppRgb ;
144
189
145
190
// Switch from RGB to BGR
146
- var bands = src . Bandsplit ( ) ;
147
- src = bands [ 2 ] . Bandjoin ( bands [ 1 ] , bands [ 0 ] ) ;
191
+ var rgb = src . Bandsplit ( ) ;
192
+ src = rgb [ 2 ] . Bandjoin ( rgb [ 1 ] , rgb [ 0 ] ) ;
148
193
break ;
149
194
case 4 :
150
195
pf = src . Format == Enums . BandFormat . Ushort
151
196
? PixelFormat . Format64bppArgb
152
197
: PixelFormat . Format32bppArgb ;
198
+
199
+ // Switch from RGBA to BGRA
200
+ var rgba = src . Bandsplit ( ) ;
201
+ src = rgba [ 2 ] . Bandjoin ( rgba [ 1 ] , rgba [ 0 ] , rgba [ 3 ] ) ;
153
202
break ;
154
203
default :
155
204
throw new NotImplementedException (
@@ -178,9 +227,35 @@ public static Bitmap ToBitmap(this Image src)
178
227
try
179
228
{
180
229
bd = dst . LockBits ( rect , ImageLockMode . WriteOnly , pf ) ;
230
+ var dstSize = ( ulong ) ( bd . Stride * h ) ;
231
+ var memory = src . WriteToMemory ( out var srcSize ) ;
232
+
233
+ // bd.Stride is aligned to a multiple of 4
234
+ if ( dstSize == srcSize )
235
+ {
236
+ unsafe
237
+ {
238
+ Buffer . MemoryCopy ( memory . ToPointer ( ) , bd . Scan0 . ToPointer ( ) , srcSize , srcSize ) ;
239
+ }
240
+ }
241
+ else
242
+ {
243
+ var offset = w * src . Bands ;
244
+
245
+ // Copy the bytes from src to dst for each scanline
246
+ for ( var y = 0 ; y < h ; y ++ )
247
+ {
248
+ var pSrc = memory + y * offset ;
249
+ var pDst = bd . Scan0 + y * bd . Stride ;
250
+
251
+ unsafe
252
+ {
253
+ Buffer . MemoryCopy ( pSrc . ToPointer ( ) , pDst . ToPointer ( ) , offset , offset ) ;
254
+ }
255
+ }
256
+ }
181
257
182
- var memory = src . WriteToMemory ( ) ;
183
- Marshal . Copy ( memory , 0 , bd . Scan0 , memory . Length ) ;
258
+ NetVips . Free ( memory ) ;
184
259
}
185
260
finally
186
261
{
0 commit comments