Writing BMP files (Platform Independent) - bmp

I have a structure such as
typedef struct FT_Bitmap_
{
int rows;
int width;
int pitch;
unsigned char* buffer;
short num_grays;
char pixel_mode;
char palette_mode;
void* palette;
} FT_Bitmap;
defining my bitmap data
I want to create a valid bmp file from this structure. How can I do that?

Take a look at:
http://en.wikipedia.org/wiki/BMP_file_format
Write out the header, the palette and the data.
Just take care when you write the bitmap data. It's "upside-down" - the first pixel in data is the left-bottom corner pixel.

First declare three types of initializers you will mostly use:
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long dword;
As for the structs, i suggest you using three, each for the element of the BMP:
typedef struct BITMAPINFOHEADER
{
dword bmp_size;
word bmp_app1;
word bmp_app2;
dword bmp_offset;
} BMP;
typedef struct DIB_HEADER
{
dword dib_size;
dword dib_w;
dword dib_h;
word dib_planes;
word dib_bits;
dword dib_compression;
dword dib_rawsize;
dword dib_xres;
dword dib_yres;
dword dib_palette;
dword dib_important;
} DIB;
typedef struct PIXEL_ARRAY
{
byte B;
byte G;
byte R;
} PIX;
Then you can manipulate the image in many ways. You can make an 1D/2D array to contain the data or just manipulate the bmp directly. The following code makes 500x460 colored blank bmp directly:
void new (char NAME[] , byte RED , byte GREEN , byte BLUE)
{
char build_name[256];
const char* id = "BM";
int i, j;
char debug[128];
FILE* fp;
dword rsize = (500 * sizeof(PIX) + 3) / 4 * 4;
dword pad = rsize - 500 * sizeof(PIX);
dword rawsize = rsize * 460 * sizeof(PIX);
byte zero[3] = {0};
dword size = (2) + sizeof(BMP) + sizeof(DIB) + sizeof(PIX);
BMP bmp[] = { 2+sizeof(BMP)+sizeof(DIB)+(sizeof(rawsize)/4), 0, 0, 2+sizeof(BMP)+sizeof(DIB) }; //2+ [!]
DIB dib[] = { sizeof(DIB), 500, 460, 1, 24, 0, (sizeof(rawsize)/4), 2835, 2835, 0, 0 };
PIX pix;
pix.R = RED;
pix.G = GREEN;
pix.B = BLUE;
sprintf(build_name, "%s.bmp", NAME);
fp = fopen(build_name, "wb");
if(!fp) strcpy(debug, "Access Denied.");
else strcpy(debug, "Saved.");
fwrite(id, 1, 2, fp);
fwrite(&bmp, 1, sizeof(bmp), fp);
fwrite(&dib, 1, sizeof(dib), fp);
for(i = 0; i < 460; i++)
{
for(j = 0; j < 500; j++)
{
fwrite(&pix, sizeof(pix), 1, fp);
}
if (pad) fwrite(zero, 1, pad, fp);
}
fclose(fp);
}
The point is using fseek() to locate the pixel and fwrite() to write pixels directly.

Related

When approaching the gpio register address of RaspberryPi, why is the result different between unsigned int* and char*?

