[C] bmp bitmap uitlezen

Pagina: 1
Acties:
  • 133 views sinds 30-01-2008
  • Reageer

  • Super_ik
  • Registratie: Maart 2001
  • Laatst online: 21-08 15:53
k wil een bitmap inlezen in een 2 dimensionale array
tis een progje dat ik omzet vanuit visual basic naar c

in vb deed ik dit:
Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Private Type pixel
    R As Byte
    G As Byte
    B As Byte
End Type

private sub loadpic
    Dim dummy As Byte
    Dim px() as Pixel
    
    Open "d:\test.bmp" For Binary As #1

    Get #1, 19, breedt
    Get #1, 23, hoog
    
    ReDim px(breedt, hoog) As pixel
    
    Get #1, 55, dummy
    For y = hoog To 1 Step -1
        For x = 1 To breedt
            Get #1, , px(x, y).G
            Get #1, , px(x, y).R
            Get #1, , px(x, y).B
        Next
    Next
    Close
en sub

dit werkt perfect voor elke groote van de bitmap om in te lezen

dit is wat ik er in c van heb gemaakt
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
unsigned char ** openfile (char filename[255], unsigned int * width, unsigned int * height)
{
    /**************************************************
   * loads file 'filename'                           *
   * return the width in width, the height in height *
   * pixelcount = width * height                     *
   * the pixel is turned into a gray value           *
   * and put in pixel[x][y]               *
   **************************************************/
   FILE *bmpfile;
    unsigned int i;
   unsigned char ** loadpixels;
   unsigned int x, y;

    bmpfile = fopen ( filename, "rb");
   if ( bmpfile ) {
    fseek ( bmpfile, 18, SEEK_SET);
      fread ( width, sizeof ( *width), 1, bmpfile);
        fseek ( bmpfile, 22, SEEK_SET);
      fread ( height, sizeof ( *height), 1, bmpfile);
        loadpixels = new unsigned char * [*width];
      for (i = 0; i < *width; i++)
        loadpixels[i] = new unsigned char[*height];
        fseek ( bmpfile, 54, SEEK_SET);
      for ( y = *height; y > 0; y--){
        for ( x = 0; x < (*width); x++){
            loadpixels[x][y] = (fgetc( bmpfile) + fgetc( bmpfile) + fgetc( bmpfile)) / 3;
            cout << (int)loadpixels[x][y] << " ";
         }
         cout << "\n";
      }
    } else {
    cout << "File error occured.\n";
   }
   return loadpixels;
}

alleen om een of andere rede doet ie t maar bij bepaalde resoluties
bij sommige dan vershuift ie een byte :? k snap er aars van

[ Voor 4% gewijzigd door Super_ik op 27-08-2003 19:12 ]

8<------------------------------------------------------------------------------------
Als ik zo door ga haal ik m'n dood niet. | ik hou van goeie muziek


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:06

.oisyn

Moderator Devschuur®

Demotivational Speaker

even kijken
loadpixels is een unsigned char **, oftewel een array van arrays.

loadpixels[0] wijst naar de eerste array, en loadpixels[1] wijst naar de volgende array. Verder weet je dat array[1] 1 element verder is dan array[0], dus loadpixels[0][0] is de hoek, en loadpixels[0][1] is 1 pixel daarnaast. Oftewel, je moet loadpixels[y][x] doen, en niet loadpixels[x][y]

En bij de allocatie van de array moet je width en height dus ook omdraaien. Houd er trouwens rekening mee dat bmp's bottom-up zijn, terwijl het scherm over het algemeen top-down is

Verder skip je de eerste 18 bytes, maar een bmp kan uit verschillende resoluties bestaan. Ook zijn de scanlines meestal dword aligned, dus altijd veelvouden van 4 lang. Een (8 bits) bmp met een breedte van 10 pixels heeft dus in werkelijkheid een breedte van 12 pixels, waarbij de laatste 2 pixels worden genegeerd

