Skip to main content
 首页 » 编程设计

c#之使用像素数组初始化 BitmapSource

2024年01月02日31wuhuacong

我正在尝试将 native 图像数据结构编码到 BitmapSource。

这是原生结构:

struct Bitmap_8Bit 
        { 
        public: 
            unsigned char* data; 
            int stride; 
            int rows; 
            int cols; 
            int nChannels; //either 1 or 3. in case of three the order of the channels is BGR 
        }; 

这是我的编码函数:

template<> 
        inline 
            System::Windows::Media::Imaging::BitmapSource^ marshal_as<System::Windows::Media::Imaging::BitmapSource^, Bitmap_8Bit>(const Bitmap_8Bit& nativeBitmap) 
        { 
            System::Windows::Media::PixelFormat format = System::Windows::Media::PixelFormats::Default; 
            System::Windows::Media::Imaging::BitmapPalette^ palette = nullptr; 
            if (nativeBitmap.nChannels == 1) 
            { 
                format = System::Windows::Media::PixelFormats::Gray8; 
                palette = System::Windows::Media::Imaging::BitmapPalettes::Gray256; 
            } 
            else if (nativeBitmap.nChannels == 3) 
            { 
                format = System::Windows::Media::PixelFormats::Bgr24; 
                palette = System::Windows::Media::Imaging::BitmapPalettes::Halftone256; 
            } 
            else 
            { 
                throw gcnew System::InvalidOperationException("Unsupported number of channels " + nativeBitmap.nChannels); 
            } 
 
            //copy data 
            int pixelDataLength = nativeBitmap.rows*nativeBitmap.stride; 
            System::IntPtr source = System::IntPtr(nativeBitmap.data); 
 
            cli::array<unsigned char>^ buffer = gcnew cli::array<unsigned char>(pixelDataLength); 
            System::Runtime::InteropServices::Marshal::Copy(source, buffer, 0, pixelDataLength); 
 
             System::Windows::Media::Imaging::BitmapSource^ managedBitmap =  
                 System::Windows::Media::Imaging::BitmapSource::Create(nativeBitmap.cols, nativeBitmap.rows,  
                 96, 96,  
                 format, palette,  
                 buffer, nativeBitmap.stride); 
 
            return managedBitmap; 
        } 

我正在一个简单的单 channel 案例中测试我的功能:

BSII::IP::Bitmap_8Bit native; 
native.cols = 8; 
native.rows = 4; 
native.nChannels = 1; 
native.stride = 8; 
int dataLength = native.stride * native.rows; 
native.data = new unsigned char[dataLength]; 
 
unsigned char gray = 0; 
for (int i = 0; i < native.rows; ++i) 
{ 
    for (int j = 0; j < native.cols; ++j) 
    { 
        native.data[native.stride*i + j] = gray; 
        gray += 10; 
    } 
} 
 
System::Windows::Media::Imaging::BitmapSource^ managed = msclr::interop::marshal_as<System::Windows::Media::Imaging::BitmapSource^>(native); 
 
System::IO::FileStream^ stream = gcnew System::IO::FileStream("c:\\workspace\\temp\\managed.bmp", System::IO::FileMode::Create); 
System::Windows::Media::Imaging::BmpBitmapEncoder^ encoder = gcnew System::Windows::Media::Imaging::BmpBitmapEncoder(); 
System::Windows::Media::Imaging::BitmapFrame^ bitmapFrame = System::Windows::Media::Imaging::BitmapFrame::Create(managed); 
encoder->Frames->Add(bitmapFrame); 
encoder->Save(stream); 
stream->Close(); 

这行不通。当我调试它时,我看到缓冲区数组内部有正确的值,但是当我将 BitmapSource 保存到图像时,它看起来不像预期的那样。

我还尝试使用 nullptr 作为调色板而不是 Grey256 或 Halftone256,但它也没有用。

我想我在 BitmapSource 的使用中遗漏了一些东西。有什么想法吗?

谢谢, 迪娜

请您参考如下方法:

使用 PngBitmapEncoder 而不是 BmpBitmapEncoder。 BmpBitmapEncoder 使图像变形。 使用 PngBitmapEncoder 示例可以正常工作。

同样出于性能原因尝试使用:

BitmapSource.Create(Int32, Int32, Double, Double, PixelFormat, BitmapPalette,  
    IntPtr, Int32, Int32)  

代替

BitmapSource.Create(Int32, Int32, Double, Double, PixelFormat, BitmapPalette,  
    Array, Int32)