Using mmap(), I am going to write a value to the GPIO register address of the Raspberry Pi.
I thought the register value would have the same when reading mapped GPIO address in unsigned int * or char *, but it was not. I compared the results for both cases.
This is my code.
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#define GPIO_BASE 0x3F200000
#define GPFSEL1 0x04
#define GPSET0 0x1C
#define GPCLR0 0x28
int main()
{
int fd = open("/dev/mem", O_RDWR|O_SYNC);
// Error Handling
if (fd < 0) {
printf("Can't open /dev/mem \n");
exit(1);
}
// Map pages of memory
char *gpio_memory_map = (char*)mmap(0, 4096, PROT_READ|PROT_WRITE,
MAP_SHARED, fd, GPIO_BASE);
// Error Handling
if (gpio_memory_map == MAP_FAILED) {
printf("Error : mmap \n");
exit(-1);
}
// GPIO18
//volatile unsigned int *gpio = (volatile unsigned int*)gpio_memory_map;
//gpio[GPFSEL1/4] = (1<<24);
volatile char *gpio = (volatile char *)gpio_memory_map;
int i;
for (i = 0; i < 16; i++)
printf("gpio[%d](%#x) = %#0x\n", i, &gpio[i], gpio[i]);
/*
for (i = 0; i < 5; i++) {
gpio[GPCLR0 / 4] = (1 << 18);
sleep(1);
gpio[GPSET0 / 4] = (1 << 18);
sleep(1);
}
*/
// Unmap pages of memory
munmap(gpio_memory_map, 4096);
return 0;
}
And those below are the results.
volatile unsigned int *gpio = (volatile unsigned int *)gpio_memory_map;
gpio[0](0x76f12000) = 0x1
gpio[1](0x76f12004) = 0x1000000
gpio[2](0x76f12008) = 0
gpio[3](0x76f1200c) = 0x3fffffc0
gpio[4](0x76f12010) = 0x24000924
gpio[5](0x76f12014) = 0x924
gpio[6](0x76f12018) = 0
gpio[7](0x76f1201c) = 0x6770696f
gpio[8](0x76f12020) = 0x6770696f
gpio[9](0x76f12024) = 0x6770696f
gpio[10](0x76f12028) = 0x6770696f
gpio[11](0x76f1202c) = 0x6770696f
gpio[12](0x76f12030) = 0x6770696f
gpio[13](0x76f12034) = 0x2ffbbfff
gpio[14](0x76f12038) = 0x3ef4ff
gpio[15](0x76f1203c) = 0
volatile char *gpio = (volatile char *)gpio_memory_map;
As the result #1 above, I thought gpio[1], gpio[2], gpio[3] should be 0. But it was different. And even if I try to write a new value on gpio[1] or gpio[2] or gpio[3], it stays the same. Why are the results different when approaching char * and unsigned char *?
gpio[0](0x76f47000) = 0x1
gpio[1](0x76f47001) = 0x69
gpio[2](0x76f47002) = 0x70
gpio[3](0x76f47003) = 0x67
gpio[4](0x76f47004) = 0
gpio[5](0x76f47005) = 0x69
gpio[6](0x76f47006) = 0x70
gpio[7](0x76f47007) = 0x67
gpio[8](0x76f47008) = 0
gpio[9](0x76f47009) = 0x69
gpio[10](0x76f4700a) = 0x70
gpio[11](0x76f4700b) = 0x67
gpio[12](0x76f4700c) = 0xc0
gpio[13](0x76f4700d) = 0x69
gpio[14](0x76f4700e) = 0x70
gpio[15](0x76f4700f) = 0x67

How to convert hex string to byte array in CAPL?

Considering having, for example, this type of hex string:
char hex_str[100] = "0x01 0x03 0x04 0x0A";
How to get out of this string the byte array representation in CAPL, like:
byte hex_str_as_byte_arr[4] = {0x01, 0x03, 0x04, 0x0A};
EDIT: Only Vector CANoe supported data types/functions are allowed!
Use strtok to split the character array into separate hex strings, then use long strtol( const char *restrict str, char **restrict str_end, int base ) to convert each hex string to an integral value.
Thanks to all...
Actually I've found a solution myself:
char hex_str[100] = "0x01 0x03 0x04 0x0A";
long data[4];
dword pos = 0;
pos = strtol(hex_str, pos, data[0]);
pos = strtol(hex_str, pos, data[1]);
pos = strtol(hex_str, pos, data[2]);
pos = strtol(hex_str, pos, data[3]);
write("0x%02x,0x%02x,0x%02x, 0x%02x", data[0], data[1], data[2], data[3]);
Now it's a simple cast: (byte) data[0]
We can use sscanf() to convert the numbers to unsigned char. In a loop, we'll need to also use a %n conversion to determine the reading position for the next iteration.
Here's a simple example (in real life, you'll need some range checking to make sure you don't overrun the output buffer):
#include <stdio.h>
int main(void)
{
const char hex_str[100] = "0x01, 0x03, 0x04, 0x0A";
unsigned char bytes[4];
{
int position;
unsigned char *b = bytes;
for (const char *input = hex_str; sscanf(input, "%hhi, %n", b, &position) == 1; ++b) {
input += position;
}
}
/* prove we did it */
for (size_t i = 0; i < sizeof bytes; ++i) {
printf("%hhu ", bytes[i]);
}
puts("");
}

Creating a packet as a string and then extracted its fields in C

