I am trying to make a terrain using a height map image in OpenGL. As a experiment i use 4x4 pixel image. this is a zoomed screen shot. so you can see the pixels.
This is a part of my code.
ILubyte * image = ilGetData();
int bpp = ilGetInteger(IL_IMAGE_BPP);
std::cout << "BPP = " << bpp << std::endl;
for (int z=0; z < terrainHeight; ++z)
{
for (int x=0; x < terrainWidth; ++x)
{
pVertices[z*terrainWidth+x] = NxVec3(NxF32(x),
NxF32(image[z*terrainWidth+x]*bpp), NxF32(z));
}
}
for (int i=0; i < vertexCount; ++i)
{
std::cout << "x = " << pVertices[i].x << "\t y = "
<< pVertices[i].y << "\t z = " << pVertices[i].z << std::endl;
}
Then, i'm getting the following result.
I'm expecting the zero values(for y-coordinate) for (0,0), (1,1), (2,2) and (3,3). but the result is different. why i'm not getting the expected results ?
I think it should be image[(z*terrainWidth+x)*bpp] instead of image[z*terrainWidth+x]*bpp.
Related
I am trying to access the Texture Coordinate of a Cube model made in blender.
for (int i = 0; i < mMesh->mNumVertices; i++) {
std::cout << mMesh->mTextureCoords[i][0].x << " " << mMesh->mTextureCoords[i][0].y << std::endl;
}
Why is this happening.
The application window launches but the red color background doesnt display.
And the first coords also get printed 0 1
How do i solve this.
Removing this code doesn't lead to a crash.
This should be:
for (int i = 0; i < mMesh->mNumVertices; i++)
{
std::cout << mMesh->mTextureCoords[0][i].x << " " << mMesh->mTextureCoords[0][i].y << std::endl;
}
Looks like you messed up the first and second array arguments. Also, it is good practice to check if the mesh has texture coordinates or not. Then the code becomes
if (mMesh->HasTextureCoords(0)) //HasTextureCoords is an assimp function
{
for (int i = 0; i < mMesh->mNumVertices; i++)
{
std::cout << mMesh->mTextureCoords[0][i].x << " " << mMesh- >mTextureCoords[0][i].y << std::endl;
}
}
I am using reactphysics3d library https://github.com/DanielChappuis/reactphysics3d
I am trying to create a square pyramid as a polyhedron mesh - 4 outer triangular faces and two base triangular faces.
I am able to successfully create the polygon vertex array, but I am having problems with the polyhedron creation stage.
I am following the progression of shape creation as outlined in the user manual.
I would appreciate help with this!
Thanks
This is my code - I tried using a triangular pyramid (triangle base with triangle faces) to create a triangular mesh and was able to do so. I was then able to create a concave shape.
However, I want to create a convex shape using a polyhedron mesh for a triangle pyramid with a square base.
Any advice would be appreciated!
//array of 5 points, 3 coordinates
float vertices[15];
for(int k=0; k<5; k++){
std::string vert = "v" + std::to_string(k);
vertices[3*k] = j3["data"]["vertices"][vert]["x"];
vertices[3*k+1] = j3["data"]["vertices"][vert]["y"];
vertices[3*k+2] = j3["data"]["vertices"][vert]["z"];
std::cout << std::setprecision(8);
std::cout << "added " << vertices[3*k] << "to index" << 3*k << std::endl;
std::cout << "added " << vertices[3*k+1] << "to index" << 3*k+1 << std::endl;
std::cout << "added " << vertices[3*k+2] << "to index" << 3*k+2 << std::endl;
}
//6 triangle faces
int indices[18];
//each face is defined through vertices (ccw)
//face1
indices[0] = 0; indices[1] = 2; indices[2] = 1;
//face2
indices[3] = 0; indices[4] = 2; indices[5] = 3;
//face3
indices[6] = 0; indices[7] = 4; indices[8] = 3;
//face4
indices[9] = 0; indices[10] = 1; indices[11] = 4;
//face5
indices[12] = 1; indices[13] = 2; indices[14] = 4;
//face6
indices[15] = 4; indices[16] = 2; indices[17] = 3;
rp3d::PolygonVertexArray::PolygonFace* polygonFaces = new rp3d::PolygonVertexArray::PolygonFace[6];
rp3d::PolygonVertexArray::PolygonFace* face = polygonFaces;
//each face has 3 indices
//6 triangles
for (int f=0; f<6; f++){
face->indexBase = f*3;
face->nbVertices = 3;
}
std::cout << "created polygon faces" << std::endl;
//create the polygon vertex array
rp3d::PolygonVertexArray* pva = new rp3d::PolygonVertexArray(5, vertices, sizeof(float), indices, sizeof(int), 6, polygonFaces, rp3d::PolygonVertexArray::VertexDataType::VERTEX_FLOAT_TYPE, rp3d::PolygonVertexArray::IndexDataType::INDEX_INTEGER_TYPE);
std::cout << "polygon vertex array created" << std::endl;
//create the polyhedron mesh
rp3d::PolyhedronMesh* pMesh = new rp3d::PolyhedronMesh(pva);
std::cout << "polyhedron mesh created" << std::endl;
//create the convex mesh collision shape
rp3d::ConvexMeshShape* convexMesh = new rp3d::ConvexMeshShape(pMesh);
std::cout << "convex mesh shape created" << std::endl;
i think you forget a face++ in the faces loop
I am doing some image processing using ITK and then using VTK to print the results in a .png format however, the output image is always black.
Currently, I am converting itk::Image to vtk::vtkImageData using the itk::ImagetoVTKImageFilter(typedeffed to ITKtoVTKFilterType in my code).
ITKtoVTKFilterType::Pointer itk2vtkGray = ITKtoVTKFilterType::New();
itk2vtkGray->SetInput(grayBinary); //grayBinary is of type itk::Image<unsigned short, 2>
itk2vtkGray->Update();
vtkSmartPointer<vtkImageData> grayVTK = vtkSmartPointer<vtkImageData>::New();
grayVTK->SetExtent(extent);
grayVTK->SetSpacing(m_spacing);
grayVTK->SetScalarTypeToUnsignedShort();
grayVTK->SetNumberOfScalarComponents(1);
grayVTK->AllocateScalars();
grayVTK->DeepCopy(static_cast<vtkImageData*>(itk2vtkGray->GetOutput()));
//grayVTK = itk2vtkGray->GetOutput();
I have even confirmed that my VTK ImageData contains values of either 255 or 0 using the following code.
int *dims = grayVTK->GetDimensions();
std::cout << "Dims: " << " x: " << dims[0] << " y: " << dims[1] << " z: " << dims[2] << std::endl;
std::cout << "Number of points: " << grayVTK->GetNumberOfPoints() << std::endl;
std::cout << "Number of cells: " << grayVTK->GetNumberOfCells() << std::endl;
for (int y = 0; y < dims[1]; y++)
{
for (int x = 0; x < dims[0]; x++)
{
unsigned short *pixel = static_cast<unsigned short*>(grayVTK->GetScalarPointer(x,y,0));
std::cout << "PIXEL LOC/VAL "<< y*dims[0] + x << " " << pixel[0] <<std::endl;
}
std::cout << std::endl;
}
I then go on to do an ImageCast to ensure the type of the data is unsignedShort.
vtkSmartPointer<vtkImageCast> cast2 = vtkSmartPointer<vtkImageCast>::New();
cast2->SetInput(grayVTK);
cast2->SetOutputScalarTypeToUnsignedShort();
cast2->ClampOverflowOn();
cast2->Update();
Then finally I use vtkPNGwriter to output the .png files. Notice that I have tried to output both the actual vtkImageData as well as output from the ImageCastFilter.
vtkSmartPointer<vtkPNGWriter> writer =
vtkSmartPointer<vtkPNGWriter>::New();
writer->SetFileName(filename.toStdString().c_str());
writer->SetInputConnection(cast2->GetOutputPort());
//writer->SetInput(grayVTK); I have tried to method as well but to no success
writer->Write();
However, the .png output is always black. Does anyone know what I am doing wrong.
For future reference it seems that many PNG readers do not display 16 bit data. Hence the casting I was doing to unsigned short at the end should have rather been to char.
vtkSmartPointer<vtkImageCast> cast2 = vtkSmartPointer<vtkImageCast>::New();
cast2->SetInput(grayVTK);
cast2->SetOutputScalarTypeToChar();
cast2->ClampOverflowOn();
cast2->Update();
I want to extract RGB from each pixel in QImage. Ideally, I want to use the img.bits() function.
QImage img;
if( img.load("Red.jpg") )
{
uchar *bits = img.bits();
for (int i = 0; i < 12; i++)
{
std::cout << (int) bits[i] << std::endl;
}
}
How to manipulate the returned bits? I expected all red because the picture is a pure red image created in Paint. However, I get 36, 27, 237, 255, 36 etc...
QImage img( "Red.jpg" );
if ( false == img.isNull() )
{
QVector<QRgb> v = img.colorTable(); // returns a list of colors contained in the image's color table.
for ( QVector<QRgb>::const_iterator it = v.begin(), itE = v.end(); it != itE; ++it )
{
QColor clrCurrent( *it );
std::cout << "Red: " << clrCurrent.red()
<< " Green: " << clrCurrent.green()
<< " Blue: " << clrCurrent.blue()
<< " Alpha: " << clrCurrent.alpha()
<< std::endl;
}
}
However this example above does returns the color table. Color table does not includes same colors twice. They will be added once in order of appearance.
If you want to get each pixels color, you can use next lines:
for ( int row = 1; row < img.height() + 1; ++row )
for ( int col = 1; col < img.width() + 1; ++col )
{
QColor clrCurrent( img.pixel( row, col ) );
std::cout << "Pixel at [" << row << "," << col << "] contains color ("
<< clrCurrent.red() << ", "
<< clrCurrent.green() << ", "
<< clrCurrent.blue() << ", "
<< clrCurrent.alpha() << ")."
<< std::endl;
}
Reference for bits() says:
Returns a pointer to the first pixel data. This is equivalent to scanLine(0).
So if you check reference for scanLine()
If you are accessing 32-bpp image data, cast the returned pointer to QRgb* (QRgb has a 32-bit size) and use it to read/write the pixel value. You cannot use the uchar* pointer directly, because the pixel format depends on the byte order on the underlying platform. Use qRed(), qGreen(), qBlue(), and qAlpha() to access the pixels.
One other option would probably be pixel() member function.
Hope that helps.
One of the problems with using the bits() function is that you need to know the format of the original image. You should convert it to RGB by using convertToFormat.
img = img.convertToFormat(QImage::Format_RGB888);
Now, when you call bits(), the data will be in the RGB format with the proper data alignment.
uchar *bits = img.bits();
for (int i = 0; i < (img.width() * img.height() * 3); i++)
{
std::cout << (int) bits[i] << std::endl;
}
In Qt 5.6 was introduced QColor QImage::pixelColor(int x, int y) method, so you can directly get color information from image pixel.
I've already asked this question, but that was about FreeImage. Now I'm trying to do the same thing with ImageMagick (to be more correct, with Magick++).
All I need is to get the RGB value of pixels in an image with the ability to print it out onto the screen. I asked this in the ImageMagick forum, but it seems there is nobody there. :-( Can anybody help, please?
Version 6 API
Given an "Image" object, you have to request a "pixel cache", then work with it. Documentation is here and here:
// load an image
Magick::Image image("test.jpg");
int w = image.columns();
int h = image.rows();
// get a "pixel cache" for the entire image
Magick::PixelPacket *pixels = image.getPixels(0, 0, w, h);
// now you can access single pixels like a vector
int row = 0;
int column = 0;
Magick::Color color = pixels[w * row + column];
// if you make changes, don't forget to save them to the underlying image
pixels[0] = Magick::Color(255, 0, 0);
image.syncPixels();
// ...and maybe write the image to file.
image.write("test_modified.jpg");
Version 7 API
Access to pixels has changed in version 7 (see: porting), but low-level access is still present:
MagickCore::Quantum *pixels = image.getPixels(0, 0, w, h);
int row = 0;
int column = 0;
unsigned offset = image.channels() * (w * row + column);
pixels[offset + 0] = 255; // red
pixels[offset + 1] = 0; // green
pixels[offset + 2] = 0; // blue
#Sga's answer didn't work for me, I'm using the ImageMagick-7.0.7-Q8 (8 bit depth) library.
Here's how I did it, to scan an image pixel by pixel and output each one's RGB value:
// "InitializeMagick" called beforehand!
void processImage()
{
std::ifstream fin;
std::stringstream fs;
fs << "/img.png";
std::cout << "Opening image \"" << fs.str() << "\".." << std::endl;
try
{
Image img;
img.read( fs.str() );
int imgWidth = img.columns();
int imgHeight = img.rows();
std::cout << "Image width: " << imgWidth << std::endl;
std::cout << "Image height: " << imgHeight << std::endl;
std::cout << "Image channels: " << img.channels() << std::endl;
img.modifyImage();
for ( int row = 0; row <= imgHeight; row++ )
{
for ( int column = 0; column <= imgWidth; column++ )
{
ColorRGB px = img.pixelColor( column, row );
std::cout << "Pixel " << column << "," << row << " R: " << px.red() << " G: " << px.green() <<
" B: " << px.blue() << std::endl;
}
}
}
catch ( Magick::Exception & error )
{
std::cerr << "Caught Magick++ exception: " << error.what() << std::endl;
}
fin.close(); // Close the file
}