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?
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!
Suppose we want to blur an image, and the first step is to read the image, what is the purpose of using file.read(reinterpret_cast(&variableName), sizeof(variablename)) ?
struct BitmapInfo {
short signature;
int fileSize;
int reserved;
int offsetToBits;
int headerSize;
int width;
int height;
} __attribute__((packed));
int main() {
fstream file("BLUE SHARD.bmp");
auto bmpInfo = BitmapInfo();
file.read(reinterpret_cast<char*>(&bmpInfo), sizeof(bmpInfo));
auto additionalData = vector<char>(bmpInfo.offsetToBits - sizeof(bmpInfo));
file.read(reinterpret_cast<char*>(&additionalData[0]), bmpInfo.offsetToBits - sizeof(bmpInfo));
auto pixels = vector<vector<rgba>>(bmpInfo.height);
for (int i=0; i<bmpInfo.height; i=i+1) {
pixels[i] = std::vector<rgba>(bmpInfo.width);
file.read(reinterpret_cast<char*>(&pixels[i][0]), bmpInfo.width * sizeof(rgba));
What does file.read(reinterpret_cast<char*>(&variableName), sizeof(variablename)) do in c++ for reading images?
It reads sizeof(variablename) bytes from a file handled by file stream to the storage of variableName object (memory, where it resides).
In simpler words, it loads some value from a file into a variable.
I have a exercise. It says, that the C program should be able to read the information of a bitmap file and after that it should display the picture on console.
I have already written a code but when it does not work correctly.
When I debugged the code it looks like the heap is corrupted. I thinks I have a known glitch/mistake in ScanPixelline function.
I don't know how to fix it. Can someone help me to check it?
I am relatively new to C programming.
#include "stdafx.h"
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include "stdint.h"
#include "windows.h"
#pragma pack(1)
struct BMP
{
char Type[2]; //File type. Set to "BM".
int32_t Size; //Size in BYTES of the file.
int16_t Reserved1; //Reserved. Set to zero.
int16_t Reserved2; //Reserved. Set to zero.
int32_t OffSet; //Offset to the data.
int32_t headsize; //Size of rest of header. Set to 40.
int32_t Width; //Width of bitmap in pixels.
int32_t Height; // Height of bitmap in pixels.
int16_t Planes; //Number of Planes. Set to 1.
int16_t BitsPerPixel; //Number of Bits per pixels.
int32_t Compression; //Compression. Usually set to 0.
int32_t SizeImage; //Size in bytes of the bitmap.
int32_t XPixelsPreMeter; //Horizontal pixels per meter.
int32_t YPixelsPreMeter; //Vertical pixels per meter.
int32_t ColorsUsed; //Number of colors used.
int32_t ColorsImportant; //Number of "important" colors.
};
struct Color
{
unsigned char B;
unsigned char G;
unsigned char R;
};
struct ColorTable
{
Color *colors;
unsigned long length;
};
struct PixelArray
{
Color **pixels;
unsigned long rowCount;
unsigned long columnCount;
};
void readBMP(char *File_Name, BMP &a)
{
FILE *p = fopen(File_Name, "rb");
if (p == NULL)
{
printf("Can't open file!");
fclose(p);
return;
}
else
{
fread(&a, sizeof(BMP), 1, p);
}
fclose(p);
}
void Get_Inf(BMP a)
{
if (a.Type[0] != 'B' || a.Type[1] != 'M')
{
printf("This is not a BMP file");
}
else
{
printf("This is a BMP file\n");
printf("The size of this file is %lu bytes\n", a.Size);
printf("The witdth of this image is %lu pixels\n", a.Width);
printf("The height of this image is %lu pixels\n", a.Height);
printf("The number of bits per pixels in this image is %u\n", a.BitsPerPixel);
}
}
void scanBmpPixelLine(Color *&line, unsigned long length)
{
FILE *pointer_ = fopen("test.bmp", "rb");
line = new Color[length];
fread(line, sizeof(Color), sizeof(Color)*length, pointer_);
fclose(pointer_);
//file.read((char *)line, length * sizeof(Color));
}
void skipBmpPadding(char count)
{
FILE *pointer__ = fopen("test.bmp", "rb");
if (count == 0)
{
fclose(pointer__);
return;
}
char padding[3];
fread(&padding, sizeof(char), count, pointer__);
fclose(pointer__);
//file.read((char *)&padding, count);
}
void ReadPixelArray(BMP a, PixelArray &data)
{
FILE *pointer = fopen("test.bmp", "rb");
data.rowCount = a.Height;
data.columnCount = a.Width;
data.pixels = new Color*[data.rowCount];
char paddingCount = (4 - (a.Width * (a.BitsPerPixel / 8) % 4)) % 4;
fseek(pointer, 54, SEEK_SET);
for (int i = 0; i < data.rowCount; i++)
{
scanBmpPixelLine(data.pixels[data.rowCount - i - 1], a.Width);
skipBmpPadding(paddingCount);
}
}
void drawBmp(BMP a, PixelArray data)
{
HWND console = GetConsoleWindow();
HDC hdc = GetDC(console);
for (int i = 0; i < a.Height; i++)
for (int j = 0; j < a.Width; j++)
{
Color pixel = data.pixels[i][j];
SetPixel(hdc, j, i, RGB(pixel.R, pixel.G, pixel.B));
}
ReleaseDC(console, hdc);
}
void releaseBmpPixelArray(PixelArray data)
{
for (int i = 0; i < data.rowCount; i++)
delete[]data.pixels[i];
delete[]data.pixels;
}
int main()
{
char file_name[] = "test.bmp";
BMP a;
PixelArray data;
readBMP(file_name, a);
Get_Inf(a);
ReadPixelArray(a, data);
drawBmp(a, data);
releaseBmpPixelArray(data);
}
This function:
void scanBmpPixelLine(Color *&line, unsigned long length)
{
FILE *pointer_ = fopen("test.bmp", "rb");
line = new Color[length];
fread(line, sizeof(Color), sizeof(Color)*length, pointer_);
fclose(pointer_);
//file.read((char *)line, length * sizeof(Color));
}
For starters, the intent of the function appears to be to read one line of pixel data from the file. But instead, it's re-opening the file and reading from the beginning (where the header bytes are). I'm not sure if you are aware of that...
But the crash is a result of this line:
fread(line, sizeof(Color), sizeof(Color)*length, pointer_);
The second parameter, sizeof(Color), is the size of each element. The third parameter is the number of elements to read. The total bytes read from the file will be the multiplication of the second parameter by the third parameter. So you've redundantly multiplied by sizeof(Color) one too many times. The result is that it will overwrite the line buffer.
To fix, it should be:
fread(line, sizeof(Color), length, pointer_);
You probably want to pass the FILE* pointer obtained from your ReadPixelArray function into this function instead of re-opening the file for every line.
Another code review comment. You should just read the entire file into memory instead of redundantly opening and closing the file for each operation. Then parse the header and set a pointer to the first "line" after the header.
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.
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);