Simple-iphone-image-processing source code question, what does this do - c++

I am going through the source code for the above project and I don't understand the following lines of code can anyone help explain it to me please? I am trying to get the code to work with color images as it currently only works with greyscale images. I have the main methods working however the filters only get applied to the top quarter of the returned images.
//In the heeder file.
inline uint8_t* operator[](const int rowIndex) {
return m_yptrs[rowIndex];
}
//in the .mm file
void Image::initYptrs() {
m_yptrs=(uint8_t **) malloc(sizeof(uint8_t *)*m_height);
for(int i=0; i<m_height; i++) {
m_yptrs[i]=m_imageData+i*m_width;
}
}
From my understanding it looks like it is creating a a reference to the pixels in the images however i don't understand this line of code.
m_yptrs[i]=m_imageData+i*m_width;
Thanks in advance.

Image::initYptrs() initializes an array of pointers to the beginning of each row of the image.
The line in question should probably read
m_yptrs[i] = m_imageData + i*BPP*m_width;
Where BPP is bytes per pixel (e.g. 3 for RGB, 4 for RGBA images).

Related

SDL putting lots of pixel data onto the screen

I am creating a program that allows you to view fractals like the Mandelbrot or Julia set. I would like to render them as quickly as possible. I would love a way to put an array of uint8_t pixel values onto the screen. The array is formatted like this...
{r0,g0,b0,r1,g1,b1,...}
(A one dimensional array or RGB color values)
I know I have the proper data because before I just set individual points and it worked...
for(int i = 0;i < height * width;++i) {
//setStroke and point are functions that I made that together just draw a colored point
r.setStroke(data[i*3],data[i*3+1],data[i*3+2]);
r.point(i % r.window.w,i / r.window.w);
}
This is a pretty slow operation especially if the screen is big (which I would like it to be)
Is there any faster way to just put all the data onto the screen.
I tried doing something like this
void* pixels;
int pitch;
SDL_Texture* img = SDL_CreateTexture(ren,
SDL_GetWindowPixelFormat(win),SDL_TEXTUREACCESS_STREAMING,window.w,window.h);
SDL_LockTexture(img, NULL, &pixels, &pitch);
memcpy(pixels, data, window.w * 3 * window.h);
SDL_UnlockTexture(img);
SDL_RenderCopy(ren,img,NULL,NULL);
SDL_DestroyTexture(img);
I have no idea what I'm doing so please have mercy
Edit (thank you for comments :))
So here is what I do now
SDL_Texture* img = SDL_CreateTexture(ren, SDL_PIXELFORMAT_RGB888,SDL_TEXTUREACCESS_STREAMING,window.w,window.h);
SDL_UpdateTexture(img,NULL,&data[0],window.w * 3);
SDL_RenderCopy(ren,img,NULL,NULL);
SDL_DestroyTexture(img);
But I get this Image... which is not what it should look like
I am thinking that my data is just formatted wrong, right now it is formatted as an array of uint8_t in RGB order. Is there another way I should be formatting it (note I do not need an alpha channel)

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.

Writing a tif pixel by pixel using LibTiff?

Is it possible to create a new tif by iterating pixel by pixel and setting the RGB values for each pixel?
Let me explain what I'm attempting to do. I'm trying to open an existing tif, read it using TIFFReadRGBAImage, take the RGB values given by TIFFGetR/TIFFGetG/TIFFGetB, subtract them from 255, take those new values and use them to write each pixel one by one. In the end I'd like to end up with the original image and a new "complement" image that would be like a negative of the original.
Is there a way to do this using LibTiff? I've gone over the documentation and searched around Google but I've only seen very short examples of TIFFWriteScanline which provide so little lines of code/context/comments that I cannot figure out how to implement it in the way that I'd like it to work.
I'm still fairly new to programming so if someone could please either point me to a thorough example with plenty of explanatory comments or help me out directly with my code, I would appreciate it greatly. Thank you for taking the time to read this and help me learn.
What I have so far:
// Other unrelated code here...
//Invert color values and write to new image file
for (e = height - 1; e != -1; e--)
{
for (c = 0; c < width; c++)
{
red = TIFFGetR(raster[c]);
newRed = 255 - red;
green = TIFFGetG(raster[c]);
newGreen = 255 - green;
blue = TIFFGetB(raster[c]);
newBlue = 255 - blue;
// What to do next? Is this feasible?
}
}
// Other unrelated code here...
Full code if you need it.
I went back and looked at my old code. It turns out that I didn't use libtiff. Nevertheless you are on the right track. You want something like;
lineBuffer = (char *)malloc(width * 3) // 3 bytes per pixel
for all lines
{
ptr = lineBuffer
// modify your line code above so that you make a new line
for all pixels in line
{
*ptr++ = newRed;
*ptr++ = newGreen;
*ptr++ = newBlue
}
// write the line using libtiff scanline write
write a line here
}
Remember to set the tags appropriately. This example assumes 3 byte pixels. TIFF also allows for separate planes of 1 byte per pixel in each plane.
Alternately you can also write the whole image into a new buffer instead of one line at a time.

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.

