Reading from the header of a bmp file - c

I am writing a program to read a bmp header. I've written some code that was working when it was all in main. How to implement this code as a function of its own and then implementing it onto main?
Here is the whole code :
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdin.h>
struct bmp_header {
uint16_t type;
uint32_t size;
uint16_t reserved1;
uint16_t reserved2;
uint32_t offset;
uint32_t dib_size;
uint32_t width;
uint32_t height;
uint16_t planes;
uint16_t bpp;
uint32_t compression;
uint32_t image_size;
uint32_t x_ppm;
uint32_t y_ppm;
uint32_t num_colors;
uint32_t important_colors;
};
void read_bmp(FILE *BMPFile,struct bmp_header* Header) {
fread(&(Header->type), 2, 1, BMPFile);
fread(&(Header->size),4,1,BMPFile);
fread(&(Header->reserved1),2,1,BMPFile);
fread(&(Header->reserverd2),2,1,BMPFile);
fread(&(Header->offset),4,1,BMPFile);
fread(&(Header->dib_size),4,1,BMPFile);
fread(&(Header->width),4,1,BMPFile);
fread(&(Header->height),4,1,BMPFile);
fread(&(Header->planes),2,1,BMPFile);
fread(&(Header->bpp),2,1,BMPFile);
fread(&(Header->compression),4,1,BMPFile);
fread(&(Header->image_size),4,1,BMPFile);
fread(&(Header->x_ppm),4,1,BMPFile);
fread(&(Header->y_pp),4,1,BMPFile);
fread(&(Header->num_colors),4,1,BMPFile);
fread(&(Header->important_colors),4,1,BMPFile);
}
int main() {
FILE *BMPFile = fopen("image.bmp","rb");
if(BMPFile == NULL)
{
return;
}
struct bmp_header* Header;
read_bmp(BMPFile,Header);
fclose(BMPFile);
return 0;
}
The relevant parts of the version of the program with all reading action in main, that worked as expected, is reported below
int main( void )
{
FILE *BMPFile = fopen ("lenna.bmp", "rb");
if (BMPFile == NULL)
{
return 0;
}
struct bmp_header Header;
memset(&Header, 0, sizeof(Header));
fread(&Header.type, 2, 1, BMPFile);
fread(&Header.size),4,1,BMPFile);
fread(&Header.reserved1),2,1,BMPFile);
fread(&Header.reserverd2),2,1,BMPFile);
fread(&Header.offset),4,1,BMPFile);
fread(&Header.dib_size),4,1,BMPFile);
fread(&Header.width),4,1,BMPFile);
fread(&Header.height),4,1,BMPFile);
fread(&Header.planes),2,1,BMPFile);
fread(&Header.bpp),2,1,BMPFile);
fread(&Header.compression),4,1,BMPFile);
fread(&Header.image_size),4,1,BMPFile);
fread(&Header.x_ppm),4,1,BMPFile);
fread(&Header.y_pp),4,1,BMPFile);
fread(&Header.num_colors),4,1,BMPFile);
fread(&Header.important_colors),4,1,BMPFile);
/* Header fields print section */
/* ... */
}

Whenever a working code stops working, it is useful to focus on the changes between the two versions of the code. So, why does your original code work correctly? It looks like this:
int main( void )
{
FILE *BMPFile = fopen ("lenna.bmp", "rb");
if (BMPFile == NULL)
{
return 0;
}
struct bmp_header Header;
memset(&Header, 0, sizeof(Header));
fread(&Header.type, 2, 1, BMPFile);
...
}
You declare Header, of type struct bmp_header, in main's stack (as local variable). In this way the structure will be for sure allocated during all program's lifetime.
You memset it to 0
You pass Header's fields addresses directly to fread
In the new version of the program you have a function defined as
void read_bmp(FILE *BMPFile,struct bmp_header* Header);
so you need a pointer to struct bmp_header to be passed to it. For this reason you declare
struct bmp_header* Header;
and call read_bmp(BMPFile,Header);.
What is the different with the working version? Well, the pointer! Declaring a pointer you say to the compiler that it contains an address, in this case the address of the structure required by read_bmp().
But you never say to the compiler what the address is, so that freads within read_bmp() will write to random location causing a segmentation fault.
What to do
You need to pass to read_bmp() a valid struct bmp_header address, and you have two options.
You can allocate Header in the stack like you did before, and pass its address to read_bmp(), through & operator. It should have been your first attempt, since it was really similar to your working solution.
struct bmp_header Header;
read_bmp(BMPFile, &Header);
You can declare Header as a pointer, but you will need to dynamically allocate its memory through malloc:
struct bmp_header * Header = malloc(sizeof(struct bmp_header));
read_bmp(BMPFile, Header);