I need to implement my own packets to send over UDP. I decided that I would do this by sending a char buffer which has the sequence number, checksum, size, and the data of the packet which is bytes from a file. The string i'm sending separates each field by a semicolon. Then, when I receive the string (which is my packet) I want to extract each felid, use them accordingly (the sequence number, size, and checksum) and write the bytes to a file. So far I have wrote a method to create 100 packets, and I'm trying to extract and write the bytes to a file (I'm not doing it in the receiver yet, first I'm testing the parsing in the sender). For some reason, the bytes written to my file are incorrect and I'm getting "JPEG DATATSTREAM CONTAINS NO IMAGE" error when I try to open it.
struct packetNode{
char packet[1052]; // this is the entire packet data including the header
struct packetNode *next;
};
This is how I'm creating my packets:
//populate initial window of size 100
for(i = 0; i < 100; i++){
memset(&data[0], 0, sizeof(data));
struct packetNode *p; // create packet node
p = (struct packetNode *)malloc(sizeof(struct packetNode));
bytes = fread(data, 1, sizeof(data), fp); // read 1024 bytes from file into data buffer
int b = fwrite(data, 1, bytes, fpNew);
printf("read: %d\n", bytes);
memset(&p->packet[0], 0, sizeof(p->packet));
sprintf(p->packet, "%d;%d;%d;%s", s, 0, numPackets, data); // create packet
//calculate checksum
int check = checksum8(p->packet, sizeof(p->packet));
sprintf(p->packet, "%d;%d;%d;%s", s, check, numPackets, data); //put checksum in packet
s++; //incremenet sequence number
if(i == 0){
head = p;
tail = p;
tail->next = NULL;
}
else{
tail->next = p;
tail = p;
tail->next = NULL;
}
}
fclose(fp);
and this is where I parse and write the bytes to a file:
void test(){
FILE *fpNew = fopen("test.jpg", "w");
struct packetNode *ptr = head;
char *tokens;
int s, c, size;
int i = 0;
char data[1024];
while(ptr != NULL){
memset(&data[0], 0, sizeof(data));
tokens = strtok(ptr->packet,";");
s = atoi(tokens);
tokens = strtok(NULL, ";");
c = atoi(tokens);
tokens = strtok(NULL, ";");
size = atoi(tokens);
tokens = strtok(NULL, ";");
if(tokens != NULL)
strcpy(data, tokens);
printf("sequence: %d, checksum: %d, size: %d\n", s,c,size);
int b = fwrite(data, 1, sizeof(data), fpNew);
ptr = ptr->next;
i++;
}
fclose(fpNew);
}
Since there is transfer of binary data, a JPEG stream, this data cannot be treated as a string. It's better to go all binary. For instance, instead of
sprintf(p->packet, "%d;%d;%d;%s", s, 0, numPackets, data); // create packet
you would do
sprintf(p->packet, "%d;%d;%d;", s, 0, numPackets);
memcpy(&p->packet[strlen(p->packet)], data, bytes);
but this leads to parsing problems: we would need to change this:
tokens = strtok(NULL, ";");
if(tokens != NULL)
strcpy(data, tokens);
to something like this:
tokens += 1 + ( size < 10 ? 1 : size < 100 ? 2 : size < 1000 ? 3 : size < 10000 ? 4 : 5 );
memcpy(data, tokens, sizeof(data));
#Binary Protocol
It's easier to use a binary packet:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma push(pack,1)
typedef struct Packet {
int seq, maxseq, size;
unsigned short cksum;
unsigned char payload[];
} Packet;
#pragma pop(pack)
typedef struct PacketNode{
struct PacketNode * next;
Packet packet;
} PacketNode;
PacketNode * allocPacketNode(int maxPayloadSize) {
void * ptr = malloc(sizeof(PacketNode) + maxPayloadSize); // FIXME: error checking
memset(ptr, 0, sizeof(PacketNode) + maxPayloadSize); // mallocz wouldn't cooperate
return (PacketNode*) ptr;
}
PacketNode * prepare(FILE * fp, int fsize, int chunksize)
{
PacketNode * head = allocPacketNode(chunksize);
PacketNode * pn = head;
int rd, seq = 0;
int maxseq = fsize / chunksize + ( fsize % chunksize ? 1 : 0 );
while ( ( rd = fread(pn->packet.payload, 1, chunksize, fp ) ) > 0 )
{
printf("read %d bytes\n", rd);
pn->packet.seq = seq++;
pn->packet.maxseq = maxseq;
pn->packet.size = rd + sizeof(Packet);
pn->packet.cksum = 0;
pn->packet.cksum = ~checksum(&pn->packet, pn->packet.size);
if ( rd == chunksize )
pn = pn->next = allocPacketNode(chunksize);
}
return head;
}
int checksum(unsigned char * data, int len)
{
int sum = 0, i;
for ( i = 0; i < len; i ++ )
sum += data[i];
if ( sum > 0xffff )
sum = (sum & 0xffff) + (sum>>16);
return sum;
}
void test( PacketNode * ptr ) {
FILE *fpNew = fopen("test.jpg", "w");
while (ptr != NULL)
{
printf("sequence: %d/%d, checksum: %04x, size: %d\n",
ptr->packet.seq,
ptr->packet.maxseq,
ptr->packet.cksum,
ptr->packet.size - sizeof(Packet)
);
int b = fwrite(ptr->packet.payload, ptr->packet.size - sizeof(Packet), 1, fpNew);
ptr = ptr->next;
}
fclose(fpNew);
}
void fatal( const char * msg ) { printf("FATAL: %s\n", msg); exit(1); }
int main(int argc, char** argv)
{
if ( ! argv[1] ) fatal( "missing filename argument" );
FILE * fp = fopen( argv[1], "r" );
if ( ! fp ) fatal( "cannot open file" );
fseek( fp, 0, SEEK_END );
long fsize = ftell(fp);
fseek( fp, 0, SEEK_SET );
printf("Filesize: %d\n", fsize );
test( prepare(fp, fsize, 1024) );
}
The #pragma push(pack,1) changes how the compiler aligns fields of the struct. We want them to be compact, for network transport. Using 1 is byte-aligned. The #pragma pop(pack) restores the previous setting of the pack pragma.
A note on the checksum method
First we calculate the sum of all the bytes in the packet:
int sum = 0, i;
for ( i = 0; i < len; i ++ )
sum += data[i];
Since the packet uses an unsigned short (16 bits, max value 65535 or 0xffff) to store the checksum, we make sure that the result will fit:
if ( sum > 0xffff ) // takes up more than 16 bits.
Getting the low 16 bits of this int is done using sum & 0xffff, masking out everything but the low 16 bits. We could simply return this value, but we would loose the information from higher checksum bits. So, we will add the upper 16 bits to the lower 16 bits. Accessing the higher 16 bits is done by shifting the int to the right 16 bits, like so: sum >> 16. This is the same as sum / 65536, since 65536 = 216 = 1 << 16.
sum = (sum & 0xffff) + (sum>>16); // add low 16 bits and high 16 bits
I should note that network packet checksums are usually computed 2 bytes (or 'octets' as they like to call them there) at a time. For that, the data should be cast to an unsigned short *, and len should be divided by 2. However! len may be odd, so in that case we'll need to take special care of the last byte. For instance, assuming that the maximum packet size is even, and that the len argument is always <= max_packet_size:
unsigned short * in = (unsigned short *) data;
if ( len & 1 ) data[len] = 0; // make sure last byte is 0
len = (len + 1) / 2;
The rest of the checksum method can remain the same, except that it should operate on in instead of data.

