2012-03-06 113 views
2

我想将本机图像数据结构编组为BitmapSource。使用像素数组初始化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; 
     } 

我测试一个简单的单信道的情况下我的功能:

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的使用中缺少一些东西。有任何想法吗?

感谢, 迪娜

回答

0

使用PngBitmapEncoder而不是BmpBitmapEncoderBmpBitmapEncoder使图像变形。 与PngBitmapEncoder该示例正常工作。

而且出于性能的考虑尝试使用:的

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

代替

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

谢谢!它确实有效! – Dina 2012-03-06 14:39:24