You have to create struct bmp_header* type function. Next create struct bmp_header pointer in your function & allocate memory (header size == 54B) for returned reference.

Related

Reallocating Structure? Copy paste structure

Hello my task is to copy full structure into a new one, and allocate structure memory.
I want to copy one structure into another and also I want to copy the memory of it. So if I "free" the first structure, then I will have this information in the memory located.
struct bmp_image* flip_vertically(const struct bmp_image* image) {
struct bmp_image* bmp = NULL;
bmp = (struct bmp_image*)realloc(bmp, sizeof(struct bmp_image));
memcpy(bmp, image, sizeof(struct bmp_image));
return bmp;
}
What can be the problem?
For example:
If I know that the
image->data[5].blue is 255 and I want to copy it but I need also to save that information into the memory
Main task is to flip the bmp picture. Everything is working perfect for me, but if I put this source code for test that writes that:
Running suite(s): flip_horizontally()
stderr
double free or corruption (!prev)
that means the test is somewhere free-ing the old structure so I don't have this information in the new one
struct bmp_header{
uint16_t type; // "BM" (0x42, 0x4D)
uint32_t size; // file size
uint16_t reserved1; // not used (0)
uint16_t reserved2; // not used (0)
uint32_t offset; // offset to image data (54B)
uint32_t dib_size; // DIB header size (40B)
uint32_t width; // width in pixels
uint32_t height; // height in pixels
uint16_t planes; // 1
uint16_t bpp; // bits per pixel (1/4/8/24)
uint32_t compression; // compression type (0/1/2) 0
uint32_t image_size; // size of picture in bytes, 0
uint32_t x_ppm; // X Pixels per meter (0)
uint32_t y_ppm; // X Pixels per meter (0)
uint32_t num_colors; // number of colors (0)
uint32_t important_colors; // important colors (0)
} __attribute__((__packed__));
/**
* This structure describes a color consisting of relative intensities of
* red, green, and blue.
*/
struct pixel {
uint8_t blue;
uint8_t green;
uint8_t red;
//uint8_t alpha;
} __attribute__((__packed__));
/**
* Structure describes the BMP file format, which consists from two parts:
* 1. the header (metadata)
* 2. the data (pixels)
*/
struct bmp_image {
struct bmp_header* header;
struct pixel* data; // nr. of pixels is `width` * `height`
};
Main.c
int main () {
struct bmp_image* image = NULL;
FILE *stream = fopen("assets/saboteur.bmp", "r");
image = read_bmp(stream);
FILE *output_p1 = fopen("square2.bmp", "w");
struct bmp_image* newimage1 = NULL;
newimage1 = flip_vertically(image);
free_bmp_image(image);
write_bmp(output_p1, newimage1);
free(newimage1);
fclose(output_p1);
fclose(stream);
return 0;
}
If I free the image (the old structure) it shows for me a lot of errors, and I can't write it to the file. That means for me that it wants to read from the old structure.
memcpy does a "shallow" copy and not a "deep" copy. A shallow copy will copy only the pointer values in the struct bmp_image and not the memory it points to. To do a deep copy, the individual fields need to be allocated and copied. Here is some illustrative code. Error checking has been left out for brevity but for final code all allocation results should be checked.
struct bmp_image* flip_vertically(const struct bmp_image* image) {
bmp = malloc(sizeof(*bmp));
bmp->header = malloc(sizeof(*(bmp->header)));
*bmp->header = *(image->header);
size_t pixel_data_size =
sizeof(*(bmp->data)) * bmp->header->width * bmp->header->height;
bmp->data = malloc(pixel_data_size);
memcpy(bmp->data, image->data, pixel_data_size);
return bmp;
}

