Sorry for the basic question, I am just starting to use QImage for reading pixel data from an image file.
To understand the member functions, I tried to load an image file and tried to output the functions return values:
QString fileName = "pic1.bmp";
QImage myImage;
myImage.load( fileName );
std::cout << "width = " << myImage.width() << std::endl;
std::cout << "height = " << myImage.height() << std::endl;
std::cout << "dotspermeterX = " << myImage.dotsPerMeterX() << std::endl;
std::cout << "dotspermeterY = " << myImage.dotsPerMeterY() << std::endl;
QRectF myRect = myImage.rect();
std::cout << "rect = " << myRect.bottomLeft().x() << "," << myRect.bottomLeft().y()
<< " " << myRect.topRight().x() << "," << myRect.topRight().y() << std::endl;
The output I got was:
width = 858
height = 608
dotspermeterX = 4724
dotspermeterY = 4724
rect = 0,608 858,0
My questions are:
1. What is the difference between dots and pixels?
2. Does QImage work only with int pixels? Can't I read sub-pixel data for better precision?
To clarify my question, Following is a zoomed bitmap image of a diagonal line and I want to read all the small pixels/dots in this line. Is this possible?
As for the "dots per meter", you probably heard of "dots per inch" (or DPI). It's the same. If, for example, you have a 20 inch monitor with the horizontal resolution of X pixels, you will have Y "dots per inch" (or pixels per inch). If you then switch to a 40 inch monitor but with the same horizontal resolution X, then you have half the number of DPI, as the screen is now double as wide. So DPI (or PPI) can be seens as a measurement of the size of the pixels.
And no, I seriously doubt that QImage have any support for sub-pixel data.
Related
I notice that this simple ArrayFire program is causing loaded TIFF images to be heavily distorted:
#include <iostream>
#include <arrayfire.h>
int main( int argc, char** argv ) {
af::array img = af::loadImage( argv[1] );
double mn, mx;
unsigned idxn, idxx;
af::min( &mn, &idxn, img );
af::max( &mx, &idxx, img );
std::cout << "Image size = " << img.dims()[0] << ", " << img.dims()[1] << '\n';
std::cout << "Data type = " << img.type() << '\n';
std::cout << "Min = " << mn << " (at " << idxn << ")\n";
std::cout << "Max = " << mx << " (at " << idxx << ")\n";
af::saveImage( argv[2], img );
return 0;
}
I then compile and run on a simple (monochrome) image:
./a.out orig.tif out.tif
with the following output:
Image size = 256, 256
Data type = 0
Min = 0 (at 65535)
Max = 81.5025 (at 31356)
When I visualize these images I get the following result:
which of course is not what ArrayFire is expected to do; I would expect it to dump the exact same image out since I didn't make any changes to it. Unfortunately I don't know enough about the TIFF image format or the graphics backend of ArrayFire to understand what is going on. Am I doing something wrong while loading the image? (I followed the ArrayFire documentation for loadImage and saveImage).
I also tried using loadImageNative and saveImageNative alternatively, but the latter returns a 4-layer TIFF image while the original image is only a 1-layer TIFF.
Any help at all from ArrayFire experts would be great.
Thanks!
I'm trying to get the color of a pixel in a jpg image and all the tutorials I can find online say to use pixelpacket which doesnt exist anymore. searching and searching through google i've found that getvirtualpixels might be the new way but that doesnt seem to exist in the newest version either. so how do I get the color of pixels from an image with an image cache? I do not need to set any pixels btw.
Using windows10 and visual studio 2015
PixelPacket structures have been replaced with a pointer to Quantum data type. From Porting to ImageMagick Version 7, the key thing to understand is that a pixel can now have dynamic parts (or "traits" previously called as "channels").
ImageMagick version 7 supports any number of channels from 1 to 32 (and beyond) and simplifies access with a single method that returns an array of pixel channels of type Quantum.
You are now responsible for authoring code that handles deterministic (is that the right term?) pixel channels. For example...
Magick::Image rose("rose:");
const Magick::Quantum * q = rose.getConstPixels(5, 5, 1, 1);
size_t channel_length = rose.channels();
for (size_t k = 0; k < channel_length; k++ ) {
std::cout << "Channel " << k << " = ";
std::cout << q[k] << " of " << QuantumRange << std::endl;
}
/** Outputs
-------
Channel 0 = 13107 of 65535
Channel 1 = 12079 of 65535
Channel 2 = 11308 of 65535
*/
Without seeing your code, or understanding what your finial goal would be, I would guess that you really just want RGB info. If that's the case, the Magick::Image.getColor will work,
Magick::Image rose("rose:");
Magick::Color pixelColor = rose.pixelColor(5, 5);
std::cout << "Channel 0 = ";
std::cout << pixelColor.quantumRed() << " of " << QuantumRange << std::endl;
std::cout << "Channel 1 = ";
std::cout << pixelColor.quantumGreen() << " of " << QuantumRange << std::endl;
std::cout << "Channel 2 = ";
std::cout << pixelColor.quantumBlue() << " of " << QuantumRange << std::endl;
/** Outputs
-------
Channel 0 = 13107 of 65535
Channel 1 = 12079 of 65535
Channel 2 = 11308 of 65535
*/
But! Sometimes it's just easier to export the image data into a format you're already working with. For example, I might only need Green values as single-point float list.
Magick::Image rose("rose:");
Magick::PixelData pixelBlob(rose, "G", Magick::FloatPixel);
float * buffer = (float *)pixelBlob.data();
// ...
I have a large, complicated graphics view that takes a lot of processing to draw, and so I only want to redraw part of it (an OpenGL video display) each frame, leaving the rest (various child widgets etc) unchanged.
However, when I call update() with a QRegion, the paintEvent's region is the full size of the widget, so the whole screen gets redrawn every time. There doesn't appear to be any call to update() with no parameters (at least, not my version thereof)
What might be causing the paint event to have the full screen in it?
void GLGraphicsView::updateVideoRegion(const QRegion & r)
{
//this function called from outside...
LOG4CXX_DEBUG(_logger, "updateVideoRegion " << r.boundingRect().x() << " " << r.boundingRect().y() << " " << r.boundingRect().width() << " " << r.boundingRect().height());
update(r);
}
void GLGraphicsView::update()
{
LOG4CXX_DEBUG(_logger, "update(all)");
QGraphicsView::update();
}
void GLGraphicsView::update(const QRegion& region)
{
LOG4CXX_DEBUG(_logger, "update(region) " << region.boundingRect().x() << " " << region.boundingRect().y() << " " << region.boundingRect().width() << " " << region.boundingRect().height());
QGraphicsView::update(region);
}
void GLGraphicsView::paintEvent(QPaintEvent *e)
{
LOG4CXX_DEBUG(_logger, "repaint region " << e->region().boundingRect().x() << " " << e->region().boundingRect().y() << " " << e->region().boundingRect().width() << " " << e->region().boundingRect().height());
/* Do the rest of the painting */
}
Output:
updateVideoRegion 19 19 1446 568
update(region) 19 19 1446 568
repaint region 0 0 1920 1201
Edit:
I've also tried using updateScene(QList) instead of update(QRegion), with viewportUpdateMode set to SmartViewportUpdate, but the paintEvent's region is still the full size of the screen. The CacheMode is set to CacheNone, and setting it to CacheBackground causes the OpenGL stuff to not be displayed.
After further investigation, it appears that this is because I am using OpenGL - the 'fullUpdate' flag in updateScene is always set in this case - qgraphicsView has "accelerateScrolling = !isGlWidget" [in setupViewport, line 2759] and "fullUpdate = !d->accelerateScrolling" [in updateScene, line 2675]
I have raw pixel data that I want to output via the opencv cvShowImage() function.
I have the following code:
#include <opencv2/highgui/highgui.hpp>
// pdata is the raw pixel data as 3 uchars per pixel
static char bitmap[640*480*3];
memcpy(bitmap,pdata,640*480*3);
cv::Mat mat(480,640,CV_8UC3,bitmap);
std::cout << mat.flags << ", "
<< mat.dims << ", "
<< mat.rows << ", "
<< mat.cols << std::endl;
cvShowImage("result",&mat);
Which outputs:
1124024336, 2, 480, 640
to the console, but fails to output the image with cvShowImage(). Instead throwing an exception with the message:
OpenCV Error: Bad flag (parameter or structure field) (Unrecognized or unsupported array type) in cvGetMat
I suspect the problem is in the way I create the mat object, but I am having a very hard time finding any more specific information on how I am supposed to do that.
I don't think CV_8UC3 is enough of a description for it to render the array of data. Doesn't it have to know whether the data is RGB or YUY2, etc.? How do I set that?
Try cv::imshow("result", mat) instead of mixing the old C and new C++ APIs. I expect casting a Mat to a CvArr* is the source of the problem.
So, something like this:
#include <opencv2/highgui/highgui.hpp>
// pdata is the raw pixel data as 3 uchars per pixel
static char bitmap[640*480*3];
memcpy(bitmap,pdata,640*480*3);
cv::Mat mat(480,640,CV_8UC3,bitmap);
std::cout << mat.flags << ", "
<< mat.dims << ", "
<< mat.rows << ", "
<< mat.cols << std::endl;
cv::imshow("result", mat);
This question already has answers here:
C++ alignment when printing cout <<
(7 answers)
Closed 8 years ago.
I want output as per follows in C++:
name aabsd
Size in KB 170
Width and Height 512 512
cout<<"\n \t name "<<std::setw(15)<<filename;
cout<<" \n \t Size in KB "<<std::setw(10)<<size;
cout<< " \n \t Width and Height "<<std::setw(3)<<width<<" "<<height;
Values on right side should be aligned in same coloumn. I tried with setw() but it does not give me output aligned because my left side text is different.
Another answer that relies on purely C++ specific constructs.
#include <iostream>
#include <iomanip>
int main()
{
char const* filename = "abcd";
int size = 10;
double width = 20;
double height = 30;
// std::left says align the output to the left when writing the next field
// set::setw(20) says use 20 characters for the next field.
std::cout << std::left << std::setw(20) << "name" << filename << std::endl;
std::cout << std::left << std::setw(20) << "Size in KB" << size << std::endl;
std::cout << std::left << std::setw(20) << "Width and Height" << width << " " << height << std::endl;
return 0;
}
printf( "%-20s%-20s", "name", "aabsd" );
printf( "%-20s%-20d", "Size in KB", 170 );
printf( "%-20s%-20d %d", "Width and Height", 512, 512 );
-20%s will left justify 20 spaces
20%s will right justify 20 spaces
Try using \t to align the output to the next tab position.
printf("Name\t%s\n",name);
printf("Size in KB\t%d\n",size);
printf("Width and Height\t%d%d\n",width,height);
That will make the second column aligned, maybe you will need a second tab in one of them, but thats it.
Another way is to manually move the cursor to where you want it. This should do
SetCursorPos(xpos,ypos);
You need to include windows.h