2009-12-02 10 views
6

मेरे पास एक हस्ताक्षर की एक छवि है जिसे मैं फ़ाइल स्थान को सहेजने के लिए 1 बीपीपी बिटमैप के रूप में सहेजने की कोशिश कर रहा हूं। पूर्ण .NET Framework में enum PixelFormat.Format1bppIndexed है, लेकिन .NET कॉम्पैक्ट फ्रेमवर्क इसका समर्थन नहीं करता है।छवि को 1 बीपीपी बिटमैप में कनवर्ट करें .नेट कॉम्पैक्ट फ्रेमवर्क

क्या किसी ने विंडोज मोबाइल में इसे पूरा करने का कोई तरीका खोजा है?

उत्तर

6

सही दिशा में मुझे इंगित करने के लिए धन्यवाद, ctacke। मैं छवि डेटा को सहेजने के लिए Bitmap कक्षा का उपयोग करने में असमर्थ था। यह लगातार OutOfMemoryException फेंक दिया। मैंने सुझाए गए बाइनरीवाइटर का उपयोग करके बिटमैप लिखने का सहारा लिया।

मेरे अंत समाधान एक बाइट सरणी, जिसके साथ आप डिस्क पर लिखने के लिए चुन सकते हैं, एक डेटाबेस के लिए बचाने के लिए, संचारित, आदि

class ImageHelper 
{ 
    [StructLayout(LayoutKind.Sequential)] 
    public struct BITMAPINFOHEADER 
    { 
     public BITMAPINFOHEADER(ushort bpp, int height, int width) 
     { 
      biBitCount = bpp; 
      biWidth = width; 
      biHeight = height; 

      biSize = (uint)Marshal.SizeOf(typeof(BITMAPINFOHEADER)); 
      biPlanes = 1; // must be 1 
      biCompression = 0; // no compression 
      biSizeImage = 0; // no compression, so can be 0 
      biXPelsPerMeter = 0; 
      biYPelsPerMeter = 0; 
      biClrUsed = 0; 
      biClrImportant = 0; 
     } 

     public void Store(BinaryWriter bw) 
     { 
      Store(bw, null); 
     } 

     public void Store(BinaryWriter bw, uint[] colorPalette) 
     { 
      // Must maintain order for file writing 
      bw.Write(biSize); 
      bw.Write(biWidth); 
      bw.Write(biHeight); 
      bw.Write(biPlanes); 
      bw.Write(biBitCount); 
      bw.Write(biCompression); 
      bw.Write(biSizeImage); 
      bw.Write(biXPelsPerMeter); 
      bw.Write(biYPelsPerMeter); 
      bw.Write(biClrUsed); 
      bw.Write(biClrImportant); 

      // write color palette if 8 bpp or less 
      if (biBitCount <= 8) 
      { 
       if (colorPalette == null) 
        throw new ArgumentNullException("bpp is 8 or less, color palette is required"); 

       uint paletteCount = BITMAPFILEHEADER.CalcPaletteSize(biBitCount)/4; 
       if (colorPalette.Length < paletteCount) 
        throw new ArgumentException(string.Format("bpp is 8 or less, color palette must contain {0} colors", paletteCount)); 

       foreach (uint color in colorPalette) 
        bw.Write(color); 
      } 
     } 