[ Voor 23% gewijzigd door .oisyn op 27-08-2003 19:18 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Super_ik
  • Registratie: Maart 2001
  • Laatst online: 21-08 15:53
maar als ik x,y doe ipv y,x kun je het toch zien als dat elke array[x] een colom vertegenwoordigt
daar licht t probleem volgens mij niet.
de breedte en hoogte worden wel goed uitgelezen, dat hebbik wel gechecked

en hiermee: for ( y = *height; y > 0; y--){ zorg ik ervoor dat t plaatje wordt omgedraait

ik lees alleen 24 bits bitmaps in, k zorg ervoor dat ook alleen 24 bits bitmaps worden aangeleverd.

[ Voor 16% gewijzigd door Super_ik op 27-08-2003 19:23 ]

8<------------------------------------------------------------------------------------
Als ik zo door ga haal ik m'n dood niet. | ik hou van goeie muziek


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Lees het hele ding in 1 keer in en cast het godganse ding naar een BITMAPFILEHEADER aub, alvorens je de rest uitleest volgens deze beschrijving.

* curry684 snurkt gezellig verder totdat de hele wereld MSDN Library Online in z'n Favourites heeft staan :z

Professionele website nodig?


  • Super_ik
  • Registratie: Maart 2001
  • Laatst online: 21-08 15:53
owkay, k zal er is meej gaan puzzele, maar waarom werkt t in vb dan wel en in c niet :?

k gebruik trouwens borland c 5
en t wordt een dosconsole (|:() programma

[ Voor 37% gewijzigd door Super_ik op 27-08-2003 22:48 ]

8<------------------------------------------------------------------------------------
Als ik zo door ga haal ik m'n dood niet. | ik hou van goeie muziek


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Ik mag hopen dat het een console programma wordt en geen DOS-programma.

En het werkt niet in C omdat je moeilijk aan het prutz0ren bent ipv simpelweg de door Microsoft bedachte methode te volgen.

Professionele website nodig?


  • MisterData
  • Registratie: September 2001
  • Laatst online: 21-08 20:35
curry684 schreef op 27 August 2003 @ 19:53:
En het werkt niet in C omdat je moeilijk aan het prutz0ren bent ipv simpelweg de door Microsoft bedachte methode te volgen.
Misschien is Super_Ik wel bezig met een programma dat straks ook op andere systemen dan Windows moet draaien?wake up, er is meer dan alleen Windows ;).

Overigens denk ik ook dat, als je windows wil en gaat gebruiken, het het makkelijste is om gewoon de Windows-functies te gebruiken. Heb je geen gezeik ook met 16bits/24bits/256 kleuren, en ook palletes enzo zijn eenvoudiger te regelen.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

MisterData schreef op 27 augustus 2003 @ 20:02:
Misschien is Super_Ik wel bezig met een programma dat straks ook op andere systemen dan Windows moet draaien?wake up, er is meer dan alleen Windows ;).
Dan moet je geen Windows-native bestandsformaat gebruiken :z
alleen om een of andere rede doet ie t maar bij bepaalde resoluties
bij sommige dan vershuift ie een byte
Zal ik het originele probleem dan ook nog maar even oplossen want anders kom je die dadelijk weer tegen: data in BMP-files is word-aligned. Oftewel je gaat fout bij BMP's met een oneven width :Y)

Professionele website nodig?


  • Super_ik
  • Registratie: Maart 2001
  • Laatst online: 21-08 15:53
da had ik gecompenseerd met if (width % 2) fgetc ( nix);
maar als de width 22 is bijvoorbleed dan moeten er weer 2 x extra worden ge-fgetc
en yup t programma moet ook op linux kunnen draaien


en!!!!! waarom werkt t in vb wel en in c niet?
is vb dan echt zoveel beter :?

[ Voor 18% gewijzigd door Super_ik op 27-08-2003 22:47 ]

8<------------------------------------------------------------------------------------
Als ik zo door ga haal ik m'n dood niet. | ik hou van goeie muziek


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Super_ik schreef op 27 augustus 2003 @ 22:46:
da had ik gecompenseerd met if (width % 2) fgetc ( nix);
Staat niet in je code.
maar als de width 22 is bijvoorbleed dan moeten er weer 2 x extra worden ge-fgetc
Dan is het longword-aligned, pardon ik had het niet opgezocht.
en yup t programma moet ook op linux kunnen draaien
Dan copy/paste je de relevante structs uit de WinGdi.h headers indien de constante WIN32 niet gedefinieerd is.
en!!!!! waarom werkt t in vb wel en in c niet?
Omdat je nog steeds niet de geeigende methode gebruikt.
is vb dan echt zoveel beter :?
Daar gaan we niet op in :z

Professionele website nodig?


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:06

.oisyn

Moderator Devschuur®

Demotivational Speaker

Heb je het in VB wel getest met dezelfde bmp files? Ik betwijfel dat namelijk ten zeerste

Overigens lees je in VB nog 1 dummy byte uit vanaf positie 55 (wat waarschijnlijk 1-based is, dus offset 54). Je begint de pixels dus te lezen vanaf offset 55
In C doe je het echter vanaf offset 54

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Super_ik
  • Registratie: Maart 2001
  • Laatst online: 21-08 15:53
yup ook in vb getest met dezelfde bmp files, en daar werkte t wel :)