Convert RGB IplImage to 3 arrays

I need some C++/pointer help. When I create an RGB IplImage and I want to access i,j I use the following C++ class taken from: http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv-intro.html
template<class T> class Image
{
private:
IplImage* imgp;
public:
Image(IplImage* img=0) {imgp=img;}
~Image(){imgp=0;}
void operator=(IplImage* img) {imgp=img;}
inline T* operator[](const int rowIndx) {
return ((T *)(imgp->imageData + rowIndx*imgp->widthStep));}
};
typedef struct{
unsigned char b,g,r;
} RgbPixel;
typedef struct{
float b,g,r;
} RgbPixelFloat;
typedef Image<RgbPixel> RgbImage;
typedef Image<RgbPixelFloat> RgbImageFloat;
typedef Image<unsigned char> BwImage;
typedef Image<float> BwImageFloat;
I've been working with CUDA so sometimes I have to put all the data into an array, I like to keep every channel in its own array, seems easier to handle the data that way. So I would usually do something like this:
IplImage *image = cvLoadImage("whatever.tif");
RgbImageFloat img(image);
for(int i = 0; i < exrIn->height; i++)
{
for(int j = 0; j < exrIn->width; j++)
{
hostr[j*data->height+i] = img[i][j].r;
hostg[j*data->height+i] = img[i][j].g;
hostb[j*data->height+i] = img[i][j].b;
}
}
I would then copy my data to the device, do some stuff with it, get it back to the host and then loop, yet again, through the array assigning the data back to the IplImage and saving my results.
It seems like I'm looping to much there has to be a faster way to do this with pointers but I'm lost, there has to be a more efficient way to do it. Is there a way I can simply use a pointer for every channel? I tried doing something like this but it didn't work:
float *hostr = &img[0][0].r
float *hostg = &img[0][0].b
float *hostb = &img[0][0].g
Any suggestions? Thanks!
EDIT:
Thanks everyone for answering. Maybe I wasn't very clear on my question. I am familiar on how to access channels and their data. What I am interested is in increasing the performance and efficiency of completely copying data off the IplImage to a standard array, more along the lines of what csl said so far. The problem I see is that the way data in an IplImage is arranged is "rgbrgbrgbrgb".
Firstly, if you're comfortable with C++, you should consider using OpenCV 2.0 which does away with different data types for images and matrices (IplImage* and CvMat*) and uses one structure (Mat) to handle both. Apart from automatic memory management and a truckload of useful routines to handle channels, etc. and some MATLAB-esque ones as well, it's really fun to use.
For your specific problem, you access the channels of an IplImage* with Mat, like this:
IplImage *image = cvLoadImage("lena.bmp");
Mat Lena(image);
vector<Mat> Channels;
split(Lena,Channels);
namedWindow("LR",CV_WINDOW_AUTOSIZE);
imshow("LR",Channels[0]);
waitKey();
Now you have the copies of each channel in the vector Channels.
If you don't want to use OpenCV2.0 and extract channels, note the following. OpenCV orders multi-channel images in the following manner:
x(1,1,1) x(1,1,2) x(1,1,3) x(1,2,1) x(1,2,2) x(1,2,3) ...
where x(i,j,k) = an element in row i of column j in channel k
Also, OpenCV pads it's images .. so don't forget to jump rows with widthStep which accounts for these padding gaps. And along the lines of what csl said, increase your row pointer in the outer loop (using widthStep) and increment this pointer to access elements in a row.
NOTE:
Since you're using 2.0 now, you can bypass IplImage* with Mat Lena = imread("Lena.bmp");.
There is room for a lot of improvement here. So much, that you should read up on how people access bitmaps.
First of all, increase memory locality as much as possible. This will increase cache hits, and performance. I.e., don't use three separate arrays for each color channel. Store each together, since you probably will be working mostly on pixels.
Secondly, don't do that y*width calculation for every pixel. When done in an inner loop, it consumes a lot of cycles.
Lastly, if you just want a complete copy of the image, then you could simply do a memcpy(), which is very fast. I couldn't deduce if you converted from floats to integers, but if not, use memcpy() for non-overlapping regions.
If you wonder how you can do this with pointers (kind of pseudo-code, and also not tested):
float *dst = &hostg[0][0];
RgbPixelFloat *src = &img[0][0];
RgbPixelFloat *end = &img[HEIGHT][WIDTH] + 1;
// copy green channel of whole image
while ( src != end ) {
*dst = src->g;
++dst;
++src;
}