Porting generic C driver with function pointer

I am trying to port a generic C driver available for a IMU to my embedded platform based on a nordic module. the most optimal way would be to correctly modify the interface functions to adapt it to my system. So the driver available on github here, has this interface for write/read register:
typedef int32_t (*lsm6dso_write_ptr)(void *, uint8_t, uint8_t*, uint16_t);
typedef int32_t (*lsm6dso_read_ptr) (void *, uint8_t, uint8_t*, uint16_t);
typedef struct {
/** Component mandatory fields **/
lsm6dso_write_ptr write_reg;
lsm6dso_read_ptr read_reg;
/** Customizable optional pointer **/
void *handle;
} lsm6dso_ctx_t;
My read/write register functions are:
void write_i2c_data(nrf_drv_twi_t const *m_twi, uint8_t reg, uint8_t val)
{
uint8_t cmd[2] = {0, 0};
cmd[0] = reg;
cmd[1] = val;
nrf_drv_twi_tx(m_twi, ADDR, cmd, 2, true);
nrf_delay_ms(1);
}
void read_i2c_data(nrf_drv_twi_t const *m_twi, uint8_t reg, uint8_t *val)
{
nrf_drv_twi_tx(m_twi, ADDR, &reg, 1, true);
nrf_delay_ms(1);
nrf_drv_twi_rx(m_twi, ADDR, val, 1);
nrf_delay_ms(1);
}
Questions -
1 - I am not sure how to pass along the m_twi driver instance function along to the lsm6dso_ctx_t struct. It says the struct is customizable, but I am not sure how to augment it.
2 - The function pointer kind of got me too - how can I point my function to the lsm6dso_write_ptr pointer. I know will need to modify my function to provide for multiple byte read/write, which I think is doable.
You should implement two functions:
static int32_t your_callback_lsm6dso_read_reg(void *ctx, uint8_t reg, uint8_t* data,
uint16_t len) {
// read from register ret
// len length of data to data pointer
// return 0 on success
// something like: (I have no idea about nrf_* interface)
nrf_drv_twi_t const *m_twi = ctx;
nrf_drv_twi_rx(m_twi, reg, data, len);
return 0;
}
static int32_t your_callback_lsm6dso_write_reg(void *ctx, uint8_t reg, uint8_t* data,
uint16_t len)
// write to register ret len length od data from data pointer
// return 0 on success
// something like: (I have no idea about nrf* interface)
nrf_drv_twi_t const *m_twi = ctx;
nrf_drv_twi_tx(m_twi, reg, data, len);
return 0;
}
Then instantiate the structure:
lsm6dso_ctx_t lsm6dso_ctx = { your_callback_lsm6dso_write_reg, your_callback_lsm6dso_read_reg, m_twi };
and use it like:
lsm6dso_some_function_from_the_library(&lsm6dso_ctx, ...)
The function from the library will call the function pointers from lsm6dso_ctx with the first argument as the void* pointer from the structure. The void* pointer from the structure is used to pass your custom data along. You can then cast the handle from void* pointer into a custom pointer and call the appropriate functions.
how can I point my function to the lsm6dso_write_ptr pointer.
I think your confusion comes from it, that's it's the other way round. The function pointers inside lsm6dso_ctx_t should point to your functions.
Then you have just an instance of lsm6dso_ctx_t structure you use with all functions from the driver. The driver has some logic and it calls your functions as passed with the structure to do input/output operations.

Adding flash before erasing and writing into flash

