I'm currently working on a C program that is opening a .wav file , copy the .wav header in the output file and after the header it adds the processed data that is obtained from the input file. The process consist of multiplying each sample with 0.5 in order to reduce the amplitude of the signal.
Here is my code:
program.c
#include <stdio.h>
#include <stdlib.h>
struct header_file
{
char chunk_id[4];
int chunk_size;
char format[4];
char subchunk1_id[4];
int subchunk1_size;
short int audio_format;
short int num_channels;
int sample_rate;
int byte_rate;
short int block_align;
short int bits_per_sample;
char subchunk2_id[4];
int subchunk2_size;
};
struct header_file header;
int main()
{
FILE * inputfile = fopen("maneskin.wav","rb"); // deschidere fisier .wav, modul de citire
FILE * outputfile = fopen("Output.wav","wb"); // creeaza fisierul .wav, modul de scriere
int BUFFSIZE = 10000; // lungimea buffer-ului
int count = 0; // numara cate frame-uri sunt in fisier
short int inputBuffer[BUFFSIZE];
short int outputBuffer[BUFFSIZE];
/* header_p meta = (header_p)malloc(sizeof(header)); */
int nb; // numarul de bytes returnati
int temp;
if (inputfile)
{
fread(&header, sizeof(header),1, inputfile);
fwrite(&header,sizeof(header),1, outputfile);
short int ch2[BUFFSIZE];
for(int i=0; i<BUFFSIZE; i++) \
ch2[i] = 1;
while (!feof(inputfile))//cat timp se citeste fisierul
{
for(int i=0; i<BUFFSIZE && !feof(inputfile); i++)
fread((char*)&inputBuffer[i],sizeof(short int),1, inputfile); // citirea datelor
count++;// incrementarea numarului de frame-uri
for(int z=0; z<BUFFSIZE; z++){
outputBuffer[z]=0.5*inputBuffer[z];
}
for(int k=0; k<BUFFSIZE; k++)
{
fwrite((char*)&outputBuffer[k], sizeof(short int), 1, outputfile);// scriere in fisier
}
}
printf("Numarul de cadre din fisierul wav:%d\n", count);
}
return 0;
}
The problemm that I have is when I'm trying to open the output file with VLC or any other media player it doens't open and gives me an error. I think it might be a problem with the header writing in the output file but I'm not sure. I tried importing the file as raw data in Audacity and played the audio file just fine but if I'm trying to import it as wav file it doesn't work.What could be the problem?
I don't know if this is your only problem, but it's definitely a problem...
In C, generally when you define a structure, the members of that structure do not sit right next to each other in memory. The compiler arranges them to fall on boundaries that are comfortable for the processor, usually in increments of the word size of the processor. So an element of type char surrounded by two ints, is not nestled right between them, but actually has perhaps 7 bytes of space between it and the next element.
This is done for execution efficiency, and usually makes sense.
But in situations like this, you want to pack the structure elements tightly together and for this there is a standard way to tell the compiler that this is what you want:
/* pack in 1 byte increments */
#pragma pack(1)
struct header_file
{
char chunk_id[4];
int chunk_size;
char format[4];
char subchunk1_id[4];
int subchunk1_size;
short int audio_format;
short int num_channels;
int sample_rate;
int byte_rate;
short int block_align;
short int bits_per_sample;
char subchunk2_id[4];
int subchunk2_size;
};
/* reset to default */
#pragma pack()
I would also suggest using size-specific types, for example uint16_t instead of short int, because you do not know the size of int on every platform where your code might be compiled.
In your code, try printing the sizeof header to see if it's what you expect, eg:
printf("sizeof(header)=%d\n", sizeof(header));
If the number does not match what it should be for a WAV header then you have got a problem with the size of one or more elements, or a problem with the packing.
Related
I am attempting to write a program to invert the color of an image. My problem is when I try to read from the DIB header in my BMP file.
When I try to get the file header size and use fread(dib.fileheader, 4,1,fp); . I get an error that says "The memory could not be written". I have attached it for further clarification.
Here is my code:
#include <stdio.h>
#include <string.h>
struct BMP {
char filetype[2]; // must be BM, must check if BM
unsigned int filesize;
short reserved1;
short reserved2;
unsigned int dataoffset;
};
struct DIB {
unsigned int fileheader;
unsigned int headersize;
int width;
int height;
short planes;
short bitsperpixel; /* we only support the value 24 here */
unsigned int compression; /* we do not support compression */
unsigned int bitmapsize;
int horizontalres;
int verticalres;
unsigned int numcolors;
unsigned int importantcolors
};
struct pixel {
int val;
char * def;
struct listitem * next;
};
void invertImage(char fileName[]){
struct BMP bmp;
struct DIB dib;
FILE *fp = fopen(fileName, "rb");
//FileType
fread(bmp.filetype, 1,2,fp);
printf("Value is %c\n", bmp.filetype[1]);
//Check if file format is BM
if(bmp.filetype[0] != 'B' && bmp.filetype[1] !='M'){
printf("Wrong format");
}
//Size of the file in bytes
fread(bmp.filesize, 4,1,fp);
printf("Value is %d\n", bmp.filesize);
//Go to dataoffset
fseek(fp,10,SEEK_CUR);
fread(bmp.dataoffset, 4,1,fp);
printf("Offset is %d\n", bmp.dataoffset);
fread(dib.fileheader, 4,1,fp);
printf("File header is %d bytes\n", dib.fileheader);
fclose(fp);
}
int main(int argc, char *argv[] ){
printf("Program name %s\n", argv[0]);
if( strcmp(argv[1],"-invert") == 0) {
printf("Invert\n");
printf("File name is %s\n", argv[2] );
invertImage(argv[2]);
}
else {
printf("Greyscale\n");
//greyScaleImage();
}
return 0;
}
Also here is the output to my program.
fread expects a pointer to memory to write the file contents. So you need to give it the address of dib.fileheader
fread( &dib.fileheader, sizeof(dib.fileheader),1,fp );
printf("File header is %d bytes\n", dib.fileheader);
It's complaining because it's interpreting whatever is in dib.fileheader as the address to write to, which may or may not be valid for your program.
Note that the following is ok as it stands because bmp.filetype is already a pointer to char - it's a char[]
fread(bmp.filetype, 1,2,fp);
printf("Value is %c\n", bmp.filetype[1]);
To make it a bit more general, you could write
fread(bmp.filetype, sizeof(bmp.filetype), 1, fp);
printf("Value is %c\n", bmp.filetype[1]);
I tried to compile your code. You must make some change in your code.
fread(bmp.filesize, 4,1,fp); --- > fread(&bmp.filesize, 4,1,fp);
fread(bmp.dataoffset, 4,1,fp); --- > fread(&bmp.dataoffset, 4,1,fp);
fread(dib.fileheader, 4,1,fp); --- > fread(&dib.fileheader, 4,1,fp);
declare the function : void invertImage(char fileName[]);
I still cannot access the color bits from a bitmap image. The problem is that, after saving the bitmap's content into a buffer, I do not know:
Where to start the loop (If i start from 0 i think it will erase the headers)?
How to access the bytes and make the changes (transform a color from the BMP into a desired one from the output)?
And, how to insert the buffer into a new bitmap file?
All the images I want to modify have rows which are divisible by 4 (I have to insert 0 when a specific byte is padding) and 24 bits per pixel. Even few tips would be much appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "bmp_header.h"
int main(void)
{
FILE *f;
f = fopen("captcha.bmp","rb");
if ((f = fopen("captcha.bmp", "rb")) == NULL)
{
printf("Error opening file %s.\n", "captcha.bmp");
exit(1);
}
fread(&BMP_header,sizeof(BMP_header),1,f);
fread(&BMP_info_header,sizeof(BMP_info_header),1,f);
fseek(f,BMP_header.imageDataOffset,SEEK_SET);
int rows = (BMP_info_header.bitPix * BMP_info_header.width + 31 ) /32 * 4 ;
char *PixelArray =malloc( rows * abs(BMP_info_header.height)*sizeof(char));
int i;
for( i =sizeof(BMP_header)+sizeof(BMP_info_header); i<=(rows * abs(BMP_info_header.height))-2;i+=3)
{
PixelArray[i]=255; // just a random value to test if this makese any sense
PixelArray[i+1]=255;
PixelArray[i+2]=255;
}
return 0;
}
And, here is bmp_header.h's content:
#pragma pack(1)
struct bmp_fileheader
{
unsigned char fileMarker1; /* 'B' */
unsigned char fileMarker2; /* 'M' */
unsigned int bfSize; /* File's size */
unsigned short unused1;
unsigned short unused2;
unsigned int imageDataOffset; /* Offset to the start of image data */
}BMP_header,BMP_header_out;
struct bmp_infoheader
{
unsigned int biSize; /* Size of the info header - 40 bytes */
signed int width; /* Width of the image */
signed int height; /* Height of the image */
unsigned short planes;
unsigned short bitPix;
unsigned int biCompression;
unsigned int biSizeImage; /* Size of the image data */
int biXPelsPerMeter;
int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
}BMP_info_header,BMP_info_header_out;
#pragma pack()
Alright, I wrote some code to write out a completely black bitmap file with the original dimensions of the old bitmap file.
This will not work with all types of bitmaps. 16-color bitmaps, for instance, have a color palette after the info header that my program does not account for. The bits per pixel also needs to be divisible by 8. If those preconditions are met, as I believe they are in 24-bit bitmaps, then this program should work.
The main code here is in getNewImageData. We calculate the row size for the image with the same formula that Wikipedia uses - it calculates the required bits and then pads that to a multiple of four bytes and then converts bits to bytes. Then we set all of the pixel array memory to zero (mostly me being paranoid about leaving values in the pad bytes). Then we run along each row and edit each pixel. The innermost for loop corresponds to each pixel. One iteration through the middle for loop writes to one pixel.
You can obviously modify this code to read the pixel data into a malloced section of memory and then edit the pixel data in place before writing it back out. This sample code does not read the input pixel data and just writes out a black bitmap of the same dimensions as the input file.
Edit: I guess I should mention what you were doing wrong.
You called fopen twice, leaving an open file pointer hanging somewhere in memory.
rows should probably be renamed to rowSize since it's the size of a row of pixels in bytes
PixelArray is not being freed.
Your for loop starts from an offset (the size of the two headers) and then is bounded by the size of the pixel data. The for loop should start from 0 and go to the size of the pixel data (unless you are reading pixel data in as you do this... which you probably shouldn't do).
Your for loop tries to write to all of the pixel data at once and doesn't account for the fact that there is anywhere between 0 and 31 bits of padding on the end of each row of pixels (my program assumes the padding is only 0, 8, 16, or 24 bits).
Here is the code:
#include <stdio.h>
#include "bmp_header.h"
#include <stdlib.h>
int readBitmapHeaders(char* fileLocation, bmp_fileheader* fileheader, bmp_infoheader* infoheader)
{
FILE* f;
f = fopen(fileLocation, "rb");
if (!f)
{
printf("Error opening file %s.\n", fileLocation);
return 1;
}
fread(fileheader, sizeof(bmp_fileheader), 1, f);
fread(infoheader, sizeof(bmp_infoheader), 1, f);
fclose(f);
return 0;
}
int writeBitmap(char* fileName, bmp_fileheader* fileheader, bmp_infoheader* infoheader, char* pixelArray, size_t pixelArraySize)
{
FILE* out;
out = fopen(fileName, "wb");
if (!out)
{
printf("Error opening file %s.\n", fileName);
return 1;
}
fwrite(fileheader, sizeof(bmp_fileheader), 1, out);
fwrite(infoheader, sizeof(bmp_infoheader), 1, out);
fwrite(pixelArray, pixelArraySize, 1, out);
fclose(out);
return 0;
}
char* getNewImageData(bmp_infoheader* infoheader, size_t* imageSize)
{
//rowsize is padded to 4 bytes
size_t rowSize = (infoheader->bitPix * infoheader->width + 31) / 32 * 4;
size_t pixelArraySize = rowSize * abs(infoheader->height);
char* pixelArray = (char*)malloc(pixelArraySize);
if (!pixelArray)
{
return NULL;
}
memset(pixelArray, 0, pixelArraySize);
size_t bytesPerPixel = infoheader->bitPix / 8;
for (int i = 0; i < infoheader->height; i++)
{
for (int j = 0; j < infoheader->width; j++)
{
size_t offset = rowSize * i + bytesPerPixel * j;
for (size_t k = 0; k < bytesPerPixel; k++)
{
pixelArray[offset + k] = 0;
}
}
}
if (imageSize)
{
*imageSize = pixelArraySize;
}
return pixelArray;
}
int main()
{
char* fileLocation = "test.bmp";
bmp_fileheader header;
bmp_infoheader infoheader;
int readResult = readBitmapHeaders(fileLocation, &header, &infoheader);
if (readResult)
{
return readResult;
}
size_t pixelArraySize;
char* pixelArray = getNewImageData(&infoheader, &pixelArraySize);
if (!pixelArray)
{
printf("%s", "Failed to create the new image data. Exiting with fatal error.\n");
return 1;
}
char* outFile = "out.bmp";
int writeResult = writeBitmap(outFile, &header, &infoheader, pixelArray, pixelArraySize);
free(pixelArray);
return writeResult;
}
I changed the bitmap header file a little to typedef the structs and make life easier (at least for me):
#pragma once
#pragma pack(1)
typedef struct _bmp_fileheader
{
unsigned char fileMarker1; /* 'B' */
unsigned char fileMarker2; /* 'M' */
unsigned int bfSize; /* File's size */
unsigned short unused1;
unsigned short unused2;
unsigned int imageDataOffset; /* Offset to the start of image data */
} bmp_fileheader;
typedef struct _bmp_infoheader
{
unsigned int biSize; /* Size of the info header - 40 bytes */
signed int width; /* Width of the image */
signed int height; /* Height of the image */
unsigned short planes;
unsigned short bitPix;
unsigned int biCompression;
unsigned int biSizeImage; /* Size of the image data */
int biXPelsPerMeter;
int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
} bmp_infoheader;
#pragma pack()
I am trying to take in a .bmp file and eventually edit the pixels one by one but I am coming up with a problem with the width and height returned to me in the INFOHEADER struct. The width returned is 13107200 and the height is 65536. However, whenever I run through the program a total of only 60003 total pixels are counted. I have no idea why this is. Any help would be greatly appreciated.
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char *argv[] ){
//define structures
typedef struct
{ unsigned short int Type; /* Magic identifier */
unsigned int Size; /* File size in bytes */
unsigned short int Reserved1, Reserved2;
unsigned int Offset; /* Offset to data (in B)*/
}HEADER; /* -- 14 Bytes -- */
typedef struct
{ unsigned int Size; /* Header size in bytes */
int Width, Height; /* Width / Height of image */
unsigned short int Planes; /* Number of colour planes */
unsigned short int Bits; /* Bits per pixel */
unsigned int Compression; /* Compression type */
unsigned int ImageSize; /* Image size in bytes */
int xResolution, yResolution;/* Pixels per meter */
unsigned int Colors; /* Number of colors */
unsigned int ImportantColors;/* Important colors */
}INFOHEADER; /* -- 40 Bytes -- */
typedef struct
{ unsigned char Red, Green, Blue;
}PIXEL;
//make instance of all three structures
HEADER data;
INFOHEADER data2;
PIXEL pixel;
//declare file read pointer
FILE *file;
//declare fileout read pointer
//FILE *fileout; //declare file printed file pointer
// open file 1 of argument counter and return 0 apon error
if( !(file = fopen( "CU.bmp","rb")))return 0;
//read HEADER data into data
fread(&data,sizeof(HEADER),1,file);
//read IB+NFOHEADER data into data2
fread(&data2,sizeof(INFOHEADER),1,file);
//Print PIXEL data
//Allocate space for pixelarray
PIXEL **pixelarray;
int r=0,c=0,rows=data2.Height,collumns=data2.Width;
pixelarray= malloc(rows*sizeof(PIXEL *));
for(r=0; r<rows; r++){
pixelarray[r]=malloc(collumns*sizeof(PIXEL));
}
//fill pixel array with pixel structs
r=0;c=0;
int pixelnum=1;
while( fread(&pixel,sizeof(PIXEL),1,file) ){
if(c == collumns){
c=0;
r++;
}
pixelarray[r][c] = pixel;
printf("\nPixel %10d: %02X%02X%02X",pixelnum,pixelarray[r][c].Red,pixelarray[r][c].Blue,pixelarray[r][c].Green);
fflush(stdout);
c++;pixelnum++;
}
free(pixelarray);
fclose(file); //close the files prior to exiting
I guess your problem is structure alignment. You can refer to it here and here. To eliminate it use the #pragma directive. So your structure declaration would be something like this:
#pragma pack(push) // push current alignment to stack
#pragma pack(1) // set alignment to 1 byte boundary
typedef struct
{
unsigned short int Type; /* Magic identifier */
unsigned int Size; /* File size in bytes */
unsigned short int Reserved1;
unsigned short int Reserved2;
unsigned int Offset; /* Offset to data (in B)*/
}HEADER; /* -- 14 Bytes -- */
typedef struct
{
unsigned int Size; /* Header size in bytes */
int Width;
int Height; /* Width / Height of image */
unsigned short int Planes; /* Number of colour planes */
unsigned short int Bits; /* Bits per pixel */
unsigned int Compression; /* Compression type */
unsigned int ImageSize; /* Image size in bytes */
int xResolution;
int yResolution;/* Pixels per meter */
unsigned int Colors; /* Number of colors */
unsigned int ImportantColors;/* Important colors */
}INFOHEADER; /* -- 40 Bytes -- */
typedef struct
{
unsigned char Red;
unsigned char Green;
unsigned char Blue;
}PIXEL;
#pragma pack(pop) // restore original alignment from stack
This correctly reads the width and height of BMP image. Further while reading image data, do it directly:
for( r=0; r<rows; r++ )
{
for( c=0; c<collumns; c++ ) // read pixel data from image
{
fread(&pixelarray[r][c] , 1, sizeof(PIXEL), file);
pixelnum++;
}
}
You must use 16 bit variable (unsigned short) instead of int for width and height. According to Wikipedia, width/height is 16 bit.
Open the bmp file in a hex editor and see what value is present in the info header.
Then debug you code and check what value you read in the infoheader.
I am trying to read 1 block of first hard drive into the memory. I tried with different LBAs but it loads spaces in to the buffer. In following code, i added for loop so that i can see if it loads anything else than just spaces. Do you guys know why it's only loading spaces into the buffer?
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <dos.h>
#include <bios.h>
struct DAP
{
unsigned char size;
unsigned char reserved1;
unsigned char blocks;
unsigned char reserved2;
unsigned char far *buffer;
unsigned long int lbalod;
unsigned long int lbahid;
} dap;
char st[80];
unsigned char buf[512];
FILE *fptr;
unsigned long int itrations = 16450559; //10gb
unsigned long int i = 0;
void main(void)
{
clrscr();
for(; i<itrations; i++)
{
dap.size = sizeof(dap);
dap.reserved1 = 0;
dap.blocks = 1;
dap.reserved2 = 0;
dap.buffer = (unsigned char far *)MK_FP(_DS, buf);
dap.lbalod = i;
dap.lbahid = 0;
_AH = 0x42;
_DL = 0x80;
_SI = (unsigned int)&dap;
geninterrupt(0x13);
printf("%lu: %s\n", i, buf);
}
}
It's using Borland Turbo C over VMWare virtual machine that is setup with WinXP. I have also tried the same on DOSBOX on Windows 7. Any help would be much appreciated.
These are only my suggestions in the hope that they help your debugging.
Print sizeof(dap) to ensure that it is indeed 16
Insert memset(buf, 'A', sizeof(buf)); before you issue INT 13h so that you can check buf is modified or not
Try printf("%lu: [%s]\n", i, buf); instead, because when buf contains \0 around its head printf stops there. The braces should work as marks.
Print _AH and _CF which should contain return codes of INT 13h
#include <dos.h>
#include <bios.h>
struct DAP
{
unsigned char size;
unsigned char reserved1;
unsigned char blocks;
unsigned char reserved2;
unsigned char far *buffer;
unsigned long int lbalod;
unsigned long int lbahid;
} dap;
char st[50];
unsigned char buff[256];
FILE *fptr;
main(void)
{
puts ("enter the lba low double word: ");
gets (st);
dap.lbalod=atol(st);
puts ("enter the lba high double word: ");
gets (st);
dap.lbahid=atol(st);
dap.size=16;
dap.reserved1=0;
dap.blocks1;
dap.reserved2=0
dap.buffer = (unsigned char far *)MK FP(DS.buf);
_AH = 0x42;
_DL = 0x80;
_SI = (unsigned int)%dap;
geninterrupt(0x13);
puts ("enter the path: ");
gets(st);
fptr = fopen(st, "wb");
fwrite(buf,256,1,fptr);
fclose(fptr);
}
i am getting statement missing error on this line dap.buffer = (unsigned char far *)MK_FP(_DS, buf);
This is got me pretty stuck, how do I fix this? I know I haven't got error checking, but they aren't required i'd guess since it's restricted to my desktop. It obveously can't be EOF. It's for the infoheader struct, fileheader works fine. Do i need to take a new line or something?
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
unsigned char fileMarker1; /* 'B' */
unsigned char fileMarker2; /* 'M' */
unsigned int bfSize;
unsigned short unused1;
unsigned short unused2;
unsigned int imageDataOffset; /* Offset to the start of image data */
}FILEHEADER;
typedef struct
{
unsigned int biSize;
int width; /* Width of the image */
int height; /* Height of the image */
unsigned short planes;
unsigned short bitPix;
unsigned int biCompression;
unsigned int biSizeImage;
int biXPelsPerMeter;
int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
}INFOHEADER;
typedef struct
{
unsigned char b; /* Blue value */
unsigned char g; /* Green value */
unsigned char r; /* Red value */
}IMAGECOMPONENT;
int fileheadfunc(FILE *image);
int infoheadfunc(FILE *image);
int main( int argc, char *argv[] )
{
char *filename; /* *threshholdInput = argv[2]; */
FILE *image;
int filehead, infohead;
filename = argv[1];
/* int threshhold = atoi(threshholdInput); */
if (argc != 2)
{
printf(" Incorrect Number Of Command Line Arguments\n");
return(0);
}
image = fopen( filename, "r");
if (image == NULL)
{
fprintf(stderr, "Error, cannot find file %s\n", filename);
exit(1);
}
filehead = fileheadfunc(image);
infohead = infoheadfunc(image);
fclose(image);
return(0);
}
int fileheadfunc(FILE *image)
{
FILEHEADER *header;
long pos;
fseek (image , 0 , SEEK_SET);
fread( (unsigned char*)header, sizeof(FILEHEADER), 1, image );
if ( (*header).fileMarker1 != 'B' || (*header).fileMarker2 != 'M' )
{
fprintf(stderr, "Incorrect file format");
exit(1);
}
printf("This is a bitmap!\n");
pos = ftell(image);
printf("%ld\n", pos);
printf("%zu\n", sizeof(FILEHEADER));
return(0);
}
int infoheadfunc(FILE *image)
{
INFOHEADER *iheader;
fseek (image, 0, SEEK_CUR );
fread( (unsigned int*)iheader, sizeof(INFOHEADER), 1, image );
printf("Width: %i\n", (*iheader).width);
printf("Height: %i\n", (*iheader).height);
return(0);
}
You're not actually allocating any storage for the BMP header data structures, e.g. you need to change this:
int fileheadfunc(FILE *image)
{
FILEHEADER *header;
long pos;
fseek(image, 0, SEEK_SET);
fread((unsigned char*)header, sizeof(FILEHEADER), 1, image);
...
to this:
int fileheadfunc(FILE *image)
{
FILEHEADER header; // <<<
long pos;
fseek(image, 0, SEEK_SET);
fread(&header, sizeof(FILEHEADER), 1, image); // <<<
...
Also, as previously noted in one of the comments above, you need #pragma pack(1) (or equivalent if you're not using gcc or a gcc-compatible compiler) prior to your struct definitions to eliminate unwanted padding. (NB: use #pragma pack() after your struct definitions to restore normal struct padding/alignment.)
There are two problems with the code:
Alignment
For performance reasons the compiler will, unless instructed to do otherwise, arrange struct fields on its "natural boundaries", effectively leaving uninitialised gaps between byte-size fields. Add
#pragma pack(1)
before the struct definitions and you should be fine. It's also easy to test: just print out the struct size without and with pragma pack in place, and you'll see the difference.
Allocation
As Paul R already said, you should allocate space for the headers, not just provide a pointer to the structures. The fact that fileheadfunc works is a coincidence, there just wasn't anything in the way that got smashed when data got written outside of the allocated space.
A last one, just for prevention sake: should you ever want to return the read structures to the calling program, do not just return a pointer to the structure allocated in the function as that will cause problems similat to the unallocated variables you have now. Allocate them in the calling function, and pass a pointer to that variable to the header read functions.
EDIT clarification regarding the last point:
DON'T
FILEHEADER * fileheadfunc(FILE *image)
{
FILEHEADER header;
...
return &header; // returns an address on the function stack that will
// disappear once you return
}
DO
int fileheadfunc(FILE *image, FILEHEADER *header)
{
...
}
which will be called like this
...
FILEHEADER header;
returnvalue = fileheaderfunc(imagefile,&header);
EDIT2: just noticed that the way you read the DIB header is not correct. There are several variations of that header, with different sizes. So after reading the file header you first need to read 4 bytes into an unsigned int and based on the value read select the correct DIB header structure to use (don't forget you already read its first field!) or tell the user you encountered an unsupported file format.