Reading bytes from bmp file - c

How do I read the bytes from a bmp file using C?

Here's a general-purpose skeleton to just load a binary file, and return a pointer to the first byte. This boils down to "fopen() followed by fread()", but is a ... bit more verbose. There's no error-handling, although errors are checked for and I believe this code to be correct. This code will reject empty files (which, by definition, don't contain any data to load anyway).
#include <stdio.h>
#include <stdlib.h>
static int file_size(FILE *in, size_t *size)
{
if(fseek(in, 0, SEEK_END) == 0)
{
long len = ftell(in);
if(len > 0)
{
if(fseek(in, 0, SEEK_SET) == 0)
{
*size = (size_t) len;
return 1;
}
}
}
return 0;
}
static void * load_binary(const char *filename, size_t *size)
{
FILE *in;
void *data = NULL;
size_t len;
if((in = fopen(filename, "rb")) != NULL)
{
if(file_size(in, &len))
{
if((data = malloc(len)) != NULL)
{
if(fread(data, 1, len, in) == len)
*size = len;
else
{
free(data);
data = NULL;
}
}
}
fclose(in);
}
return data;
}
int main(int argc, char *argv[])
{
int i;
for(i = 1; argv[i] != NULL; i++)
{
void *image;
size_t size;
if((image = load_binary(argv[i], &size)) != NULL)
{
printf("Loaded BMP from '%s', size is %u bytes\n", argv[i], (unsigned int) size);
free(image);
}
}
}
You can easily add the code to parse the BMP header to this, using links provided in other answers.

Use fopen and fread as suggested by others. For the format of the bmp header take a look here

fopen followed by fread

ImageMagick supports BMP. You can use either of two C APIs, the low-level MagickCore or the more high level Magick Wand.

make sure this file is not compressed using RLE method. otherwise, you'll have to read from the file and dump into a buffer to reconstruct the image, after reading the header file and knowing it's dimensions.

Related

Write bitstream to file in C

I'm currently trying to use a CMP decompressor: https://web.archive.org/web/20070113004119/http://rewiki.regengedanken.de:80/wiki/.CMP
It does in fact decompress the cmp, but it does not write it into a file.
So i tried myself.
int main(int argc, char** argv)
{
int length, dstLength;
unsigned char* fileInMem; //compressed data
unsigned char* dstFile; //decompressed data
if (argc < 2) {
fprintf(stderr, "give filename.cmp as parameter\n");
return 1;
}
printf("%s", argv[1]);
fileInMem = loadFile(argv[1], &length); //compressed data read
if (fileInMem == NULL) {
return 1;
}
dstFile = parseCmp(fileInMem, length, &dstLength); //decompress and assign data to dstFile
if (dstFile) {
/* Now we can save the file from dstFile, dstLength bytes */
printf("%d bytes depacked\n", dstLength);
for (int i = 0; i < 16; i++) {
dataArray[i] = fileInMem[i];
}
FILE *writer = fopen(argv[2], "r+");
//fputs(fileInMem, writer);
//fputs(dstFile, writer);
fclose(writer);
free(dstFile);
}
free(fileInMem);
return 0;
}
As you can see the decompressed data is a pointer to an unsigned char (according to the website a bitstream) and I tried fputs() from stdio.h, but the resulting file contains only 4 Bytes when viewed in a hex-editor.
If you need more information, please comment.
Thank you in advance.
Edit: This is what I was able to change thanks to your help, but when I open the file, it is still empty:
FILE* writer = fopen(argv[2], "wb");
fwrite(dstFile, 192, 192, writer);
192, because the length of the first decompressed Image is 192 Bytes large.
This is a common issue.
First, you need to open the output file writer for writing in binary mode ("wb").
FILE *writer = fopen(argv[2], "wb");
Second, you can't use fputs to write arbitrary data to a file, since it expects a string. Use fwrite instead: (assuming writer is the output file, dstFile the decompressed data and dstLength the amount of bytes to write)
fwrite(dstFile, 1, dstLength, writer);
If you examine the resulting file with an hex editor, you will see it is identical to the decompressed data.
Test-update
I wrote some test-code to see what is wrong, share your results so we can help you.
Add these functions to your code:
void printDataToScreen(unsigned char *dataptr, int datalen)
{
if (dataptr == NULL)
{
printf("[!] ERROR, NULL POINTER PROVIDED!\n");
return;
}
printf("> Dumping %d bytes of data into the terminal...\n", datalen);
for (int i = 0; i < datalen; i++)
{
if (i % 16 == 0)
printf("\n ");
printf("%02X ", dataptr[i]);
}
printf("\n\n");
}
void writeDataToFile(char *fileName, unsigned char *dataptr, int datalen)
{
FILE *file = fopen(fileName, "wb");
if (dataptr == NULL)
{
printf("[!] ERROR, NULL POINTER PROVIDED!\n");
return;
} else if (file == NULL)
{
printf("[!] ERROR WHILE OPENING FILE '%s'!\n", fileName);
return;
}
printf("> Writting %d bytes of data to '%s'...\n", datalen, fileName);
int writtenBytes = fwrite(dataptr, 1, datalen, file);
printf(" Done, %d bytes written!\n\n", writtenBytes);
fclose(file);
}
void runTest(char *fileName, unsigned char *dataptr, int datalen)
{
printf("Running tests... [0/2 done]\n");
printDataToScreen(dataptr, datalen);
printf("Running tests... [1/2 done]\n");
writeDataToFile(fileName, dataptr, datalen);
printf("Finished! [2/2 done]\n");
}
Call it like this:
runTest(argv[2], dstFile, dstLength);
Add the call to this place in your code (comment this code, also the line where you close writer):
FILE *writer = fopen(argv[2], "r+");
//fputs(fileInMem, writer);
//fputs(dstFile, writer);
Please share your results.

How to determine the size of (all the content) a file so I can allocate memory for it at once?

I am trying to allocate memory for the content of a file with words(separated by: \n).
How do I replace the 16000 to make it usable with files of greater size?
My code:
typedef struct node {
bool is_word;
struct node* children[27];
} node;
node* root;
bool load(const char* dictionary)
{
FILE *fp;
fp = fopen(dictionary, "rb");
node* node_bucket = calloc(16000, sizeof(node));
node* next_free_node = node_bucket;
// compute...
// to later free the memory with another function
root = node_bucket;
}
Thanks
You can allocate memory dynamically without knowing how large the file is. I used a block size that is a power of 2, which is generally kinder towards block I/O. It wastes a little when the last block is only partially used, but here is an example, which you could adapt to work with your node structs:
#include <stdio.h>
#include <stdlib.h>
#define BLOCKSIZE 16384
int main(void) {
unsigned char *buf = NULL;
unsigned char *tmp = NULL;
size_t totalread = 0;
size_t currentsize = 0;
size_t currentread = 0;
FILE *fp;
if((fp = fopen("test.txt", "rb")) == NULL)
exit(1);
do {
currentsize += BLOCKSIZE;
if((tmp = realloc(buf, currentsize)) == NULL)
exit(1);
buf = tmp;
currentread = fread( &buf[totalread], 1, BLOCKSIZE, fp);
totalread += currentread;
} while (currentread == BLOCKSIZE);
printf("Total size was %zu\n", totalread);
free(buf);
fclose(fp);
return 0;
}
The simplest approach to get the size of a file is using ftell():
fseek(fp, 0, SEEK_END); // non-portable
long size = ftell(fp);
However, as the comment says, this is not portable, because N1570 documents in "7.21.9.2 The seek function":
2 ...... A binary stream need not meaningfully support fseek calls with a
whence value of SEEK_END.
Alternatively, you can write a function to get the size of a file on your own:
size_t fSize(FILE *fp)
{
void *ptr = malloc(1);
size_t size = 0;
while(fread(ptr, 1, 1, fp) == 1)
size++;
if(feof(fp))
return size;
else
return 0; // reading error
}
An accuracy-efficiency trade-off:
size_t fRoughSize(FILE *fp)
{
void *ptr = malloc(1024);
size_t size = 0;
while(fread(ptr, 1024, 1, fp) == 1024)
size += 1024;
if(feof(fp))
return size;
else
return 0; // reading error
}

How to unpack a msgpack file?

I am writing msgpack-encoded data to a file. On writing, I am just using the fbuffer of the C API. As in (I striped all error handling for the example):
FILE *fp = fopen(filename, "ab");
msgpack_packer pk;
msgpack_packer_init(pk, fp, msgpack_fbuffer_write);
msgpack_pack_int(pk, 42);
// more data ...
How do I read this file back in? All the example I found assume that the data is in memory, however, my files are up to 5GB, it is not exactly a good idea to hold this in memory completely. Also I do not want to read in chunks myself. After all, I do not know how long the msgpack objects are, so chances are I end up with half an integer in my buffer.
Can msgpack's unpack somehow read from disk directly? Or is there some standard pattern to do this?
You might consider using "msgpack_unpacker" for that instead, which seems to be the official way that MessagePack implements a 'streaming' deserializer. Have a look at msgpack-c/example/c/lib_buffer_unpack.c
Regards, NiteHawk
Okay, I managed to do it.
Here is how to write:
#include <stdlib.h>
#include <msgpack.h>
#include <msgpack/fbuffer.h>
int main(int argc, char **argv) {
if(2 != argc) {
fprintf(stderr, "Call all writeFile <file>");
return;
}
FILE *fp = fopen(argv[1], "ab");
msgpack_packer pk;
msgpack_packer_init(&pk, fp, msgpack_fbuffer_write);
for(int i=0;i<2048;i++) {
msgpack_pack_int(&pk, i);
}
fclose(fp);
}
And this is what the read looks like:
#include <stdlib.h>
#include <msgpack.h>
static const int BUFFERSIZE = 2048;
int main(int argc, char **argv) {
if(2 != argc) {
fprintf(stderr, "Call with readFile <file>");
return 1;
}
char *inbuffer = (char *) malloc(BUFFERSIZE);
if(NULL == inbuffer) {
fprintf(stderr, "Out of memory!");
return 1;
}
FILE *fp = fopen(argv[1], "rb");
size_t off = 0;
size_t read = 0;
msgpack_unpacked unpacked;
msgpack_unpacked_init(&unpacked);
do {
read = fread(inbuffer, sizeof(char), BUFFERSIZE - off, fp);
off = 0;
while(msgpack_unpack_next(&unpacked, inbuffer, read, &off)) {
msgpack_object_print(stdout, unpacked.data);
puts("");
}
memcpy(inbuffer, &(inbuffer[off]), read-off);
off = read - off;
} while(read != 0);
free(inbuffer);
fclose(fp);
msgpack_unpacked_destroy(&unpacked);
return 0;
}
I did not try, but I think it will work with larger objects (arrays, maps etc.) as well.

c code text not displayed

iv'e written a part of a code which basically transfers text from a txt file into a variable and prints it(as a part of a program),yet it does not print the contents at all.
#include <stdio.h>
#include <stdlib.h>
#define WRONG_ARGUMENTS (-1)
int Lines(FILE * file);
int Length(FILE * file);
int Read(FILE * file);
int Lines(FILE * file)
{
int c=0,count=0;
++count;
while(c!=EOF)
{
c=fgetc(file);
if(c=='\n')
++count;
}
return count;
}
int Length(FILE * file)
{
int c,count=0;
while((c=fgetc(file))!=EOF)
{
++count;
}
return count;
}
int Reader(FILE * Text,char * File)
{
int counter=0;
while(fscanf(Text,"%s",File)!=EOF)
{
++counter;
strcat(File," ");
}
return counter;
}
int main(int argc,char * argv[]) {
FILE * Text=NULL;
if(argc!=2)
{
printf("usage:library text dictionary\n");
return -1;
}
Text = fopen(argv[1],"r");
if(Text==NULL)
{
printf("file %s could not be opened\n",argv[1]);
return -1;
}
char * File = "";
File=malloc(Length(Text)*(sizeof(char)));
int r = Reader(Text,File);
printf(File);
return 0;
}
i will be more than glad to understand the problem in the partial code
the output is x>
thanks,
Consider the following cut-down example. You'll notice that the getFileLength function (a) doesn't actually read anything from the file and (b) makes use of the fseek and ftell functions - fseek is the function that you use to reposition the file-pointer when it reaches EOF.
Imagine that you weren't printing the data, but doing something else with it. What if the file is a billion bytes long? We sure don't want to read 1,000,000,000 times from it just to determine its length!
As for the use of calloc - it zero initializes the data it allocates. Since you're reading text, you want to ensure that the text is NULL-terminated. (NULL generally = 0, though I've seen evil macros that change this) This NULL terminator is also why I allocate 1 byte more than the file contains.
#include <stdio.h>
#include <stdlib.h>
long getFileLength(FILE *input)
{
long result;
long origPos = ftell(input);
fseek(input, 0, SEEK_END);
result = ftell(input);
fseek(input, origPos, SEEK_SET);
return result;
}
int main (void)
{
FILE *fp;
long fileLen, numBytesRead;
char *data;
fp = fopen("main.cpp", "rb");
fileLen = getFileLength(fp);
data = (char*)calloc(sizeof(char), fileLen+1);
numBytesRead = fread(data, sizeof(char), fileLen, fp);
if (numBytesRead != fileLen)
printf("Error reading all bytes from file. Expected: %d, Read %d\n", fileLen, numBytesRead);
else
printf("%s", data);
free(data);
fclose(fp);
}