In a program to erase and write into flash, I donot understand the lines
struct kinetis_flash *kf = calloc(1, sizeof(*kf));
struct target_flash *f = &kf->f;
from the below section of the code. And the whole program can be found at https://github.com/blacksphere/blackmagic/blob/master/src/target/kinetis.c
struct kinetis_flash {
struct target_flash f;
uint8_t write_len;
};
static void kl_gen_add_flash(target *t, uint32_t addr, size_t length,
size_t erasesize, size_t write_len)
{
struct kinetis_flash *kf = calloc(1, sizeof(*kf));
struct target_flash *f = &kf->f;
f->start = addr;
f->length = length;
f->blocksize = erasesize;
f->erase = kl_gen_flash_erase;
f->write = kl_gen_flash_write;
f->done = kl_gen_flash_done;
f->erased = 0xff;
kf->write_len = write_len;
target_add_flash(t, f);
}
It would be great if someone helps me understanding above tw lines, thanks in advance.Many targets for example KL25, K22, K64 can be accordingly used what i understood from the project. Are those two lines storing target specific specifications for flash?
In general we donot need to allocate any space for flash right using calloc or malloc like we do it for RAM.
The code in question extends GDB, allowing it to use various JTAG or Serial Wire interfaces to program and debug certain ARM devices. Identifying the attached devices flash device is a time consuming and disruptive (as-in can't run device code) task, so you only want to do it once, hence the local RAM allocation for storing the type and current state of the attached flash.
This line
struct kinetis_flash *kf = calloc(1, sizeof(*kf));
is a dynamic allocation of a struct kinetis_flash somewhere in RAM. It's probably used for holding information about a flash device present in the system.
This line
struct target_flash *f = &kf->f;
makes f point to the struct target_flash - named f - inside struct kinetis_flash so that you can write to it using f->some_var = ...
So the whole function is simply creating and initializing an object of type struct kinetis_flash
Though the code is correct, it's (IMO) a bit confusing to have a variable f pointing to f inside a struct. Perhaps a name like ptr_f would be more clear.
Also notice that the code is equivalent to:
static void kl_gen_add_flash(target *t, uint32_t addr, size_t length,
size_t erasesize, size_t write_len)
{
struct kinetis_flash *kf = calloc(1, sizeof(*kf));
kf->f.start = addr;
kf->f.length = length;
...
}

How to convert struct to char array in C?

I am trying to send an ethernet packet using RAW socket in C Linux. I have following struct definition in my code:
typedef struct vlink_header_s
{
uint8_t verCmd;
uint8_t reverseVerCmd;
}vlink_header_t;
typedef struct vlink_reg_rd_s
{
vlink_header_t header;
uint32_t address;
uint16_t length;
}vlink_reg_rd_t;
In main i created a struct:
vlink_reg_rd_t g_pkt;
g_pkt.header.verCmd = 0x10|VLINK_CMD_REG_RD;
g_pkt.header.reverseVerCmd = ~(g_pkt.header.verCmd);
g_pkt.address = 0x0007 .....
and message:
char sendbuf[1024];
struct ether_header *eh = (struct ether_header *) sendbuf;
how do I add all the info from the struct g_pkt to this sendbuf after ether_header so I can send a complete packet using:
sendto(sockfd, sendbuf, txLen, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll));
Everything else in my code is working, I tried other ways by adding info to sendbuf one by one and it works fine and my machine receive the packets on the other side too. I just want to make it more versatile because there are a bunch of commands and structs for each commands will work best. Thanks.
Try to use the memcpy function:
#include<iostream>
typedef struct vlink_header_s
{
uint8_t verCmd;
uint8_t reverseVerCmd;
}vlink_header_t;
typedef struct vlink_reg_rd_s
{
vlink_header_s header;
uint32_t address;
uint16_t length;
}vlink_reg_rd_t;
using namespace std;
int main()
{
vlink_reg_rd_t data;
//TODO: Set values into typedef data.
int size = sizeof(vlink_reg_rd_t); //get
char* buffer = new char[size];
memset(buffer, 0x00, size);
memcpy(buffer, &data, size); //Copy data from vlink_reg_rd_t to char*
//TODO: Send the buffer.
delete[] buffer; //free memory
return 0;
}
IMPORTANT: be aware of the order in which data types number are written into the buffer. Also it is necessary check the align the data into the structure to avoid extra bytes at the moment of use memcpy. Here you can check this topic:
for Microsoft:
https://msdn.microsoft.com/en-us/library/xh3e3fd0.aspx
https://msdn.microsoft.com/en-us/library/83ythb65.aspx
For Gcc:
https://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/Type-Attributes.html
I have done this way with protocol buffer , you can take a look at : https://www.google.com.vn/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=protocol+buffer&* .
Edit : this way called serialize data , as you serialize your data into a proto file then compile it to the packet file that you use on both server and client .