fwrite with BMP file returning 0 and segmentation fault

I'm trying to read a simple bmp file then invert the color then save it back to the file system using fread and fwrite binary mode.
So I did
BMP_Image * img;
BMP_Header * hdr;
fread(hdr,sizeof(BMP_Header),1, fptr);
img->width = hdr->width;
img->height = hdr->height;
img->bytes_per_pixel = hdr->bits*BIT_TO_BYTE;
img->header = *hdr;
img->data_size = hdr->size;
to get the header information where BMP_Header is a struct
Then read the image data and put into array
fread(data, sizeof(char), img->data_size - 54, fptr);
Then I subtract each element in my image data by 255
int i = 0;
for(i = 0;i<img->data_size;i++){
data[i] = 255 - data[i];
}
Now when I want to write the file back to the file system, I couldn't get it to work properly. I know you'd have to do fwrite 2 times. First writing the header, then writing the image data.
I have so far:
fwrite(header, 1 ,dataSize, fptr_out);
which gives me sgmentation fault and 0 byte bmp file.
Here are the typedefs of my BMP_Header and BMP_image struct
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef int int32_t;
typedef struct {
uint16_t type; // Magic identifier
uint32_t size; // File size in bytes
uint16_t reserved1; // Not used
uint16_t reserved2; // Not used
uint32_t offset; // Offset to image data in bytes
uint32_t header_size; // Header size in bytes
int32_t width; // Width of the image
int32_t height; // Height of image
uint16_t planes; // Number of color planes
uint16_t bits; // Bits per pixel
uint32_t compression; // Compression type
uint32_t imagesize; // Image size in bytes
int32_t xresolution; // Pixels per meter
int32_t yresolution; // Pixels per meter
uint32_t ncolours; // Number of colors
uint32_t importantcolours; // Important colors
} BMP_Header;
typedef struct {
BMP_Header header;
int data_size;
int width;
int height;
int bytes_per_pixel; // This amount should be equals to number of bits/8
char *data;
} BMP_Image;

converting Biginteger to Bytearray(Raw data)

I have used the following code for converting the bigint in decimal to bytearray (raw data), but I'm getting wrong result.
What is the mistake here?
I'm trying this in Apple Mac ( for Iphone app)
COMP_BYTE_SIZE is 4
Is there any bigendian/ little endian issue, please Help.
void bi_export(BI_CTX *ctx, bigint *x, uint8_t *data, int size)
{
int i, j, k = size-1;
check(x);
memset(data, 0, size); /* ensure all leading 0's are cleared */
for (i = 0; i < x->size; i++)
{
for (j = 0; j < COMP_BYTE_SIZE; j++)
{
comp mask = 0xff << (j*8);
int num = (x->comps[i] & mask) >> (j*8);
data[k--] = num;
if (k < 0)
{
break;
}
}
}
Thanks.
The argument size is at least x->size*4, ie. the target array is big enough? Also use
comp mask = (comp)0xff << (j*8);
num should be cast to uint8_t before copy
data[k--] = (uint8_t)num;