Reading an image file in C/C++ [closed] - c++

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I need to read an image file in C/C++. It would be very great, if some one can post the code for me.
I work on gray scale images and the images are JPEG. I would like to read the images into a 2D array which will make my work easy.

If you decide to go for a minimal approach, without libpng/libjpeg dependencies, I suggest using stb_image and stb_image_write, found here.
It's as simple as it gets, you just need to place the header files stb_image.h and stb_image_write.h in your folder.
Here's the code that you need to read images:
#include <stdint.h>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
int main() {
int width, height, bpp;
uint8_t* rgb_image = stbi_load("image.png", &width, &height, &bpp, 3);
stbi_image_free(rgb_image);
return 0;
}
And here's the code to write an image:
#include <stdint.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
#define CHANNEL_NUM 3
int main() {
int width = 800;
int height = 800;
uint8_t* rgb_image;
rgb_image = malloc(width*height*CHANNEL_NUM);
// Write your code to populate rgb_image here
stbi_write_png("image.png", width, height, CHANNEL_NUM, rgb_image, width*CHANNEL_NUM);
return 0;
}
You can compile without flags or dependencies:
g++ main.cpp
Other lightweight alternatives include:
lodepng to read and write png files
jpeg-compressor to read and write jpeg files

You could write your own by looking at the JPEG format.
That said, try a pre-existing library like CImg, or Boost's GIL. Or for strictly JPEG's, libjpeg. There is also the CxImage class on CodeProject.
Here's a big list.

Check out Intel Open CV library ...

Check this thread out: read and write image file.
Also, have a look at this other question at Stackoverflow.

corona is nice. From the tutorial:
corona::Image* image = corona::OpenImage("img.jpg", corona::PF_R8G8B8A8);
if (!image) {
// error!
}
int width = image->getWidth();
int height = image->getHeight();
void* pixels = image->getPixels();
// we're guaranteed that the first eight bits of every pixel is red,
// the next eight bits is green, and so on...
typedef unsigned char byte;
byte* p = (byte*)pixels;
for (int i = 0; i < width * height; ++i) {
byte red = *p++;
byte green = *p++;
byte blue = *p++;
byte alpha = *p++;
}
pixels would be a one dimensional array, but you could easily convert a given x and y position to a position in a 1D array. Something like pos = (y * width) + x

Try out the CImg library. The tutorial will help you get familiarized. Once you have a CImg object, the data() function will give you access to the 2D pixel buffer array.

Check out the Magick++ API to ImageMagick.

Related

Can't display a PNG using Glut or OpenGL

Code is here:
void readOIIOImage( const char* fname, float* img)
{
int xres, yres;
ImageInput *in = ImageInput::create (fname);
if (! in) {return;}
ImageSpec spec;
in->open (fname, spec);
xres = spec.width;
yres = spec.height;
iwidth = spec.width;
iheight = spec.height;
channels = spec.nchannels;
cout << "\n";
pixels = new float[xres*yres*channels];
in->read_image (TypeDesc::FLOAT, pixels);
long index = 0;
for( int j=0;j<yres;j++)
{
for( int i=0;i<xres;i++ )
{
for( int c=0;c<channels;c++ )
{
img[ (i + xres*(yres - j - 1))*channels + c ] = pixels[index++];
}
}
}
in->close ();
delete in;
}
Currently, my code produces JPG files fine. It has the ability to read the file's information, and display it fine. However, when I try reading in a PNG file, it doesn't display correctly at all. Usually, it kind of displays the same distorted version of the image in three separate columns on the display. It's very strange. Any idea why this is happening with the given code?
Additionally, the JPG files all have 3 channels. The PNG has 2.
fname is simply a filename, and img is `new float[3*size];
Any help would be great. Thanks.`
Usually, it kind of displays the same distorted version of the image in three separate columns on the display. It's very strange. Any idea why this is happening with the given code?
This reads a lot like the output you get from the decoder is in row-planar format. Planar means, that you get individual rows one for every channel one-after another. The distortion and the discrepancy between number of channels in PNG and apparent count of channels are likely due to alignment mismatch. Now you didn't specify which image decoder library you're using exactly, so I can't look up information in how it communicates the layout of the pixel buffer. I suppose you can read the necessary information from ImageSpec.
Anyway, you'll have to rearrange your pixel buffer rearrangement loop indexing a bit so that consecutive row-planes are interleaved into channel-tuples.
Of course you could as well use a ready to use imagefile-to-OpenGL reader library. DevIL is thrown around a lot, but it's not very well maintained. SOIL seems to be a popular choice these days.

