I have an 720x576 picture saved row by row in an unsigned char luma[414720] and I need to display a centered picture with size 640x480.
My question is:
What is the most efficient way to selectively access to the data saved in one buffer using just one for cycle?
Thanks for your answers.
Petr Duga
Try this:
newLuma is the new pic to be displayed.
int i= 0;
char newLuma[640*480];
int rowStart = (576 - 480)/2 -1 ;
int colStart = (720 - 640)/2 -1 ;
for ( i = 0; i < 480; i++)
{
memcpy(newLuma[i*640], luma[720*(rowStart + i) + colStart], 640);
}
Related
Im working on resizing bitmap image and converting bitmap image to 8-bit (grayscale). But I have the problem that when I convert 32-bit image to 8-bit image, the result has another color overlay while it works perfectly on 24-bit. I guess the cause is in the alpha color. but I dont know where the problem exactly is.
This is my code to generate 8-bit palette color and write it after DIB part:
char* palette = new char[1024];
for (int i = 0; i < 256; i++) {
palette[i * 4] = palette[i * 4 + 1] = palette[i * 4 + 2] = (char)i;
palette[i * 4 + 3] = 255;
}
fout.write(palette, 1024);
delete[] palette;
As I said, my code works perfectly on 24-bit. In 32-bit the color is still kept after resizing, but when converting to 8-bit, it will look like this:
expected image (when converted from 24-bit) //
unexpected image (when converted from 32-bit)
This is how I get the colors and save it to srcPixel[]:
int i = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int index = getIndex(width, x, y);
srcPixel[index].A = srcBMP.pImageData[i];
i += alpha;
srcPixel[index].B = srcBMP.pImageData[i++];
srcPixel[index].G = srcBMP.pImageData[i++];
srcPixel[index].R = srcBMP.pImageData[i++];
}
i += padding;
}
And this is the code I converted it by getting average of 4 colors A, B, G and R from that srcPixel[]:
int i = 0;
for (int y = 0; y < dstHeight; y++) {
for (int x = 0; x < dstWidth; x++) {
int index = getIndex(dstWidth, x, y);
dstBMP.pImageData[i++] = (srcPixel[index].A + srcPixel[index].B + srcPixel[index].G + srcPixel[index].R) / 4;
}
i += dstPadding;
}
If I remove and skip all alpha bytes in my code, when converting my image is still like that and I will have another problem is when resizing, my image will have another color overlay like the problem when converting to 8-bit: resizing without alpha channel.
If I skip the alpha channel while getting average (change into dstBMP.pImageData[i++] = (srcPixel[index].B + srcPixel[index].G + srcPixel[index].R) / 3, there is almost nothing different, the overlay still exists.
If I remove palette[i * 4 + 3] = 255; or doing anything with it, the result is still not affected.
Thank you very much.
You add alpha channel to the color and that's why it becomes brighter. From here I found that opaque is 255 and transparent 0 - therefore you add another channel which is set to 'white' to your result.
Remove alpha channel from your equation and see if I'm right.
If I have vtkImageData of size 100x100x5, is there a quick way of getting the 3rd image in the array (i.e. the 3rd 100x100 image in the 5 image array)? All I have found so far is:
uint16_t* newIm = static_cast<uint16_t*>(newImData->GetScalarPointer());
uint16_t* num;
int index = 0;
int frameNum = 3;
for (int y = col-1; y >= 0 ; y--)
{
for (int x = 0; x < row; x++)
{
num = static_cast<uint16_t*>(imData->GetScalarPointer(x,y,frameNum));
newIm[index] = num[0];
index++;
}
}
Where imData comes from a different function in my program.
I'm trying to avoid the double for loop because its not very efficient. Does VTK have an easier way of copying the 3rd 100x100 element?
You can use the vtkExtractVOI filter to extract out a subsection of your vtkImageData. Note that although you are thinking of your image as 5 100x100 images, in VTK it is a single 5x100x100 3-d image.
To select a 2-d Z slice out of a 3-d image, you'd do something like this:
vtkSmartPointer<vtkExtractVOI> extractVOI =
vtkSmartPointer<vtkExtractVOI>::New();
extractVOI->SetInputConnection(source->GetOutputPort());
extractVOI>SetVOI(0, row-1, 0, col-1, z, z);
extractVOI->Update();
vtkImageData* extracted = extractVOI->GetOutput();
See this ExtractVOI example and the vtkExtractVOI documentation:
https://vtk.org/Wiki/VTK/Examples/Cxx/ImageData/ExtractVOI
https://vtk.org/doc/nightly/html/classvtkExtractVOI.html
During the encoding process with x265 encoder (https://x265.readthedocs.org/en/default/api.html) I want to write image pixel values (specifically values of Y channel) into .txt file after a new image is encoded (not important why). For that, I'm using 'planes' variable of class x265_picture:
x265_picture* pic_out; # variable where encoded image is to be stored
... # encoding process
uint8_t *plane = (uint8_t*)pic_out->planes[0];
uint32_t pixelCount = x265_picturePlaneSize(pic_out->colorSpace, m_param->sourceWidth, m_param->sourceHeight, 0);
ofstream out_file("out_file.txt");
for (uint32_t j = 0; j < pixelCount; j++) # loop for all pixels
{
int pix_val = plane[j];
out << pix_val;
}
ofstream.close()
But when I reconstruct the output data into image, I get
instead of
or another example:
instead of
(color is not important, the "stripes" are the concern)
In the output file there seem to be intervals of data in (apparently) correct order (let's say 89,90,102,98,...) followed always by long sequence of equal numbers (eg. 235,235,235,235... or 65,65,65,65...), that "create" the stripes. Could someone please tell me what I'm missing?
thanks guys, just solved this...the key is using 'src += srcStride':
ofstream out_file("out_file.txt");
int srcStride = pic_out->stride[0] / sizeof(pixel);
uint8_t* src = (uint8_t*) pic_out->planes[0];
for (int y = 0; y < m_param->sourceHeight; y++, src += srcStride)
{
for (int x = 0; x < m_param->sourceWidth; x++)
out_file << (int)(src[x]) << ",";
}
out_file.close();
I am working on the implementation of functions for an already written image processing program. I am given explanations of functions, but not sure how they are designating pixels of the image.
In this case, I need to flip the image horizontally, i.e., rotates 180 degrees around the vertical axis
Is this what makes the "image" i am to flip?
void Image::createImage(int width_x, int height_y)
{
width = width_x;
height = height_y;
if (pixelData!=NULL)
freePixelData();
if (width <= 0 || height <= 0) {
return;
}
pixelData = new Color* [width]; // array of Pixel*
for (int x = 0; x < width; x++) {
pixelData[x] = new Color [height]; // this is 2nd dimension of pixelData
}
}
I do not know if all the functions I have written are correct.
Also, the Image class calls on a Color class
So to re-ask: what am I "flipping" here?
Prototype for function is:
void flipLeftRight();
As there is no input into the function, and I am told it modifies pixelData, how do I flip left to right?
A quick in place flip. Untested, but the idea is there.
void flipHorizontal(u8 *image, u32 width, u32 height)
{
for(int i=0; i < height; i++)
{
for(int j=0; j < width/2; j++)
{
int sourceIndex = i * width + j;
int destIndex = (i+1) * width - j - 1;
image[sourceIndex] ^= image[destIndex];
image[destIndex] ^= image[sourceIndex];
image[sourceIndex] ^= image[destIndex];
}
}
}
well, the simplest approach would be to read it 1 row at a time into a temporary buffer the same size as 1 row.
Then you could use something like std::reverse on the temporary buffer and write it back.
You could also do it in place, but this is the simplest approach.
EDIT: what i;ve described is a mirror, not a flip, to mirror you also need to reverse the order of the rows. Nothing too bad, to do that I would create a buffer the same size as the image, copy the image and then write it back with the coordinates adjusted. Something like y = height - x and x = width - x.
I am trying to take the imageData of image in this where w= width of image and h = height of image
for (int i = x; i < x+h; i++) //height of frame pixels
{
for (int j = y; j < y+w; j++)//width of frame pixels
{
int pos = i * w * Channels + j; //channels is 3 as rgb
// if any data exists
if (data->imageData[pos]>0) //Taking data (here is the problem how to take)
{
xPos += j;
yPos += i;
nPix++;
}
}
}
jeff7 gives you a link to a very old version of OpenCV. OpenCV 2.0 has a new C++ wrapper that is much better than the C++ wrapper mentioned in the link. I recommend that you read the C++ reference of OpenCV for information on how to access individual pixels.
Another thing to note is: you should have the outer loop being the loop in y-direction (vertical) and the inner loop be the loop in x-direction. OpenCV is in C/C++ and it stores the values in row major.
See good explanation here on multiple methods for accessing pixels in an IplImage in OpenCV.
From the code you've posted your problem lies in your position variable, you'd want something like int pos = i*w*Channels + j*Channels, then you can access the RGB pixels at
unsigned char r = data->imageData[pos];
unsigned char g = data->imageData[pos+1];
unsigned char b = data->imageData[pos+2];
(assuming RGB, but on some platforms I think it can be stored BGR).
uchar* colorImgPtr;
for(int i=0; i<colorImg->width; i++){
for(int j=0; j<colorImg->height; j++){
colorImgPtr = (uchar *)(colorImg->imageData) + (j*colorImg->widthStep + i-colorImg->nChannels)
for(int channel = 0; channel < colorImg->nChannels; channel++){
//colorImgPtr[channel] here you have each value for each pixel for each channel
}
}
}
There are quite a few methods to do this (the link provided by jeff7 is very useful).
My preferred method to access image data is the cvPtr2D method. You'll want something like:
for(int x = 0; x < width; ++x)
{
for(int y = 0; y < height; ++y)
{
uchar* ptr = cvPtr2D(img, y, x, NULL);
// blue channel can now be accessed with ptr[0]
// green channel can now be accessed with ptr[1]
// red channel can now be accessed with ptr[2]
}
}
(img is an IplImage* in the above code)
Not sure if this is the most efficient way of doing this etc. but I find it the easiest and simplest way of doing it.
You can find documentation for this method here.