c - how read binary files?

i'm trying read a binary file, but i'm getting problems :(
a binary files is contitued with bytes(ascci characters). and the 1st position is the position 0(zero).
i'm trying read just some values from ICO file:
- the 3rd value is in 4th-1 position(number of icons);
(please see the table: https://www.daubnet.com/en/file-format-ico )
- the with is the (numberoficons*16) + 4 (the 16 is the Entries structure size) position;
- the height is the (numberoficons*16) + 4 + 4 (the 16 is the Entries structure size) position.

now see the code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int iconwidth;
            int iconheight;
            int iconcount;

            FILE *iconfile = fopen(filename.c_str(), "rb");//open the file
            fseek(iconfile,4-1,SEEK_SET); //put the file in position 6(the position starts from 0)

            fread(&iconcount,sizeof(char),2,iconfile);//get 2 blocks with char size(2 bytes).. i'm getting the number of icons

            fseek(iconfile,(iconcount*16)+4,SEEK_SET);//the Entries struture have 16 bytes
            //so i need multiply by the number of icons for get the next structure

            fread(&iconwidth,sizeof(char),4,iconfile);//getting the icon width

            fseek(iconfile,(iconcount*16)+4+4,SEEK_SET);//put the height position

            fread(&iconheight,sizeof(char),4,iconfile);//getting the icon height

            fclose(iconfile);//close the file 

so what i'm doing wrong with block positions?
finally i correct the positions, but i continue confused :(
1
2
3
4
5
6
7
8
9
10
11
12
13
char iconwidth;
            char iconheight;
            char iconcount;

            FILE *iconfile = fopen(filename.c_str(), "rb");//open the file
            fseek(iconfile,4,SEEK_SET);
            fread(&iconcount, 1, 2, iconfile);//get 2 blocks with char size bytes).. i'm getting the number of icons
            fseek(iconfile,6+(iconcount*16)+4,SEEK_SET);
            fread(&iconwidth, 1, 4, iconfile);

            //fseek(iconfile,6+(iconcount*16)+4+4,SEEK_SET);
            //fread(&iconheight, 1, 4, iconfile);
            fclose(iconfile);//close the file 

i recive the iconwidth correctly, but if i uncomment that 2 lines, i recive 0(zero) in iconwidth, but the iconheight value is corrected. why? is these a memory leak?
You are corrupting memory. 'iconcount' is only 1 byte wide, yet you are trying to read 2 bytes into it. This means the low byte will be read properly, but the high byte will spill into other memory doing very bad things.

You are also attempting to read 4 bytes into 'iconwidth', which is only 1 byte wide. So you have 3 bytes of spillage there as well.


With the file format, this is very simple. If you are only interested in the width/height of one of the icons:

1
2
3
4
5
6
7
8
9
10
11
uint8_t width, height;                      // explicit 8-bit sized vars (1 byte each).

FILE* file = fopen( filename, "rb" );       // open the file

fseek(file, 6, SEEK_SET);                   // skip first 6 bytes to get to the width/height of the first icon
                                            //   note we don't care about the iconcount because we're only taking
                                            //   the first icon's size
fread(&width,1,1,file);                     // read 1-byte width
fread(&height,1,1,file);                    // read 1-byte height

fclose(file);                               // close 



If you want to enumerate all the icons in the file:

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
struct IconDims
{
    uint8_t w;
    uint8_t h;
};
std::vector<IconDims>   icondims;


FILE* file = fopen( filename, "rb" );

uint16_t count;                             // 16-bit var (2 bytes wide)
fseek(file, 4, SEEK_SET);                   // skip to the icon count
fread(&count, 1, 2, file);                  // read the count


icondims.resize(count);                     // size our vector
for(int i = 0; i < count; ++i)              // loop to read dims of all icons
{
    fread(&icondims[i].w, 1, 1, file);      // read width
    fread(&icondims[i].h, 1, 1, file);      // and height
    
    fseek(file, 14, SEEK_CUR);              // skip 14 bytes to next icon's entry
}

fclose(file);
Last edited on
thanks for correct me.
but the values aren't correct :(
the icon is only drawed half of it :(
why?

anotherthing: so these table isn't correct: https://www.daubnet.com/en/file-format-ico
but the values aren't correct :(
the icon is only drawed half of it :(
why?


Beats me. It'll take some debugging.

Can you upload a copy of the icon you're using so I can try it out? Like to dropbox?

anotherthing: so these table isn't correct: https://www.daubnet.com/en/file-format-ico


It probably is correct. It's more likely that you're making some other mistake.

Always assume the problem is with your code unless you have very good reason to think otherwise.
heres the icon: https://onedrive.live.com/?cid=C3EF456E15C8DEB6&id=C3EF456E15C8DEB6!1261&v=3

and heres the code:
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
uint8_t width, height;                      // explicit 8-bit sized vars (1 byte each).

            FILE* file = fopen( filename.c_str(), "rb" );       // open the file

            fseek(file, 6, SEEK_SET);                   // skip first 6 bytes to get to the width/height of the first icon
                                            //   note we don't care about the iconcount because we're only taking
                                            //   the first icon's size
            fread(&width,1,1,file);                     // read 1-byte width
            fread(&height,1,1,file);                    // read 1-byte height

            fclose(file);                               // close


            imageweight=width;
            imageheight=height;

            HICON hicon =  (HICON)LoadImage(NULL, filename.c_str(), IMAGE_ICON, imageweight, imageheight, LR_LOADFROMFILE|LR_SHARED|LR_DEFAULTSIZE);
            hdcimage = CreateCompatibleDC(NULL);


            //create the bitmap image with icon size
            //and draw it to hdcimage
            HBITMAP hbitmap=CreateBitmap(imageweight,imageheight,1,32,NULL);
            SelectObject(hdcimage, hbitmap);
            DrawIcon(hdcimage,0,0,hicon);

and in form paint:
TransparentBlt(hdcWindow, 0, 0,m.width(), m.height(),m, 0, 0,m.width(), m.height(), GetPixel(m,0,0));
'm' is the class image instance. the DC is correct, because i'm see the icon. but not in right size.
see these print screen: https://onedrive.live.com/?cid=C3EF456E15C8DEB6&id=C3EF456E15C8DEB6!1262&v=3
Last edited on
I had to login to MSN to download that. Fortunately I had an account so it wasn't a problem... but in the future I suggest you use a site that doesn't require the person to login... since they might not be able to.

Dropbox is a good alternative.


Anyway I'll take a look. Gimmie a few mins.
sorry. but i put it in public folder. i thot that i was avoiding that problem. but thanks for tell me that
So I gave up trying to figure out DrawIcon and just wrote my own:

https://www.dropbox.com/s/2ffqhw7adg0mhi5/IconLoader.zip?dl=0


No need to load it into a DC and transparentblt... it already does that.

You can look at the header for more details

Example usage:

1
2
3
4
5
6
7
8
9
10
ImageGroup ig("whatever.ico");

int number_of_icons = ig.size();

// to get the size of the first icon:
int width = ig[0].width();
int height = ig[0].height();

// to draw the first icon to your screen at coord 10,10
ig[0].draw(screendc, 10, 10);



I did not extensively test, but it worked with the icon you uploaded and a few others I tried.
Last edited on
thanks VB knowledge ;)
http://stackoverflow.com/questions/1913468/how-to-determine-the-size-of-an-icon-from-a-hicon
heres my code:
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
//create the icon handle
            HICON hIcon =  (HICON)LoadImage(NULL, filename.c_str(), IMAGE_ICON, imageweight, imageheight, LR_LOADFROMFILE|LR_SHARED|LR_DEFAULTSIZE);
            
            ICONINFO IconInf;
            BITMAP BMInf;
            
            //get the icon size
            if (GetIconInfo(hIcon, &IconInf)!=NULL)
            {
                if (IconInf.hbmColor!=NULL)
                {
                    if (GetObject(IconInf.hbmColor, sizeof(BMInf), &BMInf))
                    {
                        imageweight = BMInf.bmWidth;
                        imageheight = BMInf.bmHeight;
                        //BitDepth = BMInf.bmBitsPixel;
                    }
                    DeleteObject(IconInf.hbmColor);
                }
                else if (GetObject(IconInf.hbmMask, sizeof(BMInf),&BMInf)!=NULL)
                {
                    imageweight = BMInf.bmWidth;
                    imageheight = BMInf.bmHeight % 2;
                    //BitDepth = 1;
                }
                DeleteObject(IconInf.hbmMask);
            }
            
            HBITMAP hbitmap=CreateBitmap(imageweight,imageheight,1,32,NULL);//create the bitmap with icon size
            hdcimage = CreateCompatibleDC(NULL);//create a memory DC
            SelectObject(hdcimage, hbitmap);//add the bitmap to memory DC
            DrawIcon(hdcimage,0,0,hIcon);//draw the icon to DC
        }

thanks for all
but true.. i always recive the 32X32 size lol
let me ask 1 thing: the DC\window is configured for 1 icon size(it can be changed) or only for the original size?
finally i put it to work like i need.. the problem was the DrawIcon() function:
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
//create the transparent icon handle
            HICON hicon =  (HICON)LoadImage(NULL, filename.c_str(), IMAGE_ICON, imageweight, imageheight, LR_LOADFROMFILE|LR_SHARED|LR_DEFAULTSIZE|LR_LOADTRANSPARENT);

            //open the file for read the icon size
            FILE *file=fopen(filename.c_str(),"rb");

            //getting the icon size
            char width,height;
            fseek(file, 6, SEEK_SET);
            fread(&width,1,1,file);
            fread(&height,1,1,file);

            //close the file
            fclose(file);

            //save the icon size
            imageweight=width;
            imageheight=height;


            HBITMAP hbitmap=CreateBitmap(imageweight,imageheight,1,32,NULL);//create the bitmap with icon size
            hdcimage = CreateCompatibleDC(NULL);//create a memory DC
            SelectObject(hdcimage, hbitmap);//add the bitmap to memory DC
            DrawIconEx(hdcimage,0,0,hicon,imageweight,imageheight,0,0,DI_NORMAL);//draw the icon to DC with right size
            //seems the DrawIcon(), always, draw it with 32X32 size 

now the icon is showed transparent too ;)
Topic archived. No new replies allowed.