?
Solved

Programming help with Binary image file with raw image format

Posted on 2011-10-10
7
Medium Priority
?
336 Views
Last Modified: 2012-06-27
The program is supposed to retrieve the Red, Blue and Green components on a given coordinate of an image.  The image has a RAW format and has a 100 x 100 pixel resolution.  This is what the program must have:
•      Three unsigned char fields r, g, b have to defined in a struct.
•      The user must enter the file name with the extension of .raw.
•      The (x, y) coordinate must be two numbers between 0 and 99. If not the program has to display a message and exit.
•      Use seekg to the corresponding location in the image file and then retrieve the color information with this formula:      loc = (y * image_x + x) * 3;    (image_x is always equal to 100).
•      Display the 3 numbers red, green, blue.
I’m having trouble with the user entering the file name, with the use of the seekg, and with the display of the numbers of green, red, blue.
Here is the program, what can I do to make it run as it should?
Thank you.

// Binari Image File
#include <iostream>
#include <fstream>
using namespace std;

//Structure for Red, Blue and Green
struct RGB
	{
	unsigned char r;	//red
	unsigned char g;	//green
	unsigned char b;	//blue
	};

int main()
{
	int x, y, loc;
	ifstream fileName;
	char data[100]; 
	int image_x = 100;

	RGB coordinate;

	//The user needs to enter the image name having a RAW format. The image has 100 x 100 pixel resolution.
	cout << "Enter the image name: " << endl;
	//cin >> fileName;

	//The user will enter a coordinate x and y. The coordinates must be between 0 and 99.
	cout << "Enter the pixel coordinate (x, y): " << endl;
	cin >> x >> y;

	if((x < 0) ||(x > 99) || (y < 0) || (y > 99))
	{
		cout << "Error x and y must be between 0 and 99." << endl;
		return 0;
	}
	else 
 
   // Open the file for input.
  fileName.read(data, sizeof(data));
   if (!fileName)
   {
      cout << "Cannot open " << fileName << endl;
      return 0;
   }

	loc = ((y + image_x + x) * 3);

	fileName.seekg(loc, ios::beg);

	//This will retrieve the RGB components depending on the coordinate.
	cout << "RGB Color at (" << x << ", " << y << "): " << endl;
	cout << coordinate.r << coordinate.g << coordinate.b;

   
   // Close the files.
   fileName.close();
   
   return 0;
}

Open in new window

0
Comment
Question by:MEAM
  • 3
  • 3
7 Comments
 
LVL 15

Expert Comment

by:Minh Võ Công
ID: 36947028
loc = (y+image_x*x)*3 ;  //image_x = 100
0
 
LVL 35

Expert Comment

by:sarabande
ID: 36947114
the filename is an ifstream. so you can't get input from cin where the user types a string. i would say filename is a poor name for a stream. better use

std::string filename;
std::ifstream file;
...
std::getline(cin, filename);
file.open(filename.c_str());
if (!file)
{
    // error

Open in new window


the getline has the advantage that the path to the file can contain spaces.

Sara
0
 

Author Comment

by:MEAM
ID: 36950416
Thank you, the user can now enter the filename correctly.

What I need now is help on how to perform a random access (using seekg) correctly, it is still not showing the red, blue and green colors for the image.

Thank you for your help.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 35

Accepted Solution

by:
sarabande earned 1000 total points
ID: 36950646
a seekg doesn't make sense if the file is a text file.  in a text file the lines have variable size and were terminated by linefeed (and carriage-control on windows platform) character. so you can't actually calculate where an RGB triple starts in a text file.

if the file is a binary file what the "raw stream format" seems to imply you should open the file with open flag std::ios::binary especially when you are at windows platform where text mode is default and any pair 0x0d 0x0a would be transformed to a single 0x0a (linefeed) when reading.
so use

file.open(filename.c_str(), std::ios::in | std::ios::binary);

Open in new window


to specify a binary read.

the formula "(y * image_x + x) * 3" would calculate the byte position within the file for a point (x, y).

if  (x, y) is for example (20, 50) the position would be

    (50*100 + 20)*3 = (5020)*3 = 15060

that is 15,000 bytes for the rgb-triples of row 0 to 49 (50 rows with 100 pixels and 3 bytes each)  plus the 60 bytes for the pixels 0 to 19 in row 50.

if you do a seekg on that location you can read 3 bytes from there.

for that read you need an object of RGB structure.

RGB pixel;

Open in new window


and the read it from file at the current position after seekg. so your current read from file is wrong (it reads only 100 bytes from begin) and at the wrong position. instead you need to exchange the 'data' argument in the read by '(char*)&pixel' and the size argument by sizeof(pixel). the cast to char* is necessary cause the read expects a char buffer and not a RGB buffer.

finally you could access the colors read by using the RGB members for example pixel.red

Sara
 
0
 

Author Comment

by:MEAM
ID: 36952844
The only part im having trouble now is with seekg.  How should the seekg statement be?
Thank you.
0
 
LVL 35

Expert Comment

by:sarabande
ID: 36953920
your seekg statement looks fine. you only need to calculate loc correctly (the formula minhvc has posted is wrong, you have to take the one specified in your assignment) and move the seekg call after opening the file in binary mode.

the seekg has two arguments. the first is the fileposition in bytes relative to the place specified with the second argument. that argument is an enumeration with three possible constants: ios::beg means relative to begin of file. ios::cur means relative to current file position (what would be used if you already read some parts and want to skip some other part) and ios::end means relative from end-of-file. the latter is used often for evaluating log files where the youngest lines are at end.

Sara
0
 

Author Comment

by:MEAM
ID: 36959783
Yes. The problem was with the loc formula. I changed it and it worked correctly. Thank you very much for your help.
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
Article by: evilrix
Looking for a way to avoid searching through large data sets for data that doesn't exist? A Bloom Filter might be what you need. This data structure is a probabilistic filter that allows you to avoid unnecessary searches when you know the data defin…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.
Suggested Courses

864 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question