Winapi wczytanie kolorow bitmapy do macierzy -error

0

Witam,

napisalem funkcje w winapi, ktora wczytuje bity z bitmapy (24 bit) do macierzy. Kompiluje sie, ale niestety dziala niepoprawnie-zwraca zle wartosci. Nie moge znalezc bledu. Oto kod:

int*** LoadBMPfromClipboard(HBITMAP hBMP,HDC hDC)
{
HANDLE hf; // file handle
BITMAPFILEHEADER hdr; // bitmap file-header
PBITMAPINFOHEADER pbih; // bitmap info-header
LPBYTE lpBits; // memory pointer
DWORD dwTotal; // total count of bytes
DWORD cb; // incremental count of bytes
BYTE *hp; // byte pointer
DWORD dwTmp;

PBITMAPINFO pbi;
pbi=CreateBitmapInfoStruct(hBMP);
int height,width,depth;

pbih = (PBITMAPINFOHEADER) pbi;
lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
//!!!! if (!lpBits)
// errhandler("GlobalAlloc", hwnd);
// Retrieve the color table (RGBQUAD array) and the bits
// (array of palette indices) from the DIB.
GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi,
DIB_RGB_COLORS);
/*!!!! if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi,
DIB_RGB_COLORS))
{
errhandler("GetDIBits", hwnd);
}
*/
width = pbi->bmiHeader.biWidth;
height = pbi->bmiHeader.biHeight;
depth = 24;
//////make an array
int ***array;
array = new int **[height];
for(int i=0;i<height;i++)
array[i] = new int*[width];
for(int i=0;i<height;i++)
for(int j=0;j<width;j++)
{
// if( depth == 1)
// array[i][j]= new float[1];
// else if(depth == 32)
// array[i][j]= new float[4];
// else if(depth == 24)
array[i][j]= new int[3];
}
//////put JPEG to array
hp = lpBits;
for(int i=0;i<height;i++)
for(int j=0;j<width;j++)
{
/* if( depth == 1)
{


}
else if(depth == 32)
{

} */
//else if(depth == 24)
//{
array[i][j][0]= *hp++;
array[i][j][1]= *hp++;
array[i][j][2]= *hp++;
//}
}

return array;
}

Z gory dziekuje za pomoc.
Pozdrawiam

//q: wlaczylem formatowanie, ale to nic nie dalo.. spotkamy sie w koszu, ja tego re-formatowac za Ciebei nie bede

0
lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
PSDK napisał(a)

biSizeImage
Specifies the size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps.

Warto to sprawdzać, tak na wszelki wypadek ;)

hp = lpBits;
for(int i=0;i<height;i++)
   for(int j=0;j<width;j++)
   {
       array[i][j][0]= *hp++;
       array[i][j][1]= *hp++;
       array[i][j][2]= *hp++;
    }

scanline'y (wiersze) w bitmapach (RGB) są wyrównane do DWORD'a, więc nie możesz po prostu przesuwać wskaźnika hp co trzy bajty - tylko dla wierszy to przejdzie.

Spróbuj tak:

// tylko dla RGB 24bit
int  skip_alignment=4-((width*3)%4);

for(int i=0;i<height;i++)
{
   for(int j=0;j<width;j++)
   {
       array[i][j][0]= hp[0];
       array[i][j][1]= hp[1];
       array[i][j][2]= hp[2];
       hp+=3;
    }

    hp+=skip_alignment;
}
0

Twoj kod kompiluje sie, ale dostaje dziwne wartosci. Wczytuje wpierw do bitmapy przykladowa tablice [znakow - 1 bajty kazdy], potem zczytuje jej wartosci do tablicy. Wyniki niestety nie porywaja sie z wartosciami w tablicy (e.g. w tabl. pocz. jako 1 znak mam: 'w', wart. ASCI: 119, a otrzymuje: 13)
Wklejam kod testujacy funkcje programu:

    HBITMAP hbitmap1;
    int ***array; 
    char tablica[120]={'w','2','c','a','i','b','o','f','r','t','u','i','3','u','i','4','k','j','6','7',
'w','2','c','a','i','b','o','f','r','t','u','i','3','u','i','4','k','j','6','7',
'w','2','c','a','i','b','o','f','r','t','u','i','3','u','i','4','k','j','6','7',
'w','2','c','a','i','b','o','f','r','t','u','i','3','u','i','4','k','j','6','7',
'w','2','c','a','i','b','o','f','r','t','u','i','3','u','i','4','k','j','6','7',
'w','2','c','a','i','b','o','f','r','t','u','i','3','u','i','4','k','j','6','7'}; 

 hbitmap1 = CreateBitmap(5,8,1,24,tablica); 
      HDC dc1 = CreateCompatibleDC(NULL);
      SelectObject(dc1, hbitmap1);
array = LoadBMPfromClipboard(hbitmap1,dc1);
0

A co zwraca CreateBitmap ??? :>

0

Zwraca nastepujace wartosci:

If the function succeeds, the return value is a handle to a bitmap.

If the function fails, the return value is NULL.

Deklaracja funkcji jest nastepujaca: HBITMAP WINAPI CreateBitmap(int,int,UINT,UINT,PCVOID);

Znalazlem nastepujaca adnotacje na stronie msdn:

The CreateBitmap function can be used to create color bitmaps. However, for performance reasons applications should use CreateBitmap to create monochrome bitmaps and CreateCompatibleBitmap to create color bitmaps.

W takim razie musze jeszcze uzyc funkcji CreateCompatibleBitmap() ??

0

Ale ja nie pytałem się o specyfikację funkcji, tylko o to, co zwraca ta funkcja w twoim kodzie. U Ciebie nie ma w ogóle sprawdzania błędów, a bez tego to można sobie zgadywać gdzie leży problem.

W takim razie musze jeszcze uzyc funkcji CreateCompatibleBitmap() ??

Niekoniecznie. CreateCompatibleBitmap stworzy bitmapę z rozdzielczością koloru zgodną z HDC, a ty musisz mieć zawsze 24 bity ponieważ twój kod innych nie obsługuje.

Przeczytaj jeszcze raz (ze zrozumieniem) co pisałem o wyrównaniu wierszy (scanline) bo w PSDK dla CreateBitmap masz:

 <i>Each scan line in the rectangle <u>must be word aligned</u> (scan lines that are not word aligned must be padded with zeros). 
</i> teraz przelicz sobie ile twoja bitmapa ma bajtów w wierszu i czy jest poprawnie wyrównana.
0

Twoja testowa 'tablica' do tworzenia bitmapy też musi być word-aligned. Jak sobie nie możesz poradzić to może po prostu użyj 32 bitowych bitmap.
No i dlaczego GlobalAlloc ???? Do tworzenia DIB'ów jest CreatDIBSection.
Nie pokazałeś jeszcze jak wygląda CreateBitmapInfoStruct. Może coś źle wypełnia.

1 użytkowników online, w tym zalogowanych: 0, gości: 1