2012-03-06 75 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