     public uint biSize; 
     public int biWidth; 
     public int biHeight; 
     public ushort biPlanes; 
     public ushort biBitCount; 
     public uint biCompression; 
     public uint biSizeImage; 
     public int biXPelsPerMeter; 
     public int biYPelsPerMeter; 
     public uint biClrUsed; 
     public uint biClrImportant; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct BITMAPFILEHEADER 
    { 
     public BITMAPFILEHEADER(BITMAPINFOHEADER info, out uint sizeOfImageData) 
     { 
      bfType = 0x4D42; // Microsoft supplied value to indicate Bitmap 'BM' 
      bfReserved1 = 0; 
      bfReserved2 = 0; 

      // calculate amount of space needed for color palette 
      uint paletteSize = CalcPaletteSize(info.biBitCount); 

      bfOffBits = 54 + paletteSize; // default value + paletteSize 

      // calculate size of image 
      sizeOfImageData = (uint)(CalcRowSize(info.biWidth * info.biBitCount) * info.biHeight); 
      bfSize = sizeOfImageData + bfOffBits; 
     } 

     private static int CalcRowSize(int bits) 
     { 
      return ((((bits) + 31)/32) * 4); 
     } 

     public static uint CalcPaletteSize(int bpp) 
     { 
      // 8 bpp or less, needs an uint per color 
      if (bpp <= 8) 
       return 4 * (uint)Math.Pow(2, bpp); 

      // no palette needed for 16bpp or higher 
      return 0; 
     } 

     public void Store(BinaryWriter bw) 
     { 
      // Must maintain order for file writing 
      bw.Write(bfType); 
      bw.Write(bfSize); 
      bw.Write(bfReserved1); 
      bw.Write(bfReserved2); 
      bw.Write(bfOffBits); 
     } 

     public ushort bfType; 
     public uint bfSize; 
     public short bfReserved1; 
     public short bfReserved2; 
     public uint bfOffBits; 
    } 

