如何从 ushort[] 创建 FreeImageBitmap 只制作一个像素数据副本?
How to create FreeImageBitmap from ushort[] making only one copy of the pixel data?
我正在使用 FreeImageNET 在 .NET 下编写单通道 16 位 PNG,因为此功能不适用于 System.Drawing.Bitmap。
我从相机获取 16 位数据作为 ushort[]。我将此数据保存到文件中,如下所示:
public void SavePngGray16(ushort[] data, string fname)
{
// Create bitmap object to manage image: one 16-bit channel (true monochrome)
Bitmap bmp16 = new Bitmap(ImageSize.Width, ImageSize.Height, PixelFormat.Format16bppGrayScale);
// Copy received data into bitmap
Rectangle rc = new Rectangle(Point.Empty, ImageSize);
BitmapData data16 = bmp16.LockBits(rc, ImageLockMode.WriteOnly, bmp16.PixelFormat);
// intermediary to enable casting in the Copy() call;
// casting required because Copy() doesn't have a ushort[] flavor.
Array ax = data;
Marshal.Copy((short[])ax, 0, data16.Scan0, data.Length);
bmp16.UnlockBits(data16);
// 16-bit support, for real
// Instantiate a FreeImage bitmap from the System.Drawing bitmap we just built
//## this causes a full copy of the image data...
//## but FreeImageBitmap.LockBits() is UNIMPLEMENTED, so can't just build-and-fill
//## as above with a FreeImageBitmap instance
FreeImageBitmap fbmp = new FreeImageBitmap(bmp16);
// And save that as a 16-bit grayscale PNG
fbmp.Save(fname, FREE_IMAGE_FORMAT.FIF_PNG, FREE_IMAGE_SAVE_FLAGS.PNG_Z_DEFAULT_COMPRESSION);
}
我想避免复制数据两次(一次将数据放入 Bitmap
,一次将数据放入 FreeImageBitmap
)。这可能吗?
您可以使用此构造函数:
public FreeImageBitmap(int width, int height, int stride, PixelFormat format, IntPtr scan0)
您有 width
和 height
。 stride
你可以放 0(它是图像行之间的填充)。 format
是 PixelFormat.Format16bppGrayScale
。您通过固定 ushort[]
获得 scan0
(如果您查看源文件,最后您传递的数组将被固定...)
GCHandle handle = default(GCHandle);
try
{
handle = GCHandle.Alloc(data, GCHandleType.Pinned);
FreeImageBitmap fbmp = new FreeImageBitmap(width, height, 0, PixelFormat.Format16bppGrayScale, handle.AddrOfPinnedObject());
}
finally
{
if (handle.IsAllocated)
{
handle.Free();
}
}
我正在使用 FreeImageNET 在 .NET 下编写单通道 16 位 PNG,因为此功能不适用于 System.Drawing.Bitmap。
我从相机获取 16 位数据作为 ushort[]。我将此数据保存到文件中,如下所示:
public void SavePngGray16(ushort[] data, string fname)
{
// Create bitmap object to manage image: one 16-bit channel (true monochrome)
Bitmap bmp16 = new Bitmap(ImageSize.Width, ImageSize.Height, PixelFormat.Format16bppGrayScale);
// Copy received data into bitmap
Rectangle rc = new Rectangle(Point.Empty, ImageSize);
BitmapData data16 = bmp16.LockBits(rc, ImageLockMode.WriteOnly, bmp16.PixelFormat);
// intermediary to enable casting in the Copy() call;
// casting required because Copy() doesn't have a ushort[] flavor.
Array ax = data;
Marshal.Copy((short[])ax, 0, data16.Scan0, data.Length);
bmp16.UnlockBits(data16);
// 16-bit support, for real
// Instantiate a FreeImage bitmap from the System.Drawing bitmap we just built
//## this causes a full copy of the image data...
//## but FreeImageBitmap.LockBits() is UNIMPLEMENTED, so can't just build-and-fill
//## as above with a FreeImageBitmap instance
FreeImageBitmap fbmp = new FreeImageBitmap(bmp16);
// And save that as a 16-bit grayscale PNG
fbmp.Save(fname, FREE_IMAGE_FORMAT.FIF_PNG, FREE_IMAGE_SAVE_FLAGS.PNG_Z_DEFAULT_COMPRESSION);
}
我想避免复制数据两次(一次将数据放入 Bitmap
,一次将数据放入 FreeImageBitmap
)。这可能吗?
您可以使用此构造函数:
public FreeImageBitmap(int width, int height, int stride, PixelFormat format, IntPtr scan0)
您有 width
和 height
。 stride
你可以放 0(它是图像行之间的填充)。 format
是 PixelFormat.Format16bppGrayScale
。您通过固定 ushort[]
获得 scan0
(如果您查看源文件,最后您传递的数组将被固定...)
GCHandle handle = default(GCHandle);
try
{
handle = GCHandle.Alloc(data, GCHandleType.Pinned);
FreeImageBitmap fbmp = new FreeImageBitmap(width, height, 0, PixelFormat.Format16bppGrayScale, handle.AddrOfPinnedObject());
}
finally
{
if (handle.IsAllocated)
{
handle.Free();
}
}