Click here to Skip to main content
15,907,687 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Hi we have problem with reading bitmap data using C# functions:

we have implemented textmanager and we want to create bitmap with Pixelformat Format1bppIndexed for text entered in my textbox.


We want to get bitmap data in byte array, for that purpose I am using Bitmap.LockBits methode. to copy Bitmapdata in to byte array I am creating byte array,Array size is calculated using "BitmapData.Stride" and "BitmapData.Width".

We have VC++ application there we have same functionality to read bitmap data in byte array and write to some hardware, we want to implment same in C#. I tried to port code in C# code is working fine but output is not as per expectations.
When I tried to get byte array in C# and VC++ for same text , byte array content are different. It should be same in VC++ and C# , Am I missing some steps?

I am not able to find out solution for same.

dose any body face same issue in development?
C#
private void button2_Click(object sender, EventArgs e)
      {
          Bitmap bmp = new Bitmap(1, 1);
          Graphics g = Graphics.FromImage(bmp);

          int w = (int)g.MeasureString(textBox1.Text, fontDialog1.Font).Width;
          int h = (int)g.MeasureString(textBox1.Text, fontDialog1.Font).Height;

          Bitmap bmp2 = new Bitmap(w, h,PixelFormat.Format32bppArgb);
          Graphics g2 = Graphics.FromImage(bmp2);
          Brush brush = new SolidBrush(Color.White);
          g2.FillRectangle(brush, 0, 0, bmp2.Width, bmp2.Height);
          Brush brush2 = new SolidBrush(Color.Black);
          g2.DrawString(textBox1.Text, fontDialog1.Font, brush2, 0, 0);
          g2.Flush();

          Bitmap bmp_return = Bitmap_Conversion.ConvertToBitonal(bmp2);

          bmp2.Save(@"c:\temp\test.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
          bmp_return.Save(@"c:\temp\test1.bmp", System.Drawing.Imaging.ImageFormat.Bmp);

          Rectangle rect = new Rectangle(0, 0, bmp_return.Width, bmp_return.Height);
          System.Drawing.Imaging.BitmapData bmpData =
              bmp_return.LockBits(rect, ImageLockMode.ReadWrite, bmp_return.PixelFormat);

          IntPtr ptr = bmpData.Scan0;

          int bytes = Math.Abs(bmpData.Stride) * bmp_return.Height;

          byte[] rgbValues = new byte[bytes];

          System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);

          StreamWriter fs = new StreamWriter(Environment.GetEnvironmentVariable("tmp") + @"\Hoge.txt");

          fs.Close();
          bmp2.Dispose();
          bmp.Dispose();
          g.Dispose();
      }

public static Bitmap BitmapTo1Bpp(Bitmap img)
      {
          int w = img.Width;
          int h = img.Height;
          Bitmap bmp = new Bitmap(w, h, PixelFormat.Format1bppIndexed);
          BitmapData data = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format1bppIndexed);
          for (int y = 0; y < h; y++)
          {
              byte[] scan = new byte[(w + 7) / 8];
              for (int x = 0; x < w; x++)
              {
                  Color c = img.GetPixel(x, y);
                  if (c.GetBrightness() >= 0.5) scan[x / 8] |= (byte)(0x80 >> (x % 8));
              }
              Marshal.Copy(scan, 0, (IntPtr)((int)data.Scan0 + data.Stride * y), scan.Length);
          }
          bmp.UnlockBits(data);
          return bmp;
      }
