![]() |
|
#31
|
|||
|
|||
Re: How to get the pixels' value of a bmp image? (Pelles C)Quote:
Really Thank you a lot!!! Regards |
|||
|
#32
|
|||
|
|||
Re: How to get the pixels' value of a bmp image? (Pelles C)Quote:
Regards, Dave |
|
#33
|
|||
|
|||
Re: How to get the pixels' value of a bmp image? (Pelles C)I hadn't been checking in over here at C++ due to self-imposed fun-time limits.
The email notifications promted me to take a look. I had forgotten about the post I made earlier! (it's getting worse...) I see how the fopen(x.x, "rb"); is all important. But not in linux? When I saw that 0x1a is ctrl-z in MS I was rememberred that there was the ctrl-d (0x04) in linux which was similar. I don't know, thought I'd ask. On reviewing the pages, way back on page 1 a point was made about pixel data width, which is what we're getting in iheader.width, and the need to take into account that byte padding may be applied if the total pixel bytes do not add up to be a multiple of 4. I was curious about it and so made this exercise program to look into it and I wondered if I was getting the concept right: CPP / C++ / C Code:
Code:
In the posting above by Dave an absolute check on the width is made: CPP / C++ / C Code:
And there is never a eol marker for BMP's ? I think I'll try the grayscale exercise next (in the "spare time"). Thanks Howard(); |
|
#34
|
||||
|
||||
Re: How to get the pixels' value of a bmp image? (Pelles C)Quote:
For Windows/cywgin users: The default at installation time is the Linux model, but it is possible to tell the cygwin installer to use "Windows" conventions in the I/O libraries so that 0x1a might be the end-of-file (I haven't checked), and the two-byte sequence '\r','\n' in a file is converted to a single '\n' in the stream buffer. I have tested this. (For writing in "windows" mode, '\n' in the stream buffer is converted to '\r',\n' in the file.) For Windows Borland compilers that I have tested, they don't do anything special with 0x1a, but they convert '\r','\n' in a file to '\n' in the stream buffer unless the file was opened in binary mode. Quote:
That ctrl-d thingie is for stdin input only. Bytes with value 0x04 in files do nothing special in the libraries supplied with GNU compilers, regardless of the 'b' in the mode. Quote:
iheader.width gives the number of pixels per row, not the number of bytes per row. Padding bytes are supplied if necessary to force the total number of bytes on a row to be a multiple of 4. Roughly speaking, the number of bytes on a row is equal to the number of bytes per pixel times the number of pixels on a row. Bytes per pixel is equal to bits per pixel divided by 8. I have encountered the following types of bmp files: For info_header.bits = 24 (millions of colors), there are three bytes per pixel For info_header.bits = 8, (256 colors) there is one byte per pixel For info_header.bits = 4, (16 colors) there are two pixels per byte For info_header.bits = 2, (four colors) there are four pixels per byte For info_header.bits = 1, (two colors) there are eight pixels per byte For bmp files with fewer than 256 colors, the number of pixel bytes on a row can be calculated from CPP / C++ / C Code:
Where width is info_header.width, and bitsperpixel = info_header.bits The value of integer ibyteswidth is equal to the number of bytes on each row that contain pixel data, and it is used to determine the number of extra bytes for each row as follows: The number of extra bytes is either 0, 1, 2 or 3 (that's obvious, isn't it?), depending on the number of bytes per row, so using the modulus operator, '%', we can do something like this: Code:
So, you can use a series if if-else statements using ibyteswidth%4. Or, you can use a switch statement using ibyteswidth%4. Or you can use the easily verified mathematical expression. (It's easy to verify; how "easy" it was to come up with it is another question.) CPP / C++ / C Code:
There are, of course, other ways. Quote:
Generally speaking binary files don't have "lines"; they have bytes.) In text files, structured as sequences of "lines," end-of-line markers are implementation dependent. However for text files, since the lines are not necessarily all of the same length, and since the "real" data bytes are typically ASCII, end-of-line markers are required to allow you to separate the lines as you read the file. The historical convention for UNIX systems text files, carried over into Linux, is 0x0a, and this is identified in C by '\n'. The historical convention for DOS/Windows systems is that end-of-line in a text file is designated by the two-byte sequence 0x0d 0x0a. The historical convention for text files on (old) Macintosh operating systems is 0x0d. Newer operating systems for the Macintosh use the UNIX convention. For reading files, the libraries supplied by compiler vendors usually convert file end-of-line conventions to a single '\n' in the stream buffer unless the input file was opened in binary mode. For writing files, the inverse operations are applied unless the output file was opened in binary mode. Regards, Dave |
|
#35
|
|||
|
|||
Re: How to get the pixels' value of a bmp image? (Pelles C)In this:
CPP / C++ / C Code:
That is, what is the difference between 0 and 1? |
|
#36
|
|||
|
|||
Re: How to get the pixels' value of a bmp image? (Pelles C)Quote:
Inputs to logical expressions are the same for the C preprocessor as they are for C: A value of zero evaluates false. A value of non-zero evaluates true. With #if 0, as shown, the preprocessor will not pass the #include <stdint.h> to the compiler, but will make the typedefs following the #else. The problem is that not all compilers have the assumed sizes for the various data types. (Recent Microsoft and Borland compilers that I use do have the assumed sizes, but older ones may have 16-bit ints, for example.) Note that the main() function that I gave actually tests the header sizes. The test will fail if the compiler doesn't have the assumed sizes for ints. If people know that they have the C99 standard header <stdint.h> in their distribution, they could change the #if 0 to #if 1 and then would be absolutely certain that the correct sizes are used. Regards, Dave |
|
#37
|
|||
|
|||
Re: How to get the pixels' value of a bmp image? (Pelles C)re: #if 0
Boy, that really seems like a dumb question now... sorry. I think I have something half presentable which reads a 24 bit color .bmp file of ?any? size, manipulates that information , and writes 2 slightly different files in grayscale. I made a lot of sidetrips in the exploration... fun stuff. CPP / C++ / C Code:
There are a couple of curiosities I have commented. Other than that I understand things better now and am getting the hang of it. What's next direction? ++Howard; |
|
#38
|
|||
|
|||
Re: How to get the pixels' value of a bmp image? (Pelles C)Quote:
CPP / C++ / C Code:
Why not make r, g, b unsigned ints? Then you have to watch for getc(). Its return value is int. So, maybe you could use something like CPP / C++ / C Code:
Also, by the way, if you ever want to do something with colors (like decrease red and increase blue) you should be aware that the triads come in order green, blue, red (Not red, blue, green.) Actually, I made them doubles so that I could conveniently round the value: CPP / C++ / C Code:
That leaves one question. I have to ask you what the heck happened to the extra bytes? The extra bytes do not go into your pixel data (but you have to re-insert them into the output file somehow). This may be why you had problems with having to allocate more than the data size of the file. As you go through the loop the last time, you are actually accessing beyond the array, I think. Any time your program fails and you have to put in a fudge factor (the extra calloc stuff): beware! Just coming up with some kind of kludge that makes it not fail for a particular data set without actually knowing what the heck is going on is a recipe for disaster. Here's an idea: Leave your loop the way it is, and put in a print statement whenever the index value goes beyond the end of what the array should be. I'll bet it shows you something. Why not do it a row at a time? Use your knowledge of the structure of the bitmap format. You can use a 1-D or 2-D array for the (width *3 times height) pixel data bytes. (Actually if you are going to convert to gray, why not just have a (width times height) array and store gray-value bytes only?) I think that the convenience of 2_D array notation to be able to locate a particular pixel by row and column number is the "only way to go." Conceivably if file I/O is a bottleneck, then reading the whole enchilada with a single fread statement (rather than the cumbersome byte-at-a-time or three-bytes-at a time or even a row-at-a-time) might be important. It's your call Anyhow, for a 2-D array, you could do something like CPP / C++ / C Code:
You can use getc() for each byte, or you can read three at a time (with fread) into a 3-char array or whatever... There is some loss of resolution in going from a 24-bit grayscale to an 8-bit grayscale, but for many purposes it's irrelevant. If you want to keep full precision, then make grayarray[][] an array of ints instead of an array of unsigned chars, and don't divide the r+g+b value by three. (Notice that your routine converted to the equivalent of an 8-bit grayscale; it just used three equal bytes to represent the gray tone.) Regards, Dave |
|
#39
|
|||
|
|||
Re: How to get the pixels' value of a bmp image? (Pelles C)Quote:
What was happening was that: - The i < imagesize was being checked at the beginning of each loop. - i and j could increment up to 3 past 'imagesize' within the loop without being checked. As a result, the program would overflow pdat_in or pdat_out. I tried .bmp file widths from the 458x457 which showed up originally to 500x457 and found only 1 more (474x457) which would segfault although, with the printf()'s in the loop, I could see that on some tests j was incrementing 2 or 3 beyond the array size with no segfault. 458 and 474 were both 1 beyond the loop size. I think the reason it SOMETIMES segfaults and NOT always is that something like this happens: calloc requests x amount of memory. The OS rounds that size up to an even 'block' that it likes to work with which is deemed "in-bounds". If the in-bounds block limit happens to be very close to the requested size, the program writes past THAT limit and the OS issues a segfault... (I have run a char pointer through some data declaration areas of memory before and noticed these 'blocks' the OS rounds to.) So as a cheap fix for the code I posted, I just stuck a bunch of checks within the loop after each increment: CPP / C++ / C Code:
Next I'll be trying to implement some of those good suggestions you made. Thanks! Last edited by Howard_L : 11-Nov-2007 at 19:23.
|
|
#40
|
|||
|
|||
Re: How to get the pixels' value of a bmp image? (Pelles C)Hi all. This was the very best thread I found that helped me create my own bmp loading code. However I do have one question which I will try to explain after I post all my code.
this is a V5 bmp header file CPP / C++ / C Code:
this is a little bmp class I made CPP / C++ / C Code:
here is the cpp of the above class CPP / C++ / C Code:
and here is the main cpp CPP / C++ / C Code:
The Print out i get is this : Size of FileHeader is : 14 Size of InfoHeader is :124 Bmp File Type is : 4d42 Bmp Size is : 263222(this is exactly the same as windows tell me so it's OK) Bmp Reserved one is : 0 Bmp Reserved two is : 0 Bmp Header Offset is 134(this should be 138 I think) Bmp Header FileSize is : 40(and this 124) Image Width is : 512 Image Height is : 512 (both correct) Image Bpp is : 8(correct since I am using 8bit grayscale) Image Compression is : 0 Bytes in Pixel data section are : 262144 File Pointer at the beginning of storing to the 2Darray is : 138(should be correct) File Pointer at the end of storing to the 2Darray is : 262282 Total number of bytes read is : 262144(should also be correct) My questions are these : Firstly it seems that I am missing some 940 bytes since my file size is 263222 and the pointer stops to 262282. Has anyone got any idea as to where those bytes are or what they are used for? Why is the offset 134 and not 138? 14+124 for (V5) should make 138 right? Last edited by admin : 07-Mar-2009 at 20:10.
Reason: Please insert your example C/C++ codes between [CPP] and [/CPP] tags
|
Recent GIDBlog
Accepted for Ph.D. program by crystalattice
| Thread Tools | Search this Thread |
| Rate This Thread | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Question about locking surfaces to directly access pixels, SDL. | george89 | C++ Forum | 0 | 18-Jun-2006 22:16 |
| Pixels | dan_ielle20 | C++ Forum | 0 | 23-Mar-2005 09:54 |
| Checking source codes of image, audio and video files | onauc | C Programming Language | 5 | 26-Feb-2005 22:47 |
Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The