diff --git a/src/OpenJpegDotNet/Image.cs b/src/OpenJpegDotNet/Image.cs index aa22ebc..fb0d8e5 100644 --- a/src/OpenJpegDotNet/Image.cs +++ b/src/OpenJpegDotNet/Image.cs @@ -184,10 +184,11 @@ public byte[] IccProfile /// /// Converts this to a GDI+ . /// + /// Export alpha channel /// A that represents the converted . /// This object is disposed. /// This object is not supported. - public Bitmap ToBitmap() + public Bitmap ToBitmap(bool alpha = true) { this.ThrowIfDisposed(); @@ -206,14 +207,6 @@ public Bitmap ToBitmap() throw new NotSupportedException("This object is not supported."); } - if (channel != 3 && channel != 1) - { - if (planes != IntPtr.Zero) - NativeMethods.stdlib_free(planes); - - throw new NotSupportedException("This object is not supported."); - } - Bitmap bitmap = null; BitmapData bitmapData = null; @@ -271,11 +264,45 @@ public Bitmap ToBitmap() } } break; + case 4: + { + bitmap = new Bitmap((int)width, (int)height, PixelFormat.Format32bppArgb); + var rect = new Rectangle(0, 0, (int)width, (int)height); + bitmapData = bitmap.LockBits(rect, ImageLockMode.WriteOnly, bitmap.PixelFormat); + var scan0 = bitmapData.Scan0; + var stride = bitmapData.Stride; + + unsafe + { + var pSrc = (byte*)planes; + var pDest = (byte*)scan0; + var gap = stride - width * channel; + var size = width * height; + for (var y = 0; y < height; y++) + { + for (var x = 0; x < width; x++) + { + pDest[3] = alpha ? pSrc[0 + size * 3] : (byte)255; + pDest[2] = pSrc[0]; + pDest[1] = pSrc[0 + size]; + pDest[0] = pSrc[0 + size * 2]; + + pSrc += 1; + pDest += channel; + } + + pDest += gap; + } + } + } + break; + default: + throw new NotSupportedException($"Unsupported number of channels: ${channel}."); } break; default: - throw new NotSupportedException("This object is not supported."); + throw new NotSupportedException($"Unsupported pixel depth: ${pixel}."); } } catch @@ -301,6 +328,7 @@ public Bitmap ToBitmap() /// /// Converts this to a . /// + /// Export alpha channel /// A that represents the converted . /// This object is not supported. public RawBitmap ToRawBitmap() @@ -322,14 +350,6 @@ public RawBitmap ToRawBitmap() throw new NotSupportedException("This object is not supported."); } - if (channel != 3 && channel != 1) - { - if (planes != IntPtr.Zero) - NativeMethods.stdlib_free(planes); - - throw new NotSupportedException("This object is not supported."); - } - var raw = new byte[width * height * channel]; try @@ -382,11 +402,39 @@ public RawBitmap ToRawBitmap() } } break; + case 4: + { + unsafe + { + fixed (byte* dst = &raw[0]) + { + var pSrc = (byte*)planes; + var pDest = dst; + var size = width * height; + for (var y = 0; y < height; y++) + { + for (var x = 0; x < width; x++) + { + pDest[3] = alpha ? pSrc[0 + size * 3] : (byte)255; + pDest[2] = pSrc[0]; + pDest[1] = pSrc[0 + size]; + pDest[0] = pSrc[0 + size * 2]; + + pSrc += 1; + pDest += channel; + } + } + } + } + } + break; + default: + throw new NotSupportedException($"Unsupported number of channels: ${channel}."); } break; default: - throw new NotSupportedException("This object is not supported."); + throw new NotSupportedException($"Unsupported pixel depth: ${pixel}."); } } finally @@ -419,4 +467,4 @@ protected override void DisposeUnmanaged() } -} \ No newline at end of file +}