hij begint wel op de goeie plek te lezen, dat weet ik zeker :)

t heeft denk ik idd iets te maken met align :? maar hoe :?

[ Voor 29% gewijzigd door Super_ik op 28-08-2003 18:43 ]

8<------------------------------------------------------------------------------------
Als ik zo door ga haal ik m'n dood niet. | ik hou van goeie muziek


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:06

.oisyn

Moderator Devschuur®

Demotivational Speaker

Uhm, dat weet je zeker?

Vergelijk deze code:
Visual Basic:
1
2
3
4
5
6
7
8
    Get #1, 55, dummy
    For y = hoog To 1 Step -1
        For x = 1 To breedt
            Get #1, , px(x, y).G
            Get #1, , px(x, y).R
            Get #1, , px(x, y).B
        Next
    Next


eens met deze:

C++:
1
2
3
4
5
6
7
8
    fseek ( bmpfile, 54, SEEK_SET); 
    for ( y = *height; y > 0; y--){ 
        for ( x = 0; x < (*width); x++){ 
            loadpixels[x][y] = (fgetc( bmpfile) + fgetc( bmpfile) + fgetc( bmpfile)) / 3; 
            cout << (int)loadpixels[x][y] << " "; 
        } 
        cout << "\n"; 
    }


In VB lees je dus eerst een dummy byte uit vanaf positie 55. Aangezien de positie in VB 1-based is, is dat dus offset 54. De volgende read operatie begint op de volgende byte, dus offset 55

In C++ seek je naar offset 54, en begin je daar met lezen. Hoe verklaar je dat verschil?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Super_ik
  • Registratie: Maart 2001
  • Laatst online: 21-08 15:53
omdat visual basic bij 1 begint te tellen en C bij 0;

k heb nu iets gevonden voor t alignen, volgens mij werkt t voor alle even getallen, maar niet voor oneven getallen.

C:
1
2
3
4
5
6
7
8
9
10
    unsigned char align = (4 - ((*width) % 4)) & 3;
      for ( y = *height; y > 0; y--){
        for ( x = 0; x < (*width); x++){
            loadpixels[x][y] = (fgetc( bmpfile) + fgetc( bmpfile) + fgetc( bmpfile)) / 3;
            cout << (int)loadpixels[x][y] << " ";
         }

         for (i = 0; i < align; i++) fgetc ( bmpfile);
         cout << "\n";
      }

help :?

8<------------------------------------------------------------------------------------
Als ik zo door ga haal ik m'n dood niet. | ik hou van goeie muziek


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:06

.oisyn

Moderator Devschuur®

Demotivational Speaker

omdat visual basic bij 1 begint te tellen en C bij 0;
lees mijn post eens!
Als VB ook begon te tellen bij 0 zit je er 2 bytes naast

In VB doe je:
lees: pos 55 -> dummy
lees: pos 56 -> pixel[0][0].g
lees: pos 57 -> pixel[0][1].r
lees: pos 58 -> pixel[0][2].b

(sowieso raar, meestal is het of RGB, of BGR, bmp is dacht ik dat laatste, maar nooit GRB ofzoiets)

In C++ doe je:
seek naar pos 54
lees: pos 54
lees: pos 55
lees: pos 56

Daar zitten toch echt 2 bytes verschil tussen. VB begint idd bij 1, dus je leest de eerste groen dan eigenlijk van offset 55. Maar dus niet 54, zoals je in C++ doet

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Super_ik
  • Registratie: Maart 2001
  • Laatst online: 21-08 15:53
tja, dat van die 54 en 56 vindt ik ook raar :? maar dat werkt wel.
en in vb deed ik idd R => G => B, maarja, t moest toch grijs worden. solly 'bout that.

k heb t maar s ff op een papiertje getekend, k snap t nu
aling berekening:
C:
1
2
3
4
5
if ((*width) % 2) {
        align = ((*width) % 4) & 3;
      } else {
        align = (4 - ((*width) % 4)) & 3;
      }


:)

[ Voor 45% gewijzigd door Super_ik op 28-08-2003 20:33 ]

8<------------------------------------------------------------------------------------
Als ik zo door ga haal ik m'n dood niet. | ik hou van goeie muziek


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 21-08 18:33
Super_ik schreef op 27 August 2003 @ 22:46:
......is vb dan echt zoveel beter :?
*kuchbullshitkuch* ;)

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.

Pagina: 1