Как создать FreeImageBitmap из ushort[], сделав только одну копию данных пикселей?

Я использую FreeImageNET для написания одноканальных 16-битных PNG-файлов под.NET, так как эта возможность не работает с 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). Это возможно?

1 ответ

Решение

Вы можете использовать этот конструктор:

public FreeImageBitmap(int width, int height, int stride, PixelFormat format, IntPtr scan0)

У тебя есть width а также height, stride Вы можете поставить 0 (это отступ между строками изображения). format является PixelFormat.Format16bppGrayScale, Вы получаете scan0 через закрепление ushort[] (если вы посмотрите на исходный файл, в конце массив, который вы передаете, будет закреплен...)

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();
    }
}
Другие вопросы по тегам