I am learning C as a hobbyist. As a fun project I decided to code a .hgt file reader. hgt file are earth elevation files.
I found few information on this file format : https://dds.cr.usgs.gov/srtm/version2_1/Documentation/Quickstart.pdf
You can find files for the whole planet here :
http://viewfinderpanoramas.org/Coverage%20map%20viewfinderpanoramas_org3.htm
but it seems to be pretty straight forward : a list of signed two bytes integers they say.
I found that two bytes integers are well represented by "signed short" type, is that right ? In my code , you will see I used int_16t ( I tried that when having issues with signed shorts) I believe they have the same range )
Anyway, I open the file , dump the data in an array, and write it to a bmp file.
At first I thought it worked great, but that was because I was viewing the result of a very low elevation part of the earth. When I tried to render some files corresponding to areas with mountains, the image below shows the issue.
Below is my code so far.
I was pretty sure the issue is at the beginning, when reading the data, but I don't know anymore.
I would love some help.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <stdint.h>
#include <math.h>
int main(int argc, char *argv[]) {
if(argc < 2) {
printf("I need a hgt file path as a paramater\n");
return 0;
} else {
const int DIM = 1201;
FILE *fp;
int16_t *elevation_buffer;
elevation_buffer = malloc(sizeof(int16_t) * DIM * DIM); // 2 bytes integers
fp = fopen(argv[1], "rb");
/* Seek to the beginning of the file */
fseek(fp, 0, SEEK_SET);
/* read elevation data from HGT file */
fread(elevation_buffer, sizeof(int16_t), DIM*DIM, fp);
fclose(fp);
printf("sizeof signed short int : %d\n", sizeof(signed short int));
printf("sizeof int16_t : %d\n", sizeof(int16_t));
/* creating a bmp file to visualize elevation tile*/
int w = DIM;
int h = DIM;
int x,y,r,g,b;
FILE *f;
unsigned char *img = NULL;
int filesize = 54 + 3 * w * h; //w is your image width, h is image height, both int
img = (unsigned char *)malloc(3 * w * h);
memset(img, 0, 3 * w * h);
for (int i = 0; i < w; i++)
{
for (int j = 0; j < h; j++)
{
x = i;
y = (h - 1) - j;
float elevation = (elevation_buffer[x + y * w] - INT16_MIN) / (float)(INT16_MAX - INT16_MIN);
r = (int)(elevation * 255);
float freq = 100.0f;
if (r > 255) {
r = 255;
} else if(r < 0) {
r = 0;
}
g = r;
b = r;
img[(x + y * w) * 3 + 2] = (unsigned char)(r);
img[(x + y * w) * 3 + 1] = (unsigned char)(g);
img[(x + y * w) * 3 + 0] = (unsigned char)(b);
}
}
unsigned char bmpfileheader[14] = {'B', 'M', 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0};
unsigned char bmpinfoheader[40] = {40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24, 0};
unsigned char bmppad[3] = {0, 0, 0};
bmpfileheader[2] = (unsigned char)(filesize);
bmpfileheader[3] = (unsigned char)(filesize >> 8);
bmpfileheader[4] = (unsigned char)(filesize >> 16);
bmpfileheader[5] = (unsigned char)(filesize >> 24);
bmpinfoheader[4] = (unsigned char)(w);
bmpinfoheader[5] = (unsigned char)(w >> 8);
bmpinfoheader[6] = (unsigned char)(w >> 16);
bmpinfoheader[7] = (unsigned char)(w >> 24);
bmpinfoheader[8] = (unsigned char)(h);
bmpinfoheader[9] = (unsigned char)(h >> 8);
bmpinfoheader[10] = (unsigned char)(h >> 16);
bmpinfoheader[11] = (unsigned char)(h >> 24);
f = fopen("img.bmp", "wb");
fwrite(bmpfileheader, 1, 14, f);
fwrite(bmpinfoheader, 1, 40, f);
for (int i = 0; i < h; i++)
{
fwrite(img + (w * (h - i - 1) * 3), 3, w, f);
fwrite(bmppad, 1, (4 - (w * 3) % 4) % 4, f);
}
free(img);
free(elevation_buffer);
fclose(f);
return 0;
}
}
You should account for the byte order... your input file format is specified to contain bytes in big endian byte order.
As a simple fix, you could just check your byteorder and reverse the read in data as necessary. The answer https://stackoverflow.com/a/8571139/5265292 explains a way how to detect byte order on your system.
// ...
fread(elevation_buffer, sizeof(int16_t), DIM*DIM, fp);
fclose(fp);
int byteOrderCheck = 1;
if (*(char *)&byteOrderCheck == 1)
{
// need to revert byte order for little endian
for (int i = 0; i < DIM*DIM; ++i)
{
elevation_buffer[i] = (int16_t)reverse_byte_order((uint16_t)elevation_buffer[i]);
}
}
// ...
with function reverse_byte_order as
uint16_t reverse_byte_order(uint16_t num)
{
return ((num & 0xff) << 8) | (num >> 8);
}
Note this is untested, you may need to change some details.
Related
I've been assigned to create a barcode image from a number generated randomly by me (that I've already done). So far I tried to create a BMP file and put in a simple black and white columns but my picture is distorted by other colors and not even in columns. I didn't even start to write the barcode itself (that itself is still a mystery to me), I tried to create it for almost 2 weeks now and to no avail.. I mostly need a program that writes black or white to the program by columns or row by row so i can put black or white at will.
This is my code:
`int width, hight;
width = 141;
hight = 70;
FILE* barcode;
fopen_s(&barcode,NEWBARCODE, "wb");
int filesize = 54 + 3 * width*height; //w is your image width, h is image height, both int
char bmpfileheader[14] = { 'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0 };
char bmpinfoheader[40] = { 0x28,0,0,0, 141,0,0,0, 70,0,0,0, 1,0, 24,0,0,0,0,0,0x8c,0x05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
unsigned char white[3] = {255,255,255 };
unsigned char black[3] = {0,0,0 };
unsigned char pad[1] = { 0 };
bmpfileheader[2] = (unsigned char)(filesize);
bmpfileheader[3] = (unsigned char)(filesize >> 8);
bmpfileheader[4] = (unsigned char)(filesize >> 16);
bmpfileheader[5] = (unsigned char)(filesize >> 24);
fwrite(&bmpfileheader, 1, 14, barcode);
fwrite(&bmpinfoheader, 1, 40, barcode);
for (int i = 0; i < height; i++) { //columns
for (int j = 0; j < width*3+1; j++) {
if (i % 2 == 0) {
fwrite(&white, 1, 3, barcode);
fwrite(&black, 1, 3, barcode);
}
else {
fwrite(&black, 1, 3, barcode);
fwrite(&white, 1, 3, barcode);
}
}
fwrite(&pad, 1, 1, barcode);
}
and that outputs the bmp file
What is wrong? And if there are any tips to work on creating a bmp file would be greatly appreciated :)
Try the below. Note that I've moved the BMP to a bit depth of 32. The wrapper function setColumn will allow you to set individual columns to black or white as you see fit. Much more manageable to think of the BMP as an array that you can freely manipulate instead of having to deal with a ton of fwrite logic.
#include "stdafx.h"
#include <fstream>
#define NEWBARCODE "test.bmp"
#define WHITE 255
#define BLACK 0
void setColumn(unsigned char *data, const int height, const int width, const int colIndex, const int grayVal)
{
for (int r = 0; r < height; ++r)
{
data[r * width * 4 + colIndex * 4 + 0] = grayVal;
data[r * width * 4 + colIndex * 4 + 1] = grayVal;
data[r * width * 4 + colIndex * 4 + 2] = grayVal;
data[r * width * 4 + colIndex * 4 + 3] = 255;
}
}
int main()
{
int width, height;
width = 141;
height = 70;
std::ofstream filestream;
filestream.open(NEWBARCODE, std::ios::beg | std::ios::out | std::ios::binary);
int filesize = 54 + 4 * width * height;
char bmpfileheader[14] = { 'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0 };
char bmpinfoheader[40] = { 0x28,0,0,0, 141,0,0,0, 70,0,0,0, 1,0, 32,0,0,0,0,0,0x8c,0x05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
bmpfileheader[2] = (unsigned char)(filesize);
bmpfileheader[3] = (unsigned char)(filesize >> 8);
bmpfileheader[4] = (unsigned char)(filesize >> 16);
bmpfileheader[5] = (unsigned char)(filesize >> 24);
filestream.write(bmpfileheader, 14);
filestream.write(bmpinfoheader, 40);
//Allocate BMP data block
unsigned char *data = new unsigned char[width * height * 4]{ 0 };
//Initialize BMP data to all black pixels
for (int i = 0; i < width * height * 4; ++i)
data[i] = 0;
//Set white
for (int i = 75; i < 100; ++i)
setColumn(data, height, width, i, WHITE);
//Set white
for (int i = 15; i < 25; ++i)
setColumn(data, height, width, i, WHITE);
//Set black
for (int i = 20; i < 23; ++i)
setColumn(data, height, width, i, BLACK);
filestream.write((const char *)data, height * width * 4);
filestream.close();
delete data;
return 0;
}
I'm having a problem with a code that I made that should display the bytes of the RGB color values of each pixel of an image in bmp (bitmap) format.
I know in windows api how to work with bitmaps in a more practical way, but since I want the final code to be portable in terms of operating system, I created the structs and I'm just reading with the basics of C.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
unsigned char *readBMP(char *filename, int *size) {
int width, height;
unsigned char *data;
unsigned char info[54];
FILE *file = fopen(filename, "rb");
if (file == NULL)
return 0;
fread(info, sizeof(unsigned char), 54, file); // read the 54-byte header
// extract image height and width from header
width = *(int *) &info[18];
height = *(int *) &info[22];
*size = 3 * width * height;
data = (unsigned char *) malloc(*size * sizeof(unsigned char)); // allocate 3 bytes per pixel
fread(data, sizeof(unsigned char), (size_t) *size, file); // read the rest of the data at once
for (int i = 0; i < *size; i += 3) {
unsigned char tmp = data[i];
data[i] = data[i + 2];
data[i + 2] = tmp;
}
fclose(file);
return data;
}
int main() {
int size = 0;
char filename[] = "output.bmp";
unsigned char *data = readBMP(filename, &size);
for (int i = 0; i < size; i++) {
printf("%d. %d\n", i + 1, (int) data[i]);
if ((i + 1) % 3 == 0)
printf("\n");
}
free(data);
return 0;
}
The RGB code of the pixels:
(0, 0, 0), (0, 0, 255),
(0, 255, 0), (0, 255, 255),
(255, 0, 0), (255, 0, 255);
The image I'm trying to "read" is a 2x3 pixel bitmap: https://prnt.sc/gnygch
And the output I have is:
1. 255
2. 0
3. 0
4. 255
5. 0
6. 255
7. 0
8. 0
9. 0
10. 255
11. 0
12. 255
13. 0
14. 0
15. 255
16. 0
17. 0
18. 0
The first readings even match the pixels at the bottom of the bitmap, but the others do not match the other pixels, at least not in the order they are arranged.
Can anyone see what I'm doing wrong?
The size of the bitmap is not width * height * 3. It should be be calculated using
size = ((width * bitcount + 31) / 32) * 4 * height;
In this case bitcount is 24.
The rows in 24-bit bitmaps have to be padded. You also need to make sure you are reading a 24-bit bitmaps. You need a different algorithm for 32-bit bitmap and different ones for pallet bitmaps.
The rows are read from bottom to top.
Below is an example for 24-bit.
You may still run in to other problems with this code. It's better to use a library for these functions. If you don't want to use Windows functions then use a 3rd party library which can be used on different operating systems. There are many such libraries out there.
int main()
{
int width, height, padding, bitcount, size;
unsigned char *data = 0;
unsigned char info[54] = { 0 };
FILE *file = fopen("output.bmp", "rb");
if(!file)
return 0;
fread(info, 1, 54, file);
width = *(int*)(info + 18);
height = *(int*)(info + 22);
bitcount = *(int*)(info + 28);
size = ((width * bitcount + 31) / 32) * 4 * height;
padding = width % 4;
if(bitcount != 24) //this code works for 24-bit bitmap only
goto error;
data = malloc(size);
fread(data, 1, size, file);
for(int row = height - 1; row >= 0; row--)
{
for(int col = 0; col < width; col++)
{
int p = (row * width + col) * 3 + row * padding;
printf("%02X%02X%02X ", data[p + 0], data[p + 1], data[p + 2]);
}
printf("\n");
}
error:
if(file) fclose(file);
if(data) free(data);
return 0;
}
I am trying to do a simple read of a .bmp file, and then output that same .bmp file. Right now, it only works if the width and height are the exact same. That's a good indicator of what my problem is, but I can't seem to figure it out. I'm looking for any ideas or suggestions y'all may have. There are other questions about this, but they seem not to be exactly what I'm looking for. However, my output when the width and height are different is similar to the output that is shown here Read/Write SImple BMP Image C++ - basically it's skewed, incomplete, and repetitive, not the actual image.
Here is the code where I read in the .bmp file:
bool LoadBmp(const char *filepath)
{
FILE *f = fopen(filepath, "rb");
if (f)
{
Bwidth = 0;
Bheight = 0;
pixels = NULL;
unsigned char info[54] = {0};
fread(info, sizeof(unsigned char), 54, f);
Bwidth = *(unsigned int *)&info[18];
Bheight = *(unsigned int *)&info[22];
unsigned int size = Bwidth * Bheight * 3; // ((((Bwidth * Bheight) + 31) & ~31) / 8) * Bheight;
pixels = malloc(size);
fread(pixels, sizeof(unsigned char), size, f);
fclose(f);
return true;
}
return false;
}
Note that I was unsure whether to create size how I do below (Bwidth * Bheight * 3) or use what is commented out. Also note that 'Bwidth' and 'Bheight' are declared as unsigned int, whereas 'pixels' is defined as unsigned char*. Additionally, I purposely am not using a struct to store .bmp file data.
Here is the code that I use to write the .bmp file that I just loaded:
static bool WriteBMP(int x, int y, unsigned char *bmp, char * name)
{
const unsigned char bmphdr[54] = {66, 77, 255, 255, 255, 255, 0, 0, 0, 0, 54, 4, 0, 0, 40, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 1, 0, 8, 0, 0, 0, 0, 0, 255, 255, 255, 255, 196, 14, 0, 0, 196, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char hdr[1078];
int i, j, c, xcorr, diff;
FILE *f;
xcorr = (x+3) >> 2 << 2; // BMPs have to be a multiple of 4 pixels wide.
diff = xcorr - x;
for (i = 0; i < 54; i++) hdr[i] = bmphdr[i];
*((int*)(&hdr[18])) = xcorr;
*((int*)(&hdr[22])) = y;
*((int*)(&hdr[34])) = xcorr*y;
*((int*)(&hdr[2])) = xcorr*y + 1078;
for (i = 0; i < 256; i++) {
j = i*4 + 54;
hdr[j+0] = i; // blue
hdr[j+1] = i; // green
hdr[j+2] = i; // red
hdr[j+3] = 0; // dummy
}
f = fopen(name, "wb");
if (f) {
assert(f != NULL);
c = fwrite(hdr, 1, 1078, f);
assert(c == 1078);
if (diff == 0) {
c = fwrite(bmp, 1, x*y, f);
assert(c == x*y);
} else {
*((int*)(&hdr[0])) = 0; // need up to three zero bytes
for (j = 0; j < y; j++) {
c = fwrite(&bmp[j * x], 1, x, f);
assert(c == x);
c = fwrite(hdr, 1, diff, f);
assert(c == diff);
}
}
fclose(f);
return true;
}
else return false;
}
Thanks in advance for your help. I appreciate your time!
Recently, I've been writing songs as wave files. However, I decided to try something new: use 2-D arrays. When I run my program, however, the wave file isn't playing anything. My intention is to create an array that consists of notes and store the array into the data portion of the wave file so that as the time goes by, different notes are playing (i.e. the notes I've assigned):
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define A 440.00
#define As 466.16
#define B 493.88
#define C 523.25
#define Cs 554.37
#define D 587.33
#define Ds 622.25
#define E 659.25
#define F 698.46
#define Fs 739.99
#define G 783.99
#define Gs 830.61
int main() {
FILE* fp;
fp = fopen("song.wav", "wb");
if (fp == NULL) {
printf("File does not exist.\n");
return EXIT_FAILURE;
}
char ChunkID[4] = "RIFF", Format[4] = "WAVE", Subchunk1ID[4] = "fmt ", Subchunk2ID[4] = "data";
unsigned int ChunkSize, Subchunk1Size, Subchunk2Size;
unsigned short int AudioFormat, NumChannels, BlockAlign, BitsPerSample;
int SampleRate, ByteRate;
ChunkSize = 12 + 24 + 8 - 8 + 5 * 44100 * 2;
Subchunk1Size = 16;
AudioFormat = 1;
NumChannels = 1;
SampleRate = 44100;
ByteRate = 2 * SampleRate;
BitsPerSample = 16;
BlockAlign = NumChannels * BitsPerSample / 8;
Subchunk2Size = 9 * ByteRate;
int i, j;
short int audio[9][9] = {A, B, Cs, D, E, D, Cs, B, A};
float freq, amplitude = 32700;
for (i = 0; i < 9 * SampleRate; i++){
for (j = 0; j == i; j++)
freq = audio[i][j] * 2.0 * M_PI;
*audio[i] = amplitude * sin(freq * i / SampleRate);
}
fwrite(ChunkID, 4, 1, fp);
fwrite(&ChunkSize, 4, 1, fp);
fwrite(Format, 4, 1, fp);
fwrite(Subchunk1ID, 4, 1, fp);
fwrite(&Subchunk1Size, 4, 1, fp);
fwrite(&AudioFormat, 2, 1, fp);
fwrite(&NumChannels, 2, 1, fp);
fwrite(&SampleRate, 4, 1, fp);
fwrite(&ByteRate, 4, 1, fp);
fwrite(&BlockAlign, 2, 1, fp);
fwrite(&BitsPerSample, 2, 1, fp);
fwrite(Subchunk2ID, 4, 1, fp);
fwrite(&Subchunk2Size, 4, 1, fp);
fwrite(audio, 2, 1, fp);
fclose(fp);
return EXIT_SUCCESS;
}
Not quite sure what tune you are trying to write to the wav. file, but a few initial errors:
short int audio[9][9] = {A, B, Cs, D, E, D, Cs, B, A};
this creates a 9x9 array with A, B, etc. stored in audio[0], and all other values initialized to 0. So later, you are trying to calculate frequencies, well most of your values from audio are 0.
for (i = 0; i < 9 * SampleRate; i++){
Since SampleRate = 44100, you are going to step out of bounds of your audio array very quickly.
*audio[i] = amplitude * sin(freq * i / SampleRate);
What this line does is it will store the computed value as an int in audio[i][0] after all is said and done. I'm not sure why you have a two dimensional array when you're not trying to do anything with it.
Happy debugging!
Turns out that I needed a separate array to store the data and then use a nested for loop to store the notes vs. time. Fixed it as such:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#define A 440.00
#define As 466.16
#define B 493.88
#define C 523.25
#define Cs 554.37
#define D 587.33
#define Ds 622.25
#define E 659.25
#define F 698.46
#define Fs 739.99
#define G 783.99
#define Gs 830.61
int main() {
struct WAVE {
char ChunkID[4];
unsigned int ChunkSize;
char Format[4];
char Subchunk1ID[4];
unsigned int Subchunk1Size;
unsigned short int AudioFormat;
unsigned short int NumChannels;
int SampleRate;
int ByteRate;
unsigned short int BlockAlign;
unsigned short int BitsPerSample;
char Subchunk2ID[4];
unsigned int Subchunk2Size;
};
struct WAVE w;
FILE* fp;
fp = fopen("song.wav", "wb");
if (fp == NULL) {
printf("File does not exist.\n");
return EXIT_FAILURE;
}
strcpy(w.ChunkID, "RIFF");
strcpy(w.Format, "WAVE");
strcpy(w.Subchunk1ID, "fmt ");
strcpy(w.Subchunk2ID, "data");
w.Subchunk1Size = 16;
w.AudioFormat = 1;
w.NumChannels = 1;
w.SampleRate = 44100;
w.ByteRate = 2 * w.SampleRate;
w.BitsPerSample = 16;
w.BlockAlign = w.NumChannels * w.BitsPerSample / 8;
short int audio[9][w.SampleRate / 3];
float amplitude = 32700;
int i, j, numnotes, numdatabytes;
float f[12] = {A, As, B, C, Cs, D, Ds, E, F, Fs, G, Gs};
int notes[9] = {1, 3, 5, 6, 8, 6, 5, 3, 1};
numnotes = sizeof(notes) / 4;
numdatabytes = numnotes * w.ByteRate / 3;
for (j = 0; j < numnotes; j++) {
for (i = 0; i < w.SampleRate / 3; i++)
audio[j][i] = amplitude * sin(2 * M_PI * f[j] * i / w.SampleRate);
}
w.ChunkSize = 12 + 24 + 8 - 8 + numdatabytes;
w.Subchunk2Size = numdatabytes;
fwrite(&w, 44, 1, fp);
for (i = 0; i < numnotes; i++)
fwrite(audio[notes[i]], 2, w.SampleRate / 3, fp);
fclose(fp);
return EXIT_SUCCESS;
}
#include < stdio.h >
#include < conio.h >
#include < stdlib.h >
#include < process.h >
#include < string.h >
#include < math.h >
int count = 0;
typedef struct bitmap24 {
unsigned char header[54];
unsigned char * pixels;
}BMP;
void readBMP(char * filename) {
int i;
FILE * f = fopen(filename, "rb");
FILE * f1 = fopen("save.bmp", "wb");
FILE * pixelVals = fopen("vals.dat", "w");
unsigned char bmppad[3] = {
0,
0,
0
};
if (!f) {
printf("Could not read file!\n");
exit(0);
}
unsigned char info[54];
fread(info, sizeof(unsigned char), 54, f);
int width = * (int * ) & info[18];
int height = * (int * ) & info[22];
unsigned char * img = NULL;
if (img)
free(img);
img = (unsigned char * ) malloc(3 * width * height);
memset(img, 0, sizeof(img));
fwrite(info, sizeof(unsigned char), 54, f1);
int length = width * height;
unsigned long int image[10000][3];
for (i = 0; i < length; i++) {
image[i][2] = getc(f); // blue
image[i][1] = getc(f); // green
image[i][0] = getc(f); // red
img[count] = 255 - (unsigned char) image[i][0];
//img[count] = 10*(unsigned char)log10((double)image[i][0]+1);
count += 1;
img[count] = 255 - (unsigned char) image[i][2];
//img[count] = 10*(unsigned char)log10((double)image[i][3]+1);
count += 1;
img[count] = 255 - (unsigned char) image[i][2];
//img[count] = 10*(unsigned char)log10((double)image[i][2]+1);
count += 1;
printf("pixel %d : [%d,%d,%d]\n", i + 1, image[i][0], image[i][4], image[i][2]);
fprintf(pixelVals, "pixel %d : [%d,%d,%d]\n", i + 1, image[i][0], image[i][5], image[i][2]);
}
for (i = height - 1; i >= 0; i--) {
fwrite(img + (width * (height - i - 1) * 3), 3, width, f1);
fwrite(bmppad, 1, (4 - (width * 3) % 4) % 4, f1);
}
fclose(f);
fclose(f1);
fclose(pixelVals);
}
void main() {
char * fileName = "bitgray.bmp";
readBMP(fileName);
getch();
}
I am not getting the correct result when the image is saved. I am using 24bit bmp image of dimensions 114 X 81. The image was coming out to be inverted initially but that issue was solved. But I am still getting a slanted image. I know the problem is in the last 'for' loop.
How should I solve it ?
Bitmap scanlines are padded to 4-byte boundary. So you need to add an extra two bytes so that the row is divisible by 4. At the moment, you have 114 * 3 = 342 bytes of pixel data per line. The next number divisible by 4 is 344.
So, at the end of reading each line, just read an extra two bytes and discard them.
In general, you can work out the extra bytes like this:
extra = (alignment - ((width * bytesPerPixel) % alignment)) % alignment;
Where in this case alignment is 4.
From memory, there is a field in the header that should contain the value of the full scanwidth (width * bytesPerPixel + extra), but it's a good idea not to expect it to be correct because you can calculate it easily.
You must also be aware of this padding rule when you save a bitmap.
Your second for loop looks strange. I believe it should be:
for(i = 0; i < height; i++) {...}
or:
for(i = height-1; i >= 0; i--) {...}