What is the "easiest" way to find the number of dark pixels of a jpeg? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I'm a first year engineering student and I'm working on a end of term project. Due to tight deadlines, I would like to avoid rummaging through image processing libraries. We (my group mates) need to find the easiest implementable method to get an integer for the number of dark pixels from an image. I have read many other posts regarding image processing, but they are much more complicated than we need. Is there an easy way to do this? It is important that it is easy because this is only a small part of our project and there can't be too much time committed to this.
As for languages, I would prefer to use C++.
On a side note, any exceptional help given would be cited in our report (just mention the name you want to be cited as and you'll go down in history). It would also give us time to sleep. Sleep is to engineering students what cake is to fat kids.
Here is it done in Qt (not image processing but application library)
#include <QImage>
#include <QColor>
uint countDarkPixels(QString filename, quint8 threshold) {
QImage img(filename);
uint darkPixels = 0;
for (int x = 0; x < img.width(); ++x) {
for (int y = 0; y < img.height(); ++y) {
QColor color(img.pixel(x, y));
if (color.toHsl().lightness() < threshold) darkPixels++;
}
}
return darkPixels;
}
Works for other formats besides JPG too. It uses conversion to HSL which may not be very fast, but you said "easy" not "fast".
There are two stages to this:
Load an image from a file.
Determine how many pixels in that image are "dark".
The first stage isn't too difficult - you could either use a pre-existing library, such as DevIL or FreeImage, or write your own - this and this should be enough to get you started.
Once you've loaded the image into your program somehow, you'll need to loop over the pixel data and count the number of "dark" pixels. Let's say you have an image structure that looks like this:
typedef struct
{
int w;
int h;
unsigned char *data;
} image_s;
For simplicity, let's make the following assumptions:
The image is stored in 24-bit, RGB format, so that each pixel is represented as three unsigned bytes like this: RGBRGBRGB.
A "dark" pixel is one where (R+G+B)/3 < 10
Given the above, you would simply need to loop through each pixel within the image structure like so:
int count_dark_pixels(image_s *img)
{
int dark_pixels, i;
for (dark_pixels = 0, i = 0; i < img->w * img->h; ++i)
{
int r = img->data[(i*3)+0];
int g = img->data[(i*3)+1];
int b = img->data[(i*3)+2];
if ((r+g+b)/3 < 10) { ++dark_pixels; }
}
return dark_pixels;
}
Uncompress the jpeg, get the Y channel pixel data (these values are the luminosity of each pixel), count the dark pixels in that. I don't think you need the U and V channels, these are used to reconstruct the colour information.
Working RGB may be a pain, but it all depends on what you mean by a 'dark' pixel.
JPEG images are usually encoded using the YCbCr color space. Rather than Red, Green, Blue the three components are Darkness, Blueness, and redness. The Y component is then a black and white version of the color image.
You can then determine the darkness of any point by examining the value of the Y component of the image. You can set some threshold to determine a dark pixel.

Raw RGB values to JPEG

I have an array with raw RGB values in it, and I need to write these values to a JPEG file. Is there an easy way to do this?
I tried:
std::ofstream ofs("./image.JPG", std::ios::out | std::ios::binary);
for (unsigned i = 0; i < width * height; ++i) {
ofs << (int)(std::min(1.0f, image[i].x) * 255) << (int)(std::min(1.0f, image[i].y) * 255) << (int)(std::min(1.0f, image[i].z) * 255);
}
but the format isn't recognized.
If you're trying to produce an image file you might look at Netpbm. You could write the intermediate format (PBM or PAM) fairly simply from what you have. There are then a large number of already written programs that will generate many types of images from your intermediate file.
WOH THERE!
JPEG is MUCH more complicated than raw RBG values. You are going to need to use a library, like LIBJPEG, to store the data as JPEG.
If you wrote it yourself you'd have to:
Convert from RGB to YCbCr
Sample the image
Divide into 8x8 blocks.
Perform the DCT on each block.
Run-length/huffman encode the values
Write these values in properly formatted JPEG blocks.
You could use Boost GIL: it's free, portable (it's part of Boost libraries), usable across a broad spectrum of operating systems (including Windows).
Popular Linux and Unix distributions such as Fedora, Debian and NetBSD include pre-built Boost packages.
The code is quite simple:
#include <boost/gil/extension/io/jpeg_io.hpp>
const unsigned width = 320;
const unsigned height = 200;
// Raw data.
unsigned char r[width * height]; // red
unsigned char g[width * height]; // green
unsigned char b[width * height]; // blue
int main()
{
boost::gil::rgb8c_planar_view_t view =
boost::gil::planar_rgb_view(width, height, r, g, b, width);
boost::gil::jpeg_write_view("out.jpg", view);
return 0;
}
jpeg_write_view saves the currently instantiated view to a jpeg file specified by the name (throws std::ios_base::failure if it fails to create the file).
Remember to link your program with -ljpeg.

