i am trying to read and write a bmp file in c++.output file is created but is not opening and it's size is 257kb whereas the input file is 258kb.i first read and write the 14 byte header file,40 byte imageheader file,then the 512*512 pixels,here's my code,can anyone help please
#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;
int main()
{
ifstream iFile;
char ch;
iFile.open("lena.bmp",ios::binary);
ofstream oFile;
oFile.open("lena3.bmp",ios::binary);
//int headerImageHeader=54;
// int imageHeader=40;
int fs[54];
//int ihs[imageHeader];
int tfs[54];
int pixel[512][512];
if(iFile.is_open() && oFile.is_open())
{
for(int i=0;i<54;i++)
{
iFile.get(ch);
fs[i]=ch;
cout<<fs[i]<<" ";
char p;
p=fs[i];
oFile<<p;
}
for(int w=0;w<512;w++)
{
for(int h=0;h<512;h++)
{
iFile.get(ch);
pixel[w][h]=ch;
//cout<<pixel[w][h]<<;
char pi=pixel[w][h];
oFile<<pi;
}
}
oFile.close();
iFile.close();
}
else cout << "Unable to open file"<<endl;
return 0;
}
Your code has multiple problems. Basically, the pixel storage in BMP file is not that simple. It depends on the type of BMP (e.g. Monochrome Bitmap, 16 Color Bitmap, 256 Color Bitmap and 24-bit Bitmap etc).
There are two options to read one Bitmap file and write it in another Bitmap file.
a) Read each byte from the source file and write in destination file
b) Understand Bitmap storage format and write code accordingly.
For option b) good source is available at wiki.
In summary, the calculation of Pixel Array storage (size) is:
PixelArraySize = RowSize x ImageHeight
Where ImageHeight is height of image in pixel. The RowSize is calculated as:
RowSize = [(BitsPerPixelxImageWidth + 31) / 32 ]x4
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!
I have a float buffer with the data of the ppm file. The buffer[0][0] is the 1st element and the buffer[3*width*height][0] is the last element of the data.
Buffer has elements like this. 1st = 117 2st= 135 3st = 122. It's red, green and blue.
The point is to write this data into a binary file!
I try this, getHeight() returns the Height and getWidth() the width of the data.
ofstream output(filename, ios::out | ios::binary);
output.write((char *)buffer, img.getHeight() * img.getWidth() * 3);
Also i try this, for i=0 to i=3*height*width
fp = fopen(filename, "wb");
fwrite(reinterpret_cast<char*>(&buffer[i][0]), 1, 3*height*width, fp);
A float is 4 bytes each.
fwrite() doesn't know of the type you're writing, so for the size, you need to also multiply by the size of each element.
fwrite(reinterpret_cast<char*>(&buffer[i][0]), 1, 3*height*width * sizeof(float), fp);
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
int main() {
ofstream out("blah.txt");
float val = 10.0f;
out << fixed << setprecision(5) << val << endl;
out.close();
return 0;
}
#include <iostream>
#include <fstream> // for file I/O
#define WIDTH 128
#define HEIGHT 128
#include <cmath>
using namespace std;
typedef unsigned char unchar;
class MImage
{
///////////////////////////////////////////////////////////////////////////////////////read
public:
void readimage()
{
imageData = new unchar*[HEIGHT]; // create new array size: height of image.
for (int i = 0; i < HEIGHT; i++)
{
imageData[i] = new unchar[WIDTH]; //create matrix.
}
//image I/O
pInFile = new ifstream;
pInFile->open("L.bmp", ios::in | ios::binary); // open fileName and read as binary.
pInFile->read(reinterpret_cast<char*>(imageHeaderData), 1078); //read bmp header data into array.
for (int i = 0; i < HEIGHT; i++)
{
pInFile->read(reinterpret_cast<char*>(imageData[i]), WIDTH); //read row into each array entry.
}
pInFile->close(); //close stream.
}
public:
void write()
{
//smoothFilter();
pOutFile = new ofstream;
pOutFile->open("output.bmp", ios::out | ios::binary);
pOutFile->write(reinterpret_cast<char*>(imageHeaderData), 1078); //write header data onto output
for (int i = 0; i < HEIGHT; i++)
{
pOutFile->write(reinterpret_cast<char*>(imageData[i]), WIDTH); // write new image data.
}
pOutFile->close(); //close stream
}
public:
ifstream* pInFile;
ofstream* pOutFile;
unchar imageHeaderData[1078]; //.bmp header data with offset 1078. unchar** imageData;
};
int main()
{
MImage abc;
abc.readimage();
abc.write();
return 0;
}
I am unable to read image in a 2d array so that i could do some processing on it. i have used the code above but saved file is giving error.
what i am doing is first reading a .bmp file 128x128 then saving it in an other .bmp file. but when i try to open output file it gives error "file is corrupted or large in size"
Hope it helps ;)
I skipped error checking but you should add it to the final code. For writing a .bmp image, wirte BITMAPFILEHEADER first, then BITMAPINFOHEADER and at the end the actual raw data
FILE* filePtr;
int error;
unsigned int count;
BITMAPFILEHEADER bitmapFileHeader;
BITMAPINFOHEADER bitmapInfoHeader;
int imageSize;
unsigned char* bitmapImage;
// Open the height map file in binary.
error = fopen_s(&filePtr, filename, "rb");
// Read in the file header.
count = fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr);
// Read in the bitmap info header.
count = fread(&bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr);
// Save the dimensions of the terrain.
Width= bitmapInfoHeader.biWidth;
Height= bitmapInfoHeader.biHeight;
// Calculate the size of the bitmap image data.
imageSize = Width* Height* 3;
// Allocate memory for the bitmap image data.
bitmapImage = new unsigned char[imageSize];
// Move to the beginning of the bitmap data.
fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET);
// Read in the bitmap image data.
count = fread(bitmapImage, 1, imageSize, filePtr);
// Close the file.
error = fclose(filePtr);
Don't forget to delete bitmapImage or use std::vector instead
I'm working on a C++ program that overlays one 8 bit depth BMP image into another one of the same format and size. The program is supposed to read both images and then for every black pixel in the overlay picture, it changes the same pixel in the original picture to white. The essentials parts of my code are shown below:
The class for a BMP picture:
class BMPImage{
int width;
int height;
int size;
unsigned char* data; //Array with all pixels
unsigned char* header; //54 byte header
void setSize();
public:
BMPImage(const char* filename);
BMPImage(unsigned char* header, unsigned char* data);
int getSize();
int getWidth();
int getHeight();
unsigned char* getData();
unsigned char* getHeader();
void createFile(char* filename);
}
Constructors to create an object from a filename or from a header and a data array:
BMPImage::BMPImage(const char* filename){
FILE* f = fopen(filename, "rb");
if(f == NULL)
throw "Argument Exception";
header= new unsigned char[54];
fread(header, sizeof(unsigned char), 54, f); // read the 54-byte header
// extract image height and width from header
setSize();
cout << endl;
cout << "Reading file " << filename << endl;
cout << " Width: " << width << endl;
cout << " Height: " << height << endl;
data = new unsigned char[size];
fread(data, sizeof(unsigned char), size, f); // read the rest of the data at once
fclose(f);
}
BMPImage::BMPImage(unsigned char* h, unsigned char* d){
header = new unsigned char[54];
for(int i=0;i<54;i++){
header[i]=h[i];
}
setSize();
data = new unsigned char[size];
for(int i=0;i<size;i++){
data[i]=d[i];
}
}
A function to create a file from a BMPImage object:
void BMPImage::createFile(char* filename){
FILE* f;
f=fopen(filename, "wb");
//write header
fwrite(header,sizeof(unsigned char), 54, f);
//write data
fwrite(data, sizeof(unsigned char), size, f);
//close file
fclose(f);
cout<<endl<<"File "<< filename <<" was successfully created."<<endl;
}
Finally, my function to overlay two images. The overlay is done so that if the pixel of "overlay" is black, the corresponding pixel in the result image will be white, else the pixel will be the same as in the "original" image.
void overlay(char* original, char* overlay, char* result){
BMPImage overlayIm(overlay);
BMPImage originalIm(original);
//Check if the pictures have the same size
if(originalIm.getHeight()!=overlayIm.getHeight() || originalIm.getWidth()!=overlayIm.getWidth())
throw "Files do not have the same size";
int size = overlayIm.getSize();
unsigned char* dataResult = new unsigned char[size];
unsigned char* dataOriginal = originalIm.getData();
unsigned char* dataOverlay = overlayIm.getData();
//If a pixel in overlay is black, change corresponding pixel in original to white
for(int i=0; i<size; i++){
if(dataOverlay[i]!=0){
dataResult[i]=dataOriginal[i];
}else{
dataResult[i]=(unsigned char)255;
}
}
//Create new file with the result
BMPImage resultIm(originalIm.getHeader(), dataResult);
resultIm.createFile(result);
cout<<endl<<"New overlay image created in "<<result <<endl;
}
Although I only check for the pixels in the overlay image, it seems that the program is checking for the pixels in both the overlay and the original image at the same time. So when a pixel is black in the original image, the pixel in the result will be white, and I just want it to be white only if the pixel in overlay image is black.
An example of my problem is shown in this picture. The pictures on the left are the arguments in the overlay function. In the right, the "desired" picture is the one that my program should generate, and the "result" is the one that my program actually generates:
I don't understand why the black pixels in the original are changed to white if I never check the pixels in my original picture when I create the result image. Can anybody point me to the mistake I'm committing so that I can solve my problem?
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;
}