2009-12-02 35 views
6

Tôi có hình ảnh chữ ký Tôi đang cố gắng lưu dưới dạng bitmap 1 bpp để tiết kiệm dung lượng tệp. Khuôn khổ .NET đầy đủ có enum PixelFormat.Format1bppIndexed, nhưng .NET Compact Framework không hỗ trợ nó.Chuyển đổi hình ảnh thành bitmap 1 bpp trong khung nhỏ gọn .net

Có ai phát hiện ra cách để thực hiện việc này trong Windows Mobile không?

Trả lời

6

Cảm ơn bạn đã chỉ cho tôi đúng hướng, ctacke. Tôi không thể sử dụng lớp Bitmap để lưu dữ liệu hình ảnh. Nó liên tục ném OutOfMemoryException. Tôi đã sử dụng một BinaryWriter, như bạn đã gợi ý.

giải pháp cuối cùng của tôi trả về một mảng byte, mà bạn có thể chọn để ghi vào đĩa, lưu vào một cơ sở dữ liệu, truyền vv

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

cũng được thực hiện, Jack – ctacke

+0

Đừng cho rằng bạn biết nơi bạn có Win32.DeleteObject (và các phương pháp Win32 khác)? Tôi có một dự án Win32 trong giải pháp của tôi nhưng nó không có những phương pháp đó. Bạn có tự cuộn chúng (hoặc bạn có thể nhớ sau một thời gian dài không?) – Vaccano

+2

Chúng là các hàm P/Invoke từ coredll.dll. Ví dụ: [DllImport ("coredll.dll")] public static extern void DeleteObject (IntPtr hObj); – jnosek

1

Tạo và lưu bitmap bitmap có vấn đề ngay cả trong toàn bộ khuôn khổ.

Trước đây tôi đã viết một bài viết về các vấn đề này liên quan.

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

tôi revisited mã này trong bối cảnh khuôn khổ nhỏ gọn và phát hiện ra khi bạn đã làm điều đó giá trị enum không tồn tại, vì vậy bạn không thể tạo ra một hình ảnh bitonal từ đầu.

Tôi muốn được biết liệu bạn có thể tải hình ảnh biton có sẵn trong khung nhỏ gọn hay không. Nếu bạn có thể tải bitmap biton có sẵn, thì có thể đi mức thấp hơn và ghi định dạng hình ảnh bitmap vào đĩa hoặc luồng bộ nhớ trực tiếp, thay vì sử dụng các đối tượng GDI +, nhưng nó sẽ không tầm thường để làm như vậy .

11

Tôi phải làm điều này trong quá khứ để tạo màu đen & báo cáo màu trắng được in qua Bluetooth (hình ảnh màu hoặc thang độ xám quá lớn đối với bộ đệm của máy in). Hóa ra tôi phải tạo ra những hình ảnh bằng cách sử dụng mã nguồn gốc.

Dưới đây là một đoạn:

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); 
} 

sau đó tôi sử dụng Graphics.FromHdc để có được một đồ họa quản lý đối tượng mà tôi có thể vẽ bản báo cáo lên.

Tôi đã tiết kiệm với một BinaryWriter, nhưng đó là trong CF 1.0 ngày khi lớp Bitmap không có một Lưu, vì vậy bạn đang miễn phí và rõ ràng ở đó.

+0

Cảm ơn đã chỉ cho tôi đi đúng hướng. Tôi đã nghĩ ra một giải pháp (được đăng bên dưới) để xây dựng trên đoạn mã của bạn và chuyển đổi một đối tượng Bitmap thành một luồng bitmap 1 bpp bitmap. – jnosek

Các vấn đề liên quan