Error while trying to update array element

I am working on an embedded platform which does not have debugging features. So it is hard to say what is the error source.
I have defined in header file:
typedef struct cm_packet {
CM_Header Header; //header of packet 3 bytes
uint8_t *Data; //packet data 64 bytes
CM_Footer Footer; //footer of packet 3 bytes
} CM_Packet;
typedef struct cm_inittypedef{
uint8_t DeviceId;
CM_Packet Packet;
} CM_InitTypeDef;
extern CM_InitTypeDef cmHandler;
void CM_Init(CM_InitTypeDef *handler);
CM_AppendResult CM_AppendData(CM_InitTypeDef *handler, uint8_t identifier
, uint8_t *data, uint8_t length);
And somewhere in implementation I have:
uint8_t bufferIndex = 0;
void CM_Init(CM_InitTypeDef *cm_initer) { //init a handler
cmHandler.DeviceId = cm_initer->DeviceId;
CM_Packet cmPacket;
cmPacket.Header.DeviceId = cm_initer->DeviceId;
cmPacket.Header.PacketStart = CM_START;
cmPacket.Footer.PacketEnd = CM_END;
//initialize data array
uint8_t emptyBuffer[CM_MAX_DATA_SIZE] = {0x00};
cmPacket.Data = emptyBuffer;
cm_initer->Packet = cmPacket;
}
CM_AppendResult CM_AppendData(CM_InitTypeDef *handler, uint8_t identifier
, uint8_t *data, uint8_t length){
//some check to see if new data does not make Data overflow
uint8_t i;
/*** ERROR HAPPENS HERE!!!! ***/
handler->Packet.Data[bufferIndex++] = identifier;
//now add the data itself
for(i = 0; i < length; i++) {
handler->Packet.Data[bufferIndex++] = data[i];
}
//reset indexer
if(bufferIndex > 64) {
PacketReady(); //mark packet as ready
bufferIndex = 0
};
//return result
}
The idea is to update the Packet.Data from some other source codes which have access to the handler. For example some other sources can call that Append function to change Packet.Data. But as you see in the code, I have commented the place which causes the micro-controller to go in hard fault mode. I am not sure what is happening here. All I know is exactly at that line micro goes into hard fault mode and never recovers!
This might be a race condition but before anything else I want to know I have written correct c !!! code then I try to rule out other problems.
In function CM_Init, you are setting cmPacket.Data to point to a local array:
uint8_t emptyBuffer[CM_MAX_DATA_SIZE] = {0x00};
cmPacket.Data = emptyBuffer;
Accessing this memory address outside the scope of the function yields undefined behavior.
As #barak manos mentioned, the buffer supplied to Data is allocated on the stack.
When you get to CM_AppendData, you are writing over memory that is no longer dedicated to the buffer.
You may want to use malloc so that the buffer is allocated on the heap instead of on the stack. Just remember to call free so that you are not leaking memory.
If you can't use dynamic allocation, it's possible to dedicate some scratch memory for all the Data uses. It just needs to be static.
Hope that helps :)

Resources