    public static byte[] GetByteArray(Bitmap image) 
    { 
     IntPtr hbmOld; 
     IntPtr hBitmap; 
     IntPtr hDC; 

     // create infoheader 
     BITMAPINFOHEADER bih = new BITMAPINFOHEADER(1, image.Height, image.Width); 
     // set black and white for 1 bit color palette 

     // create fileheader and get data size 
     uint sizeOfImageData; 
     BITMAPFILEHEADER bfh = new BITMAPFILEHEADER(bih, out sizeOfImageData); 

     // create device context in memory 
     hDC = Win32.CreateCompatibleDC(IntPtr.Zero); 

     // create a 1 bpp DIB 
     IntPtr pBits = IntPtr.Zero; 
     hBitmap = Win32.CreateDIBSection(hDC, ref bih, 1, ref pBits, IntPtr.Zero, 0); 

     // selet DIB into device context 
     hbmOld = Win32.SelectObject(hDC, hBitmap); 

     using (Graphics g = Graphics.FromHdc(hDC)) 
     { 
      g.DrawImage(image, 0, 0); 
     } 

     byte[] imageData = new byte[sizeOfImageData]; 
     byte[] fileData; 

     using (MemoryStream ms = new MemoryStream((int)bfh.bfSize)) 
     { 
      using (BinaryWriter w = new BinaryWriter(ms)) 
      { 
       bfh.Store(w); 
       // store bitmapinfoheader with 1 bpp color palette for black and white 
       bih.Store(w, new uint[] { (uint)0x0, (uint)0xffffff }); 

       // copy image data into imageData buffer 
       Marshal.Copy(pBits, imageData, 0, imageData.Length); 

       // write imageData to stream 
       w.Write(imageData); 

       w.Close(); 
      } 

      fileData = ms.GetBuffer(); 
      ms.Close(); 
     } 

     // select old object 
     if (hbmOld != IntPtr.Zero) 
      Win32.SelectObject(hDC, hbmOld); 

     // delete memory bitmap 
     if (hBitmap != IntPtr.Zero) 
      Win32.DeleteObject(hBitmap); 

     // delete memory device context 
     if (hDC != IntPtr.Zero) 
      Win32.DeleteDC(hDC); 

     return fileData; 
    } 
} 
+0

अच्छी तरह से किया गया, जैक – ctacke

+0

मान लीजिए कि आपको पता नहीं है कि आपको Win32.DeleteObject (और अन्य Win32 विधियों) कहां मिला है? मेरे पास मेरे समाधान में एक Win32 प्रोजेक्ट है लेकिन इसमें उन विधियां नहीं हैं। क्या आपने उन्हें स्वयं रोल किया था (या आप इतने लंबे समय बाद याद कर सकते हैं?) – Vaccano

+2

वे coredll.dll से P/Invoke फ़ंक्शन हैं। उदाहरण: [DllImport ("coredll.dll")] सार्वजनिक स्थैतिक बाहरी शून्य हटाएं निकालें (IntPtr hObj); – jnosek

1

बिटोनल बिटमैप बनाना और सहेजना पूर्ण ढांचे में भी समस्याग्रस्त है।

मैंने पहले इस मुद्दे पर शामिल एक लेख लिखा था।

http://www.codeproject.com/KB/GDI-plus/BitonalImageConverter.aspx

मैं कॉम्पैक्ट फ्रेमवर्क के संदर्भ में इस कोड को दोबारा गौर किया और पाया के रूप में तुमने किया था कि enum मूल्य, मौजूद नहीं है तो आप स्क्रैच से एक bitonal छवि नहीं बना सकते।

मुझे यह जानने में दिलचस्पी होगी कि क्या आप कॉम्पैक्ट फ्रेमवर्क में पूर्व-मौजूदा बिटोनल छवियों को लोड कर सकते हैं। यदि आप प्री-मौजूदा बिटोनल बिटमैप्स लोड कर सकते हैं, तो निम्न स्तर पर जाना संभव है और जीडीआई + ऑब्जेक्ट्स का उपयोग करने के बजाय डिस्कमैट छवि प्रारूप को डिस्क या मेमोरी स्ट्रीम पर सीधे लिखना संभव हो सकता है, लेकिन ऐसा करने के लिए यह गैर-तुच्छ होगा ।

11

मुझे ब्लैक & ब्लूटूथ के माध्यम से मुद्रित सफेद रिपोर्ट बनाने के लिए अतीत में ऐसा करना पड़ा था (रंग या ग्रेस्केल छवियां प्रिंटर के बफर के लिए बहुत बड़ी थीं)। बाहर निकला मुझे देशी कोड का उपयोग कर छवियां बनाना पड़ा।

private void CreateUnmanagedResources() 
{ 
    // for safety, clean up anything that was already allocated 
    ReleaseUnmanagedResources(); 

    bih = new BITMAPINFOHEADER(); 
    bih.biBitCount = 1; 
    bih.biClrImportant = 0; 
    bih.biClrUsed = 0; 
    bih.biCompression = 0; 
    bih.biHeight = m_cy; 
    bih.biPlanes = 1; 
    bih.biSize = (uint)(Marshal.SizeOf(typeof(BITMAPINFOHEADER)) - 8); 
    bih.biSizeImage = 0; 
    bih.biWidth = m_cx; 
    bih.biXPelsPerMeter = 0; 
    bih.biYPelsPerMeter = 0; 
    bih.clr2 = 0xffffff; 
    bih.clr1 = 0x0; 

    hDC = Win32.CreateCompatibleDC(IntPtr.Zero); 
    pBits = IntPtr.Zero; 
    hBitmap = Win32.CreateDIBSection(hDC, bih, 1, ref pBits, IntPtr.Zero, 0); 
    hbmOld = Win32.SelectObject(hDC, hBitmap); 
} 

private void ReleaseUnmanagedResources() 
{ 
    if (hbmOld != IntPtr.Zero) 
     Win32.SelectObject(hDC, hbmOld); 

    if(hBitmap != IntPtr.Zero) 
     Win32.DeleteObject(hBitmap); 

    if (hDC != IntPtr.Zero) 
     Win32.DeleteDC(hDC); 
} 

मैं तो Graphics.FromHdc इस्तेमाल किया एक प्रबंधित ग्राफिक्स वस्तु है कि मैं पर रिपोर्ट पेंट कर सकते प्राप्त करने के लिए:

यहाँ एक टुकड़ा है।

मैंने बाइनरीवाइटर के साथ बचत की, लेकिन यह सीएफ़ 1.0 दिनों में था जब बिटमैप कक्षा में कोई बचत नहीं थी, इसलिए आप वहां स्वतंत्र और स्पष्ट हैं।

+0

मुझे सही दिशा में इशारा करते हुए के लिए धन्यवाद देता है। मैंने एक समाधान तैयार किया है (नीचे पोस्ट किया गया है जो आपके स्निपेट पर बनाता है और बिटमैप ऑब्जेक्ट को 1 बीपीपी बिटमैप बाइट स्ट्रीम में परिवर्तित करता है। – jnosek

संबंधित मुद्दे