This question already exists:
I am getting BITMAP filesize 0 everytime [duplicate]
Closed 8 years ago.
I am trying to read the FILEHEADER and INFOHEADER of a bitmap file, but I am unable to do so. I am getting Segmentation Fault.
My code has been given below.
#include <bits/stdc++.h>
using namespace std;
typedef int LONG;
typedef unsigned short WORD;
typedef unsigned int DWORD;
struct BITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
};
struct BITMAPINFOHEADER {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
};
int main(void){
ifstream file("lena.bmp");
char* bf = NULL;
int begin = file.tellg();
file.seekg(0, ios::end);
int end = file.tellg();
int length = end-begin;
file.read(bf, length);
BITMAPFILEHEADER* file_header = (BITMAPFILEHEADER*)(bf);
//BITMAPINFOHEADER* info_header = (BITMAPINFOHEADER*)(bf+sizeof(BITMAPFILEHEADER)-1);
cout << file_header->bfSize << endl;
//cout << info_header->biSize << endl;
return 0;
}
The segmentation fault is probably because you forgot to initialize bf;
int end = file.tellg();
int length = end-begin;
bf = new char[lenght+1]; //Add this
file.seekg(0, ios::beg); //And this too
file.read(bf, length);
[EDIT]
The second problem (size is always 0) occurs because the file pointer is at the end of the file, so you never read anything actually.
As was mentioned in the previous reply, you where trying to file.read with a null pointer.
I see that you are trying to load the whole file into memory, then do some pointer arithmetics to work with the data. But why not just read the BITMAPFILEHEADER directly instead?
ifstream file("lena.bmp");
// read in the header:
BITMAPFILEHEADER header;
file.read(reinterpret_cast<char *>(&header), sizeof(header));
// validate the header, get the size in bytes of the bitmap data
size_t bitmapSizeBytes = width * height * channels; // or something like that...
// Now read the bitmap. Use a vector to simplify memory management:
std::vector<unsigned char> bitmap;
bitmap.resize(bitmapSizeBytes);
file.read(reinterpret_cast<char *>(&bitmap[0]), bitmapSizeBytes);
Related
I am trying to store data of .wav file in an array. I am not able to find a way to store data from subchunk2 in an array. Can anybody help me with this?
This is the code which I have used till now
typedef 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; // sample_rate denotes the sampling rate.
int byte_rate;
short int block_align;
short int bits_per_sample;
char subchunk2_id[4];
int subchunk2_size; // subchunk2_size denotes the number of samples.
} header;
typedef struct header_file* header_p;
Main Part
//Load wave file
FILE* infile = fopen("E:/fCWT-main/MATLAB/1s_speech.wav", "rb"); // Open wave file in read mode
int BUFSIZE = 512; // BUFSIZE can be changed according to the frame size required (eg:512)
int count = 0; // For counting number of frames in wave file.
short int buff16[BUFSIZE]; // short int used for 16 bit as input data format is 16 bit PCM audio
header_p meta = (header_p)malloc(sizeof(header)); // header_p points to a header struct that contains the wave file metadata fields
int nb; // variable storing number of byes returned
if (infile)
{
fread(meta, 1, sizeof(header), infile);
//fwrite(meta, 1, sizeof(*meta), outfile);
int samples = meta->subchunk2_size;
size_t result;
tmp = (float*)malloc(sizeof(float) * samples);
while (!feof(infile))
{
nb = fread(buff16, 1, BUFSIZE, infile); // Reading data in chunks of BUFSIZE
cout << nb << endl;
count++; // Incrementing Number of frames
}
cout << " Number of frames in the input wave file are " << count << endl;
}
Basically here I want to store and display the data of wav file into an array so that I can use that array for further processing and I don't have any idea how to do it. I have tried searching it online but that solutions were limited to reading Header File.
I am new in C++ so any help regarding this will work.
Thanks!
Thank you for help. This is the final version.
Working version
BMPHead.znak1='B';
BMPHead.znak2='M';
BMPHead.bfSize=40;
BMPHead.bfReserved1 = 0;
BMPHead.bfReserved1 = 0;
BMPHead.bfOffBits=54;
BMPHead.biSize=40;
BMPHead.biWidth=CSVHead.depth_pxsize ;
BMPHead.biHeight=CSVHead.lateral_pxsize;
BMPHead.biPlanes=1;
BMPHead.biBitCount=32;
BMPHead.biCompression = 0;
BMPHead.biSizeImage = ((CSVHead.lateral_pxsize * CSVHead.depth_pxsize)*4);
BMPHead.biXPelsPerMeter = 0;
BMPHead.biYPelsPerMeter = 0;
BMPHead.biClrUsed = 0;
BMPHead.biClrImportant =0;
void zamiana_danych(int &EndOfHead, float line[], csvh &CSVHead, bmph BMPHead, float &max, float &min)
{ unsigned char bit_empty=0;
float tmp[500];
ifstream obraz;
fstream bitmapa("POP_OCT.bmp");
obraz.open("POP_OCT.csv", ios::binary);
obraz.seekg(EndOfHead, ios_base::beg);
bitmapa.seekg(BMPHead.bfOffBits, ios_base::beg); // this part was missing
for( int numb=0; numb < CSVHead.depth_pxsize; numb++ )
{
//wczytanie jednego wiersza dancyh
for(int i=0; i<CSVHead.lateral_pxsize; i++)
{ //wczytanie komorki danych
obraz>>line[i];
obraz.seekg(+1, ios_base::cur);
tmp[i]=((max-min) / 255) * line[i] - min;
unsigned char pixel[4]={tmp[i],tmp[i],tmp[i],0};
bitmapa.write((char*)&pixel, sizeof(pixel));
}
}
bitmapa.close();
obraz.close();
Question
I need to create BMP in C++ without using nonstandard libraries, but I still have some errors. I know there are some similiar topics, but it's still not clear for me how to make this thing working.
File is created, but when I try to open it, photo browser says:
"Windows Image Viewer can not open the image, because the file is too big or broken".
I'm not sure if the problem is in header or in pixel writing.
That's the code:
#include<iostream>
#include<fstream>
#include<cstring>
#include <stdlib.h>
using namespace std;
struct bmph{
unsigned short int bfType; // instead of this I use znak1 and znak2
unsigned long int bfSize;
unsigned short int bfReserved1;
unsigned short int bfReserved2;
unsigned long int bfOffBits;
unsigned long int biSize;
unsigned long int biWidth;
unsigned long int biHeight;
unsigned short int biPlanes;
unsigned short int biBitCount;
unsigned long int biCompression;
unsigned long int biSizeImage;
unsigned long int biXPelsPerMeter;
unsigned long int biYPelsPerMeter;
unsigned long int biClrUsed;
unsigned long int biClrImportant;
};
int main()
{
unsigned char pixel[4]={255,255,255,0};
char znak1='B';
char znak2='M';
bmph bmpheader;
ofstream moje_bmp("tworzBMP.bmp");
bmpheader.bfSize=40 + (500*999)*4;
bmpheader.bfReserved1 = 0;
bmpheader.bfReserved1 = 0;
bmpheader.bfOffBits=54;
bmpheader.biSize=40;
bmpheader.biWidth=500;
bmpheader.biHeight=999;
bmpheader.biPlanes=1;
bmpheader.biBitCount=4;
bmpheader.biCompression = 0;
bmpheader.biSizeImage = (500*999)*4;
bmpheader.biXPelsPerMeter = 0;
bmpheader.biYPelsPerMeter = 0;
bmpheader.biClrUsed = 0;
bmpheader.biClrImportant =0;
moje_bmp << znak1 <<znak2;
moje_bmp.write((char*)&bmpheader.bfSize, sizeof(bmpheader.bfSize));
moje_bmp.write((char*)&bmpheader.bfReserved1, sizeof(bmpheader.bfReserved1));
moje_bmp.write((char*)&bmpheader.bfReserved1, sizeof(bmpheader.bfReserved1));
moje_bmp.write((char*)&bmpheader.bfOffBits, sizeof(bmpheader.bfOffBits));
moje_bmp.write((char*)&bmpheader.bfSize, sizeof(bmpheader.bfSize));
moje_bmp.write((char*)&bmpheader.biWidth, sizeof(bmpheader.biWidth));
moje_bmp.write((char*)&bmpheader.biHeight, sizeof(bmpheader.biHeight));
moje_bmp.write((char*)&bmpheader.biPlanes, sizeof(bmpheader.biPlanes));
moje_bmp.write((char*)&bmpheader.biBitCount, sizeof(bmpheader.biBitCount));
moje_bmp.write((char*)&bmpheader.biCompression, sizeof(bmpheader.biCompression));
moje_bmp.write((char*)&bmpheader.biSizeImage, sizeof(bmpheader.biSizeImage));
moje_bmp.write((char*)&bmpheader.biXPelsPerMeter, sizeof(bmpheader.biXPelsPerMeter));
moje_bmp.write((char*)&bmpheader.biYPelsPerMeter, sizeof(bmpheader.biYPelsPerMeter));
moje_bmp.write((char*)&bmpheader.biClrUsed, sizeof(bmpheader.biClrUsed));
moje_bmp.write((char*)&bmpheader.biClrImportant, sizeof(bmpheader.biClrImportant));
for(int tx=0; tx<500;tx++)
{
for(int ty=0; ty<999;ty++)
{
moje_bmp.write((char*)&pixel, sizeof(pixel));
}
}
moje_bmp.close();
return 0;
}
As all of it worked in the example above, in my main project it does not. Here are the functions from main project and the same result:
"Windows Image Viewer can not open the image, because the file is too big or broken".
void glowa_bmp(bmph &BMPHead, csvh &CSVHead)
{
ofstream bitmapa("bitmapa.bmp", ios::binary);
//przypisanie wartosci naglowka
BMPHead.znak1='B';
BMPHead.znak2='M';
BMPHead.bfSize=54;
BMPHead.bfReserved1 = 0;
BMPHead.bfReserved1 = 0;
BMPHead.bfOffBits=54;
BMPHead.biSize=40;
BMPHead.biWidth=CSVHead.depth_pxsize ;
BMPHead.biHeight=CSVHead.lateral_pxsize;
BMPHead.biPlanes=1;
BMPHead.biBitCount=32;
BMPHead.biCompression = 0;
BMPHead.biSizeImage = ((CSVHead.lateral_pxsize * CSVHead.depth_pxsize)*4);
BMPHead.biXPelsPerMeter = 0;
BMPHead.biYPelsPerMeter = 0;
BMPHead.biClrUsed = 0;
BMPHead.biClrImportant =0;
//zapisanie naglowka w pliku
bitmapa << BMPHead.znak1 << BMPHead.znak2;
bitmapa.write((char*)&BMPHead.bfSize, sizeof(BMPHead.bfSize));
bitmapa.write((char*)&BMPHead.bfReserved1, sizeof(BMPHead.bfReserved1));
bitmapa.write((char*)&BMPHead.bfReserved1, sizeof(BMPHead.bfReserved1));
bitmapa.write((char*)&BMPHead.bfOffBits, sizeof(BMPHead.bfOffBits));
bitmapa.write((char*)&BMPHead.bfSize, sizeof(BMPHead.bfSize));
bitmapa.write((char*)&BMPHead.biWidth, sizeof(BMPHead.biWidth));
bitmapa.write((char*)&BMPHead.biHeight, sizeof(BMPHead.biHeight));
bitmapa.write((char*)&BMPHead.biPlanes, sizeof(BMPHead.biPlanes));
bitmapa.write((char*)&BMPHead.biBitCount, sizeof(BMPHead.biBitCount));
bitmapa.write((char*)&BMPHead.biCompression, sizeof(BMPHead.biCompression));
bitmapa.write((char*)&BMPHead.biSizeImage, sizeof(BMPHead.biSizeImage));
bitmapa.write((char*)&BMPHead.biXPelsPerMeter, sizeof(BMPHead.biXPelsPerMeter));
bitmapa.write((char*)&BMPHead.biYPelsPerMeter, sizeof(BMPHead.biYPelsPerMeter));
bitmapa.write((char*)&BMPHead.biClrUsed, sizeof(BMPHead.biClrUsed));
bitmapa.write((char*)&BMPHead.biClrImportant, sizeof(BMPHead.biClrImportant));
bitmapa.close();
}
void zamiana_danych(int &EndOfHead, float line[], csvh &CSVHead, float &max, float &min)
{ unsigned char bit_empty=0;
float tmp[500];
ifstream obraz;
ofstream bitmapa("bitmapa.bmp", ios::binary);
obraz.open("POP_OCT.csv", ios::binary);
obraz.seekg(EndOfHead, ios_base::beg);
for( int numb=0; numb < CSVHead.depth_pxsize; numb++ )
{
//wczytanie jednego wiersza dancyh
for(int i=0; i<CSVHead.lateral_pxsize; i++)
{ //wczytanie komorki danych
obraz>>line[i];
obraz.seekg(+1, ios_base::cur);
tmp[i]=((max-min) / 255) * line[i] - min;
unsigned char pixel[4]={tmp[i],tmp[i],tmp[i],0};
bitmapa.write((char*)&pixel, sizeof(pixel));
}
}
bitmapa.close();
obraz.close();
}
bmpheader.bfSize=40 + (500*999)*4;
You need to add 54 instead of 40:
BITMAPFILEHEADER: 14
BITMAPINFOHEADER: 40
Which you both combined in struct bmph.
Thus: 54 + (500*999)*4;, being the total size of the resulting file.
bmpheader.biBitCount=4;
bmpheader.biBitCount should be 32 (24 for RGB and 32 for RGBA).
Also, if you can make sure the padding of struct bmph is ok (i.e. no padding - not sure about the setting for Linux, it's #pragma pack in Windows for example), then you could write the whole struct in one go.
And as #fleebness already suggested, make sure to use fixed types in your struct, so they won't change depending on the system you are compiling for.
Have you tried this correction:
ofstream moje_bmp("tworzBMP.bmp", std::ios::binary | std::ios::out);
I believe std::ofstream expects text output instead of binary, so you have to override it.
Also, you might refer to this:
https://web.archive.org/web/20080912171714/http://www.fortunecity.com/skyscraper/windows/364/bmpffrmt.html
and instead of using 'unsigned short int' and such, try things like std::uint16_t for 2 byte values, or std::uint32_t for four byte values, etc.
I have been trying to read a bmp file with ifstream, however it works fine without debugging, when I run it in debug mode it fails. At the beginning I read 54 bytes of info, to get the height and the width of the picture, which are unfortunately -858993460 in debug mode, so the whole size of my picture overflows everytime, so I get a bad allocation error. I use VS 2013, could anyone help me out with this one ?
unsigned char* readBMP(char* filename)
{
int i;
char info[54];
std::ifstream ifs(filename, std::ifstream::binary);
ifs.read(info, 54);
// extract image height and width from header
int width = *(int*)&info[18];
int height = *(int*)&info[22];
int size = 3 * width * height;
char* data = new char[size]; // allocate 3 bytes per pixel
ifs.read(data, size);
ifs.close();
return (unsigned char*)data;
}
I guess you failed to open the file, so your read must been failed.
you can check: if (ifs.is_open()) { /* good*/}
you can also check: if(ifs.read(...)){/*good*/}
try this code:
unsigned char* readBMP(char* filename)
{
int i;
char info[54];
std::ifstream ifs(filename, std::ifstream::binary);
if(!ifs.is_open()){
std::cerr<<" failed to open file"<<std::endl;
return NULL;
}
if(!ifs.read(info, 54)) {
std::cerr<<" failed to read from file"<<std::endl;
return NULL;
}
// extract image height and width from header
int width = *(int*)&info[18];
int height = *(int*)&info[22];
int size = 3 * width * height;
char* data = new char[size]; // allocate 3 bytes per pixel
ifs.read(data, size);
ifs.close();
return (unsigned char*)data;
}
Here's my first post, and first question.
Why shouldn't I use:bmpFile.read((char*)(&bmpImageData),bmpImageDataSize); to read data block from BMP file, and how should I do this properly (I know about BGR triplets, but as for now I do not really care about them existing) EDIT: Maybe I should clarify something - as the code is right now it compiles pretty well, but stops working on the line provided higher.
#include "stdafx.h"
#include "mybmp.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
filebuf bmpBuff;
ifstream bmpFile("test.bmp", ios::binary);
bmpBuff.open("test_zapis.bmp", ios::binary | ios::out);
ostream bmpSaved(&bmpBuff);
unsigned long bmpSizeBuffer;
bmpFile.seekg(2, ios::beg); // Missing BMP, DIB identification for good byte adjustment
mybmp bmpHeader;
bmpFile.read((char*)(&bmpHeader),sizeof(mybmp));
if(bmpHeader.FReadFileSize()>0)
{
unsigned long bmpImageDataSize = bmpHeader.FReadFileSize()-bmpHeader.FReadOffset(); // Reading ImageData size
char* bmpImageData = new char[bmpImageDataSize];
bmpFile.seekg(bmpHeader.FReadOffset(),ios::beg); // Positioning pointer to ImageData start point
bmpFile.read((char*)(&bmpImageData),bmpImageDataSize); // This breaks down // Reading ImageData to bmpImageData buffer
// Fun with buffer //
for(int i = 0; i < bmpImageDataSize; i++)
{
bmpImageData[i]++;
}
// Saving (...) //
}
else
{
cout << "Plik nie zostal wczytany"<<endl;
}
return 0;
}
My mybmp.h header:
#pragma pack(push,1)
class mybmp
{
unsigned long fileSize; // BMP overall filesize in bytes
unsigned long reserved; // filled with 0
unsigned long fileOffset; // Offset before Raster Data
//---------------------------//
unsigned long size; // Size of InfoHeader = 40
unsigned long width; // overall image width
unsigned long height; // overall image height;
unsigned short planes; // = 1;
unsigned short bitCounts; // Bits per Pixel
unsigned long compression; // Type of compression
unsigned long typeOfImage; // compressed size of Image. 0 if compression parameter = 0;
unsigned long xPixelsPerM; // horizontal resolution - Pixels/Meter
unsigned long yPixelsPerM; // vertical resolution - Pixels/Meter
unsigned long colorsUsed; // Number of colors actually used
unsigned long colorsImportant; // Number of important colors, 0 if all
//--------------------------//
public:
mybmp(void);
unsigned long FReadFileSize();
void FPrintObject();
unsigned long FReadOffset();
~mybmp(void);
};
#pragma pack(pop)
The line bmpFile.read((char*)(&bmpImageData),bmpImageDataSize); looks wrong, the bmpImageData is already a char *. Taking the address gives you a char ** (which will probably be on the stack), which you then write to, corrupting your stack.
Change your problem line to this bmpFile.read (bmpImageData, bmpImageDataSize); does that help?
I am trying to learn more about binary files, so I started with HexEdit, and I manually wrote a file and created a template for it. Here is my work:
Now, I started working on a console application in C++ Win32 to read the contents in that file and make them look friendly. Here is part my code:
typedef unsigned char BYTE;
long getFileSize(FILE *file)
{
long lCurPos, lEndPos;
lCurPos = ftell(file);
fseek(file, 0, 2);
lEndPos = ftell(file);
fseek(file, lCurPos, 0);
return lEndPos;
}
int main()
{
const char *filePath = "D:\\Applications\\ColorTableApplication\\file.clt";
BYTE *fileBuf; // Pointer to our buffered data
FILE *file = NULL; // File pointer
if ((file = fopen(filePath, "rb")) == NULL)
printf_s("Could not open specified file\n");
else {
printf_s("File opened successfully\n");
printf_s("Path: %s\n", filePath);
printf_s("Size: %d bytes\n\n", getFileSize(file));
}
long fileSize = getFileSize(file);
fileBuf = new BYTE[fileSize];
fread(fileBuf, fileSize, 1, file);
for (int i = 0; i < 100; i++){
printf("%X ", fileBuf[i]);
}
_getch();
delete[]fileBuf;
fclose(file); // Almost forgot this
return 0;
}
(I provided that much code because I want to be clear, to help you get the idea about what I am trying to do)
First of all, I need to get the first 14 bytes and write them in the console as text, and then, in a for I need to write something like this for each color:
black col_id = 1; R = 00; G = 00; B = 00;
red col_id = 2; R = FF; G = 00; B = 00;
etc...
How can I read and translate these bytes?
It is correct as you have it to write out the 14 bytes.
a technique is to create a struct with the layout of your records, then cast e.g. (C-style)
typedef struct
{
char name[10];
long col_id;
unsigned char R;
unsigned char G;
unsigned char B;
} rec;
rec* Record = (rec*)(fileBuf + StartOffsetOfRecords);
now you can get the contents of the first record
Record->name, ...
getting next record is just a matter of moving Record forward
++Record;
You could also have a struct for the header to make it more convenient to pickout the number of records, it is good to use stdint.h in order to get well defined sizes. also to pack structures on byte boundary to make sure no padding is done by the compiler i.e. #pragma pack(1) at the top of your source.
typedef struct
{
char signature[14];
uint32_t tableaddress;
uint32_t records;
} header;
typedef struct
{
char name[10];
uint32_t col_id;
unsigned char R;
unsigned char B;
unsigned char G;
} rec;
so instead when you read you could do like this
header Header;
rec* Record;
fread(&Header,sizeof(header),1,file);
fread(fileBuf,1,fileSize,file);
Record = (rec*)(fileBuf); // first record can be accessed through Record