Bitmap und ihre Farbwerte



  • Hallo an Alle
    Ich weiß nicht mehr weiter.. hänge nun schon tage an folgendenProblem
    ich habe ein Bitmap in einem HBITMAP .
    das Bitmap wird auch angezeigt
    Ich möchte nun die Farbwerte des Bitmaps auslesen . Mit Getpixel komme ich nicht weiter weil es zu lahm ist..
    kann mir jemand eine möglichkeit nehnen um an die einzeln Farbwerte der Pixel zu kommen...???
    Habe es schon mit RGBTRIPLE versucht bekomme aber immer den Wert null zurück



  • @hans12345678 sagte in Bitmap und ihre Farbwerte:

    s auslesen . Mit Getpixel ko

    Hallo Hans,

    es gibt zwei Möglichkeiten , entweder du erzeugst eine Dib -Section und "blittest" das Bild dort rein, und hast dann einen linearen Zugriff auf das Bild , oder du holst einen Zeiger auf die Bits der Depended Bitmap :

    Beispiel 1)

    BITMAP bitmap;
    if(!::GetObject ((HBITMAP)hBmp, sizeof (bitmap), &bitmap))
      return false;
    
    if(!bitmap.bmBits)
      return false;
    

    bitmap.bmBits enthält den Zeiger auf die Pixel entsprechend der Bittiefe.

    Beispiel 2)

    Mit Load from File : Auf CreateDibsection beim laden achten :

    BITMAP bm;
    		HBITMAP hb;
    		if (!(hb = (HBITMAP)::LoadImage(NULL, m_strFilename, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE))) return;
    		if (!::GetObject((HBITMAP)hb, sizeof(BITMAP), &bm)) return;
    		if (!bm.bmBits) return;
    

    Besser ist es aber eine Bitsection zu erzeugen , und dann in diese dein Bild zu blitten, danach kannst Du die Pixel in dem Format zurück lesen wie du die Section angelegt hast das ist die schnellste lösung, und wird immer effektiver wenn man diese als Vorlage verwendet.

    PseudoCode Beispiel 3)

    independed Bitmaps :

    m_hdd  = DrawDibOpen();
    
    
    void CDib::Delete()
    {
      m_filename.Empty();
    
      FreeBitmapInfo(&m_pBitmapInfo);
    
      if(m_hOldBitmap)
    	SelectObject(m_hDC,m_hOldBitmap);
    
      if(m_hBmp)//delete DibSection 
    	DeleteObject(m_hBmp),m_hBmp=0,m_pDat=0;
    
      if(m_pJpgDat)
    	delete [] m_pJpgDat,m_pJpgDat = 0,m_Jpgsize = JPGSTREAM;
    
      if (m_hFile != INVALID_HANDLE_VALUE)
      {
    	  DWORD fl(HANDLE_FLAG_INHERIT);
    	  if (GetHandleInformation(m_hFile, &fl))
    	  ::CloseHandle(m_hFile), m_hFile = INVALID_HANDLE_VALUE;
      }
    
      if(m_hDC)
    	DeleteDC(m_hDC),m_hDC=0;
    }
    
    bool CDib::Create(int Width, int Height, int Bpp/*=32*/,int board/*=0*/,int port/*=0*/,int NumBuffs/*=1*/)
    {
    	CDib::Delete();
    
    	if(!m_hdd)
          return  CVersions::DbgMsg(false,"error: Dib:Create:DibOpen\n");
    
    	if (!AllocBitmapInfo(&m_pBitmapInfo, Width, -Height, Bpp))
    	 return CVersions::DbgMsg(false, "error: Dib:Create:AllocBitmapInfo\n");
    	
    	m_Height = abs(Height);
    	m_Width  = Width;
    	m_Bpp    = Bpp;
    
    	if(!(m_hDC = CreateCompatibleDC(0)))
        {
    	  Delete();
    	  return  CVersions::DbgMsg(false,"error: Dib:Create:CreateCompatibleDC\n");
        }
    	
    	GdiFlush();//see documentation
    
    	m_hFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, m_pBitmapInfo->bmiHeader.biSizeImage, NULL);
        m_hBmp  = CreateDIBSection(m_hDC, m_pBitmapInfo, DIB_RGB_COLORS, (void**)&m_pDat, (INVALID_HANDLE_VALUE != m_hFile)? m_hFile:NULL, NULL);
    	if(!m_hBmp)
        {
    		CDib::Delete();
    		return  CVersions::DbgMsg(false, "Dib:Create:DIBSection error W(%d) H(%d) BPP(%d)\n", Width, Height, Bpp);
        }
    	
    	m_hOldBitmap = (HBITMAP)SelectObject (m_hDC, m_hBmp);// Select hBitmap Into Our Device Context (hdc)
    
    	return true;
    }
    
    bool CDib::FreeBitmapInfo(BITMAPINFO **ppBitmapInfo)
    {
    	if (!*ppBitmapInfo)
    		return FALSE;
    
    	delete *ppBitmapInfo; *ppBitmapInfo = 0;
    }
    
    //GFX braucht eine vorlage von Bitmapinfo die Kameras liefern diese daten nicht
    //lediglich CDib also lag es nache eine bitmapinfo erzeugen zu lassen der anrufer
    //ist schuldig diese selber wieder freizugeben 
    bool CDib::AllocBitmapInfo(BITMAPINFO **ppBitmapInfo, int Width, int Height, int Bpp)
    {
    	*ppBitmapInfo = (BITMAPINFO*)(new char[sizeof(BITMAPINFOHEADER) + ((Bpp == 8 ? 256 : 1)*sizeof(RGBQUAD))]);
    
    	if (!*ppBitmapInfo)
    		return FALSE;
    
    	(*ppBitmapInfo)->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    	(*ppBitmapInfo)->bmiHeader.biWidth = Width;
    	(*ppBitmapInfo)->bmiHeader.biHeight = Height;//Bpp==8|Bpp==24?-Height:Height;//botomup
    	(*ppBitmapInfo)->bmiHeader.biPlanes = 1;
    	(*ppBitmapInfo)->bmiHeader.biBitCount = Bpp;
    	(*ppBitmapInfo)->bmiHeader.biCompression = BI_RGB;
    	(*ppBitmapInfo)->bmiHeader.biSizeImage = Width*abs(Height)*(Bpp >> 3);
    	(*ppBitmapInfo)->bmiHeader.biXPelsPerMeter = 0;
    	(*ppBitmapInfo)->bmiHeader.biYPelsPerMeter = 0;
    	(*ppBitmapInfo)->bmiHeader.biClrUsed = Bpp == 8 ? 256 : 0;
    	(*ppBitmapInfo)->bmiHeader.biClrImportant = 0;
    
    
    	if ((*ppBitmapInfo)->bmiHeader.biClrUsed)
    	{
    		SetColorbasis(*ppBitmapInfo, RGB(255, 255, 255), 1,true);
    	}
    
    	return true;
    }
    
    
    void CDib::SetColorbasis(BITMAPINFO *pBmi, COLORREF basecol, BYTE chanels, bool setgraymap/*= true*/)
    {
    	if (!pBmi)
    	{
    		if (!m_pBitmapInfo)
    			return;
    
    		pBmi = m_pBitmapInfo;
    	}
    
    	int step = max((chanels / 8) * 8, 1);
    	int loops = pBmi->bmiHeader.biClrUsed - (step>1 ? step : 0);
    	for (int i = 0; i < loops; i += step)
    		for (int n = 0; n < step; n++)
    		{
    			float r((GetRValue(basecol) / 255.0f)*i),
    				g((GetGValue(basecol) / 255.0f)*i),
    				b((GetBValue(basecol) / 255.0f)*i);
    
    			pBmi->bmiColors[i + n].rgbRed = r;
    			pBmi->bmiColors[i + n].rgbGreen = g;
    			pBmi->bmiColors[i + n].rgbBlue = b;
    			pBmi->bmiColors[i + n].rgbReserved = 0;
    
    			if (setgraymap) *((DWORD *)&m_GrayMap[i + n]) = (r + g + b) / 3;
    		}
    }
    
    void CDib::SetColorbasis(RGBQUAD *pRgbDat)
    {
    	if (m_pBitmapInfo && pRgbDat)
    		for (int i = 0; i<256; i++)
    		{
    			m_pBitmapInfo->bmiColors[i] = pRgbDat[i];
    		}
    }
    
    BOOL CDib::Draw(HDC hdc,void *pMem,CRect rc,int xSrcOffset,int ySrcOffset,int xDstOffset,int yDstOffset)
    {	
      if(!m_pBitmapInfo)
    	return FALSE;
    
      if(!pMem)
       pMem = m_pDat;
    
      ::SetDIBitsToDevice(hdc,    
    	            rc.left+xDstOffset,
    				rc.top+yDstOffset,
    				rc.Width(),
    				rc.Height(),
    				rc.left+xSrcOffset,                            //SrcX
    				abs(m_pBitmapInfo->bmiHeader.biHeight) - (rc.top+ySrcOffset) - rc.Height(),  //SrcY
    				0,                         
    				abs(m_pBitmapInfo->bmiHeader.biHeight),             
    				(void *)pMem,
    				m_pBitmapInfo,
    				DIB_RGB_COLORS//DIB_PAL_COLORS  
    				);
    
      return TRUE;
    }
    
    

    Nach CreateDibSecion ist der Zeiger m_pDat ständig aktuell auf die zugehörigen Pixeldaten, die HAL HardwareAbstarktionsLayer sorgt dafür das dieser Speicherzeiger in die Grafikhardware gemap't wird, so ist es unter 32 Bit sogar möglich unbegrenzte Bildmengen zu hosten .



  • ganz herzlichen dank..
    werde dieses versuchen und mich Rückmelden. Vielen dank nochmal😃



  • Cool man 🙂



  • @KahnSoft
    Habe ich es richtig verstanden-- Die Farbe steht jeweils in bm.bmBits???
    und wie komme ich ich nun zum Beispiel an pixel nr 37??



  • @hans12345678 Hallo Hans,
    ok dahinter steht natürlich das Speicherfeld , ab dieser Adresse beginnen die Daten.

    Für normal handelt es sich um ein 3Byte (24Bit RGB) die Farbwerte stehen in den Bitmaps zumeist in der Folge BGR
    und werden über einen Byte Pointer aufgelöst , das geht dann also so:

    Nachdem Du den Zeiger über GetObject erhalten hast , kannst Du die Farbwerte wie folgt durchlaufen:

    Das trifft nun ausschließlich für 24Bit Grafiken zu, über DibSektionen kannst Du auch Grauwerte Bilder handhaben oder 32Bit RGBA mit Alphakanal. Aber zum Anfang dürfte das folgende ausreichen, der Zeiger muss gegen Null geprüft werden:

    BYTE *pMem((BYTE *)bm.bmBits);
    
    for(int y(0); x<bm.bmHeight; y++)
    for(int x(0); x<bm.bmWidth; x++)
    {
          BYTE blue(*pMem++);
          BYTE green(*pMem++);
          ByTE red(*pMem++);
    }
    


  • @KahnSoft

    kurzer Probelauf und es geht😃 😃

    BYTE *pMem((BYTE *)bm.bmBits);
    

    for(int y(0); y<bm.bmHeight; y++)
    {

    for(int x(0); x<bm.bmWidth; x++)
    {
    BYTE blue(*pMem++);
    BYTE green(*pMem++);
    BYTE red(*pMem++);
    tester[x]=red;

    }
    }

     for(int y; y<50; y++)
    

    {

    for(int x; x<50; x++)
    {
    a=a+30;

    sprintf(temp41,"%d",tester[x]);
    TextOut(DevC,a,b,temp41,3);

    }
    b=b+20;
    }

    ganz einfach(wen man weiß wie es geht)..😉 😉

    nochmal herzlichen Dank..Du hast mir sehr geholfen.....Danke



  • @hans12345678 Wunderbar, aber GetObjekt ist recht langsam.. das beste was Windows bietet sind dib -sectionen -hardwareunterstützt (HAL) , du kannst damit in unter 1ms 50MB hin und her schiffen im VM(Virtual Memory) Grenzenloser pixelspass 🙂


Log in to reply