How to read the content of a file to a string in C?

What is the simplest way (least error-prone, least lines of code, however you want to interpret it) to open a file in C and read its contents into a string (char*, char[], whatever)?
I tend to just load the entire buffer as a raw memory chunk into memory and do the parsing on my own. That way I have best control over what the standard lib does on multiple platforms.
This is a stub I use for this. you may also want to check the error-codes for fseek, ftell and fread. (omitted for clarity).
char * buffer = 0;
long length;
FILE * f = fopen (filename, "rb");
if (f)
{
fseek (f, 0, SEEK_END);
length = ftell (f);
fseek (f, 0, SEEK_SET);
buffer = malloc (length);
if (buffer)
{
fread (buffer, 1, length, f);
}
fclose (f);
}
if (buffer)
{
// start to process your data / extract strings here...
}
Another, unfortunately highly OS-dependent, solution is memory mapping the file. The benefits generally include performance of the read, and reduced memory use as the applications view and operating systems file cache can actually share the physical memory.
POSIX code would look like this:
int fd = open("filename", O_RDONLY);
int len = lseek(fd, 0, SEEK_END);
void *data = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0);
Windows on the other hand is little more tricky, and unfortunately I don't have a compiler in front of me to test, but the functionality is provided by CreateFileMapping() and MapViewOfFile().
If "read its contents into a string" means that the file does not contain characters with code 0, you can also use getdelim() function, that either accepts a block of memory and reallocates it if necessary, or just allocates the entire buffer for you, and reads the file into it until it encounters a specified delimiter or end of file. Just pass '\0' as the delimiter to read the entire file.
This function is available in the GNU C Library, http://www.gnu.org/software/libc/manual/html_mono/libc.html#index-getdelim-994
The sample code might look as simple as
char* buffer = NULL;
size_t len;
ssize_t bytes_read = getdelim( &buffer, &len, '\0', fp);
if ( bytes_read != -1) {
/* Success, now the entire file is in the buffer */
If you are reading special files like stdin or a pipe, you are not going to be able to use fstat to get the file size beforehand. Also, if you are reading a binary file fgets is going to lose the string size information because of embedded '\0' characters. Best way to read a file then is to use read and realloc:
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int main () {
char buf[4096];
ssize_t n;
char *str = NULL;
size_t len = 0;
while (n = read(STDIN_FILENO, buf, sizeof buf)) {
if (n < 0) {
if (errno == EAGAIN)
continue;
perror("read");
break;
}
str = realloc(str, len + n + 1);
memcpy(str + len, buf, n);
len += n;
str[len] = '\0';
}
printf("%.*s\n", len, str);
return 0;
}
Note: This is a modification of the accepted answer above.
Here's a way to do it, complete with error checking.
I've added a size checker to quit when file was bigger than 1 GiB. I did this because the program puts the whole file into a string which may use too much ram and crash a computer. However, if you don't care about that you could just remove it from the code.
#include <stdio.h>
#include <stdlib.h>
#define FILE_OK 0
#define FILE_NOT_EXIST 1
#define FILE_TOO_LARGE 2
#define FILE_READ_ERROR 3
char * c_read_file(const char * f_name, int * err, size_t * f_size) {
char * buffer;
size_t length;
FILE * f = fopen(f_name, "rb");
size_t read_length;
if (f) {
fseek(f, 0, SEEK_END);
length = ftell(f);
fseek(f, 0, SEEK_SET);
// 1 GiB; best not to load a whole large file in one string
if (length > 1073741824) {
*err = FILE_TOO_LARGE;
return NULL;
}
buffer = (char *)malloc(length + 1);
if (length) {
read_length = fread(buffer, 1, length, f);
if (length != read_length) {
free(buffer);
*err = FILE_READ_ERROR;
return NULL;
}
}
fclose(f);
*err = FILE_OK;
buffer[length] = '\0';
*f_size = length;
}
else {
*err = FILE_NOT_EXIST;
return NULL;
}
return buffer;
}
And to check for errors:
int err;
size_t f_size;
char * f_data;
f_data = c_read_file("test.txt", &err, &f_size);
if (err) {
// process error
}
else {
// process data
free(f_data);
}
What is the simplest way (least error-prone, least lines of code, however you want to interpret it) to open a file in C and read its contents into a string ...?
Sadly, even after years, answers are error prone and many lack proper string formation and error checking.
#include <stdio.h>
#include <stdlib.h>
// Read the file into allocated memory.
// Return NULL on error.
char* readfile(FILE *f) {
// f invalid? fseek() fail?
if (f == NULL || fseek(f, 0, SEEK_END)) {
return NULL;
}
long length = ftell(f);
rewind(f);
// Did ftell() fail? Is the length too long?
if (length == -1 || (unsigned long) length >= SIZE_MAX) {
return NULL;
}
// Convert from long to size_t
size_t ulength = (size_t) length;
char *buffer = malloc(ulength + 1);
// Allocation failed? Read incomplete?
if (buffer == NULL || fread(buffer, 1, ulength, f) != ulength) {
free(buffer);
return NULL;
}
buffer[ulength] = '\0'; // Now buffer points to a string
return buffer;
}
Note that if the text file contains null characters, the allocated data will contain all the file data, yet the string will appear to be short. Better code would also return the length information so the caller can handle that.
char* readfile(FILE *f, size_t *ulength_ptr) {
...
if (ulength_ptr) *ulength_ptr == *ulength;
...
}
If the file is text, and you want to get the text line by line, the easiest way is to use fgets().
char buffer[100];
FILE *fp = fopen("filename", "r"); // do not use "rb"
while (fgets(buffer, sizeof(buffer), fp)) {
... do something
}
fclose(fp);
If you're using glib, then you can use g_file_get_contents;
gchar *contents;
GError *err = NULL;
g_file_get_contents ("foo.txt", &contents, NULL, &err);
g_assert ((contents == NULL && err != NULL) || (contents != NULL && err == NULL));
if (err != NULL)
{
// Report error to user, and free error
g_assert (contents == NULL);
fprintf (stderr, "Unable to read file: %s\n", err->message);
g_error_free (err);
}
else
{
// Use file contents
g_assert (contents != NULL);
}
}
Just modified from the accepted answer above.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
char *readFile(char *filename) {
FILE *f = fopen(filename, "rt");
assert(f);
fseek(f, 0, SEEK_END);
long length = ftell(f);
fseek(f, 0, SEEK_SET);
char *buffer = (char *) malloc(length + 1);
buffer[length] = '\0';
fread(buffer, 1, length, f);
fclose(f);
return buffer;
}
int main() {
char *content = readFile("../hello.txt");
printf("%s", content);
}
// Assumes the file exists and will seg. fault otherwise.
const GLchar *load_shader_source(char *filename) {
FILE *file = fopen(filename, "r"); // open
fseek(file, 0L, SEEK_END); // find the end
size_t size = ftell(file); // get the size in bytes
GLchar *shaderSource = calloc(1, size); // allocate enough bytes
rewind(file); // go back to file beginning
fread(shaderSource, size, sizeof(char), file); // read each char into ourblock
fclose(file); // close the stream
return shaderSource;
}
This is a pretty crude solution because nothing is checked against null.
I will add my own version, based on the answers here, just for reference. My code takes into consideration sizeof(char) and adds a few comments to it.
// Open the file in read mode.
FILE *file = fopen(file_name, "r");
// Check if there was an error.
if (file == NULL) {
fprintf(stderr, "Error: Can't open file '%s'.", file_name);
exit(EXIT_FAILURE);
}
// Get the file length
fseek(file, 0, SEEK_END);
long length = ftell(file);
fseek(file, 0, SEEK_SET);
// Create the string for the file contents.
char *buffer = malloc(sizeof(char) * (length + 1));
buffer[length] = '\0';
// Set the contents of the string.
fread(buffer, sizeof(char), length, file);
// Close the file.
fclose(file);
// Do something with the data.
// ...
// Free the allocated string space.
free(buffer);
easy and neat(assuming contents in the file are less than 10000):
void read_whole_file(char fileName[1000], char buffer[10000])
{
FILE * file = fopen(fileName, "r");
if(file == NULL)
{
puts("File not found");
exit(1);
}
char c;
int idx=0;
while (fscanf(file , "%c" ,&c) == 1)
{
buffer[idx] = c;
idx++;
}
buffer[idx] = 0;
}

Resources