Posted
Updated 13-Jun-12 4:37am
v2
Comments
Fredrik Bornander 13-Jun-12 10:45am    
Is the generated bmp file identical to the one you get from the C++ version?
Somnath T Avhad 14-Jun-12 1:11am    
In C++ we are not creating any bitmap file on disk as such
everything is in memory.
Somnath T Avhad 14-Jun-12 1:13am    
When I am using VC++ equivalent functions in C# , both should be identical.
That is the reason bitmap data is not indentical for bitmaps created in VC++ and C#.
Somnath T Avhad 14-Jun-12 1:22am    
I am adding VC++ code here.
void CTextBitmapWnd::CreateBitmapFromText(BYTE* pbByteArray,CString a_SMessage,CWindowsFontCDC* a_pWinFontCDC,int a_eHorizontalAllignment /*= E_INVALID_ALIGNMENT */ , bool a_bDrawVertical /*=FALSE*/ )
{
CString a_sMessage = a_SMessage;
int iMsgLen = a_sMessage.GetLength();

//int iMsgLen = 3;
if(0 == iMsgLen)
{
a_pWinFontCDC->m_uiBitmapDataSize = 0;
a_pWinFontCDC->m_BmpSize.cx = 0;
a_pWinFontCDC->m_BmpSize.cy = 0;

return;
}

m_sMessage = a_sMessage;
m_eHorizontalAllignment = a_eHorizontalAllignment;
m_bDrawVertical = a_bDrawVertical;

m_sMessage = AddCarriageReturn(m_sMessage);

CDC* pDC = GetDC();

CDC MemDC;
MemDC.CreateCompatibleDC( pDC );

CFont txtFont;
txtFont.CreateFontIndirect( &a_pWinFontCDC->m_winLogFont );
CFont* pOldFont = pDC->SelectObject( &txtFont );

int iPreviousExtraCharacters = pDC->GetTextCharacterExtra();
pDC->SetTextCharacterExtra(a_pWinFontCDC->m_uiCharacterPitch);

CalculateEndPoints(pDC, a_pWinFontCDC);
CRect rcTxt(0,0,m_szBitmap.cx, m_szBitmap.cy);

pDC->SelectObject( pOldFont );

int iImageSize = WIDTHBYTES(rcTxt.Width()) * rcTxt.Height();

int iTotalSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 2 + iImageSize;

m_lpBmpInfo = (LPBITMAPINFO) new BYTE[iTotalSize];

memset( m_lpBmpInfo, 0, iTotalSize );

m_lpBmpInfo->bmiHeader.biBitCount = 1;
m_lpBmpInfo->bmiHeader.biClrImportant = 1;
m_lpBmpInfo->bmiHeader.biClrUsed = 2;
m_lpBmpInfo->bmiHeader.biCompression = BI_RGB;
m_lpBmpInfo->bmiHeader.biHeight = rcTxt.Height();
m_lpBmpInfo->bmiHeader.biWidth = rcTxt.Width();
m_lpBmpInfo->bmiHeader.biPlanes = 1;
m_lpBmpInfo->bmiHeader.biSize = sizeof(m_lpBmpInfo->bmiHeader);
m_lpBmpInfo->bmiHeader.biSizeImage = WIDTHBYTES(m_lpBmpInfo->bmiHeader.biWidth) * m_lpBmpInfo->bmiHeader.biHeight;

m_lpBmpInfo->bmiColors[0].rgbRed = m_lpBmpInfo->bmiColors[0].rgbGreen = m_lpBmpInfo->bmiColors[0].rgbBlue = 0;
m_lpBmpInfo->bmiColors[1].rgbRed = m_lpBmpInfo->bmiColors[1].rgbGreen = m_lpBmpInfo->bmiColors[1].rgbBlue = 255;

LPBYTE lpData = (LPBYTE)(m_lpBmpInfo + sizeof(BITMAPINFOHEADER));

m_hBitmap = (HBITMAP)::CreateDIBSection(pDC->GetSafeHdc(),m_lpBmpInfo, DIB_RGB_COLORS, (void**)&lpData, NULL, 0);

CBitmap messageBmp;
messageBmp.Attach( m_hBitmap );

iPreviousExtraCharacters = MemDC.GetTextCharacterExtra();
MemDC.SetTextCharacterExtra(a_pWinFontCDC->m_uiCharacterPitch);

CBitmap* pOldBmp = MemDC.SelectObject(&messageBmp);
pOldFont = MemDC.SelectObject( &txtFont );
COLORREF OldTextColor = MemDC.SetTextColor( RGB(255,255,255));
COLORREF OldTextBkColor = MemDC.SetBkColor( RGB(0,0,0));
MemDC.FillSolidRect(rcTxt, RGB(0,0,0));
DrawMessage(&MemDC, a_pWinFontCDC);

MemDC.SelectObject( pOldBmp );
MemDC.SelectObject( pOldFont );
CBitmap* pBitmap = new CBitmap();
pBitmap->Attach( messageBmp.Detach() );
messageBmp.DeleteObject();

DIBSECTION ds;
pBitmap->GetObject(sizeof(DIBSECTION), &ds);

a_pWinFontCDC->m_BmpSize.cy = ds.dsBm.bmHeight;
a_pWinFontCDC->m_BmpSize.cx = ds.dsBm.bmWidth;
a_pWinFontCDC->m_uiBitmapDataSize = WIDTHBYTES(ds.dsBm.bmWidth) * ds.dsBm.bmHeight;

//-----------------------------------------------------------------------------------------------------------------------
BITMAP Bmp;
pBitmap->GetBitmap( &Bmp );

iTotalSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 2;
LPBITMAPINFO lpBmpInfo = (LPBITMAPINFO) new BYTE[iTotalSize];

lpBmpInfo->bmiHeader.biBitCount = 1;
lpBmpInfo->bmiHeader.biClrImportant = 1;
lpBmpInfo->bmiHeader.biClrUsed = 2;
lpBmpInfo->bmiHeader.biCompression = BI_RGB;
lpBmpInfo->bmiHeader.biHeight = Bmp.bmHeight;
lpBmpInfo->bmiHeader.biWidth = Bmp.bmWidth;
lpBmpInfo->bmiHeader.biPlanes = 1;
lpBmpInfo->bmiHeader.biSize = sizeof(lpBmpInfo->bmiHeader);
lpBmpInfo->bmiHeader.biSizeImage = WIDTHBYTES(lpBmpInfo->bmiHeader.biWidth) * lpBmpInfo->bmiHeader.biHeight;

lpBmpInfo->bmiColors[0].rgbRed = lpBmpInfo->bmiColors[0].rgbGreen = lpBmpInfo->bmiColors[0].rgbBlue =
Fredrik Bornander 14-Jun-12 2:24am    
Why not change the C++ code to create the bitmap, that way you can compare them?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900