Can any one Help me out in Drawing a rectangle in an image? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions must demonstrate a minimal understanding of the problem being solved. Tell us what you've tried to do, why it didn't work, and how it should work. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Guys I a new programmer in C++, please can you help me out in writing a program for drawing a blue colored rectangle in Visual C++ in a bitmap 24bit colored image without using OpenCV.
Also in VS C++ I'm not able to get a header graphics.h instead what shud i use.
I have to draw a rectangle in the image not the line
Here is my code in VS-C++ which only shows a black line at the bottom:
void copy_Header(FILE *,FILE *);
void main()
{
FILE *src; int offset; int width, height;
fopen_s(&src,"jaguar.bmp","rb");
FILE *dest;
fopen_s(&dest,"rect_image.bmp","wb");
fseek(src,10,SEEK_SET);
fread(&offset,4,1,src);
fseek(src,18,SEEK_SET);
fread(&width,4,1,src);
fseek(src,22,SEEK_SET);
fread(&height,4,1,src);
copy_Header(src,dest);
fseek(src,offset,SEEK_SET);
fseek(dest,offset,SEEK_SET);
unsigned char x=(unsigned char)fgetc(src);
double r,g,b,z[3];
int i;
unsigned char ch[3];
b=ch[0]=fgetc(src);
g=ch[1]=fgetc(src);
r=ch[2]=fgetc(src);
for (int j=0;j<4;j++)
{
for(; offset<width; offset++)
{
z[0]=b;
z[1]=0;
z[2]=0;
fputc(z[0],dest);
fputc(z[1],dest);
fputc(z[2],dest);
}
}
fseek(src,4096,SEEK_SET);
fseek(dest,4096,SEEK_SET);
unsigned char y= (unsigned char)fgetc(src);
while(!feof(src))
{
fputc(y,dest);
y=(unsigned char)fgetc(src);
}
fclose(src);
fclose(dest);
puts("Image Copied");
_getch();
}
void copy_Header(FILE *srcImage,FILE *dstImage)
{
unsigned char *ptrc= (unsigned char *)malloc(54*sizeof(char));
fseek(srcImage,0,SEEK_SET);
fseek(dstImage,0,SEEK_SET);
fread(ptrc,54,1,srcImage);
fwrite(ptrc,54,1,dstImage);
}
Thanx in advance.
image size is of 1024 by 1024 and is 24 bit bitmap file.
Let's break the problem.
First problem: how do you relate a pixel coordinate to its position in a file?
In other words, given a RGB pixel with coordinates (x,y), where is it located on the file?
Let's consider that it has WIDTH width and HEIGHT height. Since it has 3 channels - Red, Green, and Blue - and considering each channel has 1 byte, each pixel will have 3 bytes in size. A BMP file is just a matrix of pixels, organized line by line, so each line will have then 3*WIDTH bytes.
The x coordinate will then tell how many lines will be skipped, and y will point to the pixel in the current line. In other words:
seek_position= x*(3*WIDTH) + 3*y
With this relation, you can now write a function like
int mat2seek(int x,int y){
//converts a xy coordinate system to seek position
return x*(3*WIDTH) + 3*y + BMP_HEADER_SIZE;
}
where BMP_HEADER_SIZE is self explaining
Second problem: now that you know how to convert a (x,y) coordinate system to seek system, what is the algorithm of drawing a rectangle?
Such algorithm is a lot easier to make in (x,y) coordinate than seek coordinates:
for (int x = xini; x< xend; x++)
for (int y=yini; y<yend; y++){
int seek=mat2seek(x,y);
//do the magic...
}

How to rescale an image with c/c++ in windows?

What's the shortest solution in c/c++?
You didn't give too much information so I will go with StretchBlt
For an example, see Scaling an Image.
I won't give you a demo, but try to do the following:
create destination bitmap that is of your desired size
select that bitmap into device context
StretchBlt original bitmap onto device context previously mentioned
unselect bitmap from the device context
That recipe above needs no any library then GDI that is already present in windows. And if you plan to draw something in c++, you should get familiarity with that library anyway.
Look here:
http://www.ucancode.net/Free-VC-Draw-Print-gdi-example-tutorial/GDI-Object-VC-MFC-Tutorial.htm
or here:
http://www.olivierlanglois.net/clover.html
if you don't plan to use MFC for the task.
One of the easiest rescale algorithms is nearest-neighbour. Suppose your are rescaling from an image in an array of size x1 y1 to another size x2 y2. The idea is to find the nearest integer offset in original array to each target array position. So your rescale algorithm ends for something like this:
const int x1 = 512;
const int y1 = 512;
const int x2 = 64;
const int y2 = 64;
unsigned char orig[x1*y1]; /* Original byte array */
unsigned char target[x2*y2] /* Target byte array */
for(int i=0;i<x2;i++)
{
for(int j=0;j<y2;j++)
{
xoff = (i*x2)/x1;
yoff = (j*y2)/y1;
target[i+j*x2] = orig[xoff+yoff*x1]
}
}
This will give a blocky resized image. For better results you can use average or any other fancier polynomial based interpolators.
What libraries are you using? How do you represent images? Most image libraries should already be able to do that, e.g. Qt has QPixmap with scaled() and GDI has StretchBlt.
Or you could code it yourself with bicubic interpolation.