How can I write a qt application to display a dcm image? - linux

I have found a way using vtk to display dcm image. But vtk is too much for what I want, I only want to display a dcm image. The dcmtk will process the dcm image for me.
So is there an easy way for me to display dcm image?
Thanks in advance.

The smallest learning curve and code requirement will likely be to use Grass Roots DICOM. (http://gdcm.sourceforge.net/wiki/index.php/Main_Page) This library will link to Qt and give you a quick way to load an image. The only thing to remember is that a DICOM image file does not contain an image that Qt (or anything else) can display directly. You have to load the DICOM data and convert the image to display it.
These are the lines to add to the project file. Note that the paths will have to match your machine and versions, not mine;
#INCLUDEPATH += /usr/local/include/gdcm-2.4/
#LIBS += -L"/usr/local/lib/" -lgdcmCommon -lgdcmDICT -lgdcmDSED -lgdcmIOD -lgdcmMEXD -lgdcmMSFF -lgdcmjpeg12 -lgdcmjpeg16 -lgdcmopenjpeg -lgdcmjpeg8
#LIBS += -L"/usr/local/lib/" -lgdcmcharls -lexpat -lgdcmzlib
This is an example converter, once you have the dicom image loaded, it will convert it to a Qt QImage.
bool imageConverters::convertToFormat_RGB888(gdcm::Image const & gimage, char *buffer, QImage* &imageQt)
{
unsigned int dimX;
unsigned int dimY;
int photoInterp;
const unsigned int* dimension = gimage.GetDimensions();
if (dimension == 0)
{
dimX = 800;
dimY = 600;
}
else
{
dimX = dimension[0];
dimY = dimension[1];
}
gimage.GetBuffer(buffer);
photoInterp = gimage.GetPhotometricInterpretation();
qDebug() << "photo interp = " << photoInterp;
qDebug() << "pixel format = " << gimage.GetPixelFormat();
// Let's start with the easy case:
if( photoInterp == gdcm::PhotometricInterpretation::RGB )
{
if( gimage.GetPixelFormat() != gdcm::PixelFormat::UINT8 )
{
return false;
}
unsigned char *ubuffer = (unsigned char*)buffer;
// QImage::Format_RGB888 13 The image is stored using a 24-bit RGB format (8-8-8).Format_RGB888 Format_ARGB32
imageQt = new QImage((unsigned char *)ubuffer, dimX, dimY, 3*dimX, QImage::Format_RGB888);
//imageQt = &imageQt->rgbSwapped();
}
else
if( photoInterp == gdcm::PhotometricInterpretation::MONOCHROME2 ||
photoInterp == gdcm::PhotometricInterpretation::MONOCHROME1
)
{
if( gimage.GetPixelFormat() == gdcm::PixelFormat::UINT8 || gimage.GetPixelFormat() == gdcm::PixelFormat::INT8
|| gimage.GetPixelFormat() == gdcm::PixelFormat::UINT16)
{
// We need to copy each individual 8bits into R / G and B:
unsigned char *ubuffer = new unsigned char[dimX*dimY*3];
unsigned char *pubuffer = ubuffer;
for(unsigned int i = 0; i < dimX*dimY; i++)
{
*pubuffer++ = *buffer;
*pubuffer++ = *buffer;
*pubuffer++ = *buffer++;
}
imageQt = new QImage(ubuffer, dimX, dimY, QImage::Format_RGB888);
}
else
if( gimage.GetPixelFormat() == gdcm::PixelFormat::INT16 )
{
// We need to copy each individual 16bits into R / G and B (truncate value)
short *buffer16 = (short*)buffer;
unsigned char *ubuffer = new unsigned char[dimX*dimY*3];
unsigned char *pubuffer = ubuffer;
for(unsigned int i = 0; i < dimX*dimY; i++)
{
// Scalar Range of gdcmData/012345.002.050.dcm is [0,192], we could simply do:
// *pubuffer++ = *buffer16;
// *pubuffer++ = *buffer16;
// *pubuffer++ = *buffer16;
// instead do it right:
*pubuffer++ = (unsigned char)std::min(255, (32768 + *buffer16) / 255);
*pubuffer++ = (unsigned char)std::min(255, (32768 + *buffer16) / 255);
*pubuffer++ = (unsigned char)std::min(255, (32768 + *buffer16) / 255);
buffer16++;
}
imageQt = new QImage(ubuffer, dimX, dimY, QImage::Format_RGB888);
}
else
{
std::cerr << "Pixel Format is: " << gimage.GetPixelFormat() << std::endl;
return false;
}
}
else
{
std::cerr << "Unhandled PhotometricInterpretation: " << gimage.GetPhotometricInterpretation() << std::endl;
return false;
}
return true;
}

#john elemans
If I use the code that you gave me, It seems to be worng. My image's pixel format is UINT16, so the program will execute the following sentences.
unsigned char *ubuffer = new unsigned char[dimX*dimY*3];
unsigned char *pubuffer = ubuffer;
for(unsigned int i = 0; i < dimX*dimY; i++)
{
*pubuffer++ = *buffer;
*pubuffer++ = *buffer;
*pubuffer++ = *buffer++;
}
imageQt = new QImage(ubuffer, dimX, dimY, QImage::Format_RGB888);
But after the converting, the result is not right.
The original image is like this:before
And this is the image which has been converted:after
The result proves that the code isn't right. I also have tried other ways. One of the codes that I have tried is this:
short *buffer16 = (short*)buffer;
unsigned char *ubuffer = new unsigned char[dimX*dimY*3];
unsigned char *pubuffer = ubuffer;
for (unsigned int i = 0; i < dimX*dimY; i++)
{
*pubuffer++ = *buffer16;
*pubuffer++ = *buffer16;
*pubuffer++ = *buffer16;
buffer16++;
}
imageQt = new QImage(ubuffer, dimX, dimY, QImage::Format_RGB888);
After I used this code to convert the image, I almost believed that I have succeeded. But the result is like this: sorry, I don't have the enough reputation the post more than 2 links.
I only want to convert DICOM image to bitmap, but I don't know how.
At last, thank you for your help.

Related

i2c read register on /dev/i2c

I have written a small test program that reads a temperature register on a LSM6DSO chip and display the temperature correctly after reading the /dev/i2c (IOCTL call) so far so good but whilst reading the chip through iio_generic_buffer() (which relies on the sysfs filesystem) correctly updates the register and returns slightly different values at each read, my program keeps on displaying the same value over and
over.
So question is: What am I missing? And why doesn't the register updates itself with the next temperature?
int main()
{
...
for (i = 0; i <= 100; i++) {
i2c_read_1_byte(0x6a, 0xf, result); // reading 1 byte of register 0xf (WHO_AM_I)
printf("Read %#02X\n", result[0]);
i2c_read_1_byte(0x6a, 0x20, result);
templ = result[0];
i2c_read_1_byte(0x6a, 0x21, result);
temph = result[0];
printf("Read temph %#02X\n", temph);
printf("Read templ %#02X\n", templ);
res = (((unsigned short)temph << 8) & 0xFF00) | templ;
printf("res: 0x%x\n", res);
}
int i2c_read_1_byte(unsigned char slave_addr, unsigned char reg, unsigned char *result)
{
unsigned char outbuf[1], inbuf[1];
struct i2c_msg msgs[2];
struct i2c_rdwr_ioctl_data msgset[1];
msgs[0].addr = slave_addr;
msgs[0].flags = 0;
msgs[0].len = 1;
msgs[0].buf = outbuf;
msgs[1].addr = slave_addr;
msgs[1].flags = I2C_M_RD | I2C_M_STOP;
msgs[1].len = 1;
msgs[1].buf = inbuf;
msgset[0].msgs = msgs;
msgset[0].nmsgs = 2;
outbuf[0] = reg;
inbuf[0] = 0;
*result = 0;
if (ioctl(i2c_fd, I2C_RDWR, &msgset) < 0) {
perror("ioctl(I2C_RDWR) in i2c_read");
return -1;
}
*result = inbuf[0];
return 0;
}
Solved, was a timing problem, so started with usleep and ended polling the DTA_RDY register ...

Import FBX Vertex And Index Buffer To DirectX 11

Ok, I'm still trying to figure out how to correctly import FBX vertex and index buffer into DirectX 11. I wrote a controller for doing that and passing the vertex and index buffer to the DX11 renderer, the output should look like a cube but it is not, I only see triangles that don't make sense.
The code is shown below. I did multiply the Z values by -1, though.
What do I need to modify to get the render right?
#pragma once
#include "Array.h"
#include "Vector.h"
#include "fbxsdk.h"
#include <assert.h>
#include "constants.h"
class FbxController
{
public:
FbxController();
~FbxController();
void Import(const char* lFilename)
{
lImporter = FbxImporter::Create(lSdkManager, "");
bool lImportStatus = lImporter->Initialize(lFilename, -1, lSdkManager->GetIOSettings());
if (!lImportStatus) {
printf("Call to FbxImporter::Initialize() failed.\n");
printf("Error returned: %s\n\n", lImporter->GetStatus().GetErrorString());
exit(-1);
}
lScene = FbxScene::Create(lSdkManager, "myScene");
lImporter->Import(lScene);
FbxNode* lRootNode = lScene->GetRootNode();
int childCount = lRootNode->GetChildCount();
FbxNode *node1 = lRootNode->GetChild(0);
const char* nodeName1 = node1->GetName();
fbxsdk::FbxMesh *mesh = node1->GetMesh();
int cpCount1 = mesh->GetControlPointsCount();
fbxsdk::FbxVector4 *controlPoints = mesh->GetControlPoints();
for (int i = 0; i < cpCount1; i++)
{
fbxsdk::FbxVector4 cpitem = controlPoints[i];
printf("%d, %d, %d, %d", cpitem[0], cpitem[1], cpitem[2], cpitem[3] );
VERTEXPOSCOLOR vpc;
vpc.Color.x = 0.5f;
vpc.Color.y = 0.5f;
vpc.Color.z = 0.5f;
vpc.Position.x = cpitem[0];
vpc.Position.y = cpitem[1];
vpc.Position.z = cpitem[2] * -1.0f;
m_vertices.add(vpc);
}
int pvCount = mesh->GetPolygonVertexCount();
int polyCount = mesh->GetPolygonCount();
for (int i = 0; i < polyCount; i++)
{
int polyItemSize = mesh->GetPolygonSize(i);
assert(polyItemSize == 3);
for (int j = 0; j < polyItemSize; j++)
{
int cpIndex = mesh->GetPolygonVertex(i, j);
m_indices.add(cpIndex);
float x = controlPoints[cpIndex].mData[0];
float y = controlPoints[cpIndex].mData[1];
float z = controlPoints[cpIndex].mData[2];
}
}
fbxsdk::FbxMesh *mesh2;
bool isT = mesh->IsTriangleMesh();
FbxNode *node2 = lRootNode->GetChild(1);
FbxNode *node3 = lRootNode->GetChild(2);
//lImporter->Destroy();
}
Array<VERTEXPOSCOLOR> GetVertexPosColors()
{
return m_vertices;
}
Array<unsigned int> getIndexBuffer()
{
return m_indices;
}
protected:
FbxManager *lSdkManager;
FbxIOSettings *ios;
FbxImporter *lImporter;
bool lImportStatu;
FbxScene *lScene;
private:
Array<VERTEXPOSCOLOR> m_vertices;
Array<unsigned int> m_indices;
};
I think you have some problems in your index buffer creation.
You simply gives an index for each vertex, and index buffer not working that way.
let me know if you solve this.

Get distance from kinect depth image using ubuntu 12.04 LTS and opencv

I found out from one site that it is possible to find distance from the raw depth video output of the Kinect through the 2 bytes assigned to a particular pixel as shown in this link - tutorial. Based on this I written a code to find out the distance of the middle point form the Kinect sensor.
I compiled it and ran the code on Ubuntu and it is showing the output. The output is showing some values as distance. The values are coming around 150->1147. I hope it is showing the distance in mm.
But I am not sure, if it is right or wrong. I am providing the code below. Is my code working correctly or do I need to make some changes?
Code:
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <stdio.h>
#include "libfreenect_cv.h"
int getDist(IplImage *depth){
int x = depth->width/2;
int y = depth->height/2;
printf("width= %d and height %d \n",x,y);
int d = depth->imageData[x*2+y*640*2+1];
printf("1st value is %d \n",d);
d= d << 8;
d= d+depth->imageData[x*2+y*640*2];
return d;
}
IplImage *GlViewColor(IplImage *depth)
{
static IplImage *image = 0;
if (!image) image = cvCreateImage(cvSize(640,480), 8, 3);
unsigned char *depth_mid = (unsigned char*)(image->imageData);
int i;
for (i = 0; i < 640*480; i++) {
int lb = ((short *)depth->imageData)[i] % 256;
int ub = ((short *)depth->imageData)[i] / 256;
switch (ub) {
case 0:
depth_mid[3*i+2] = 255;
depth_mid[3*i+1] = 255-lb;
depth_mid[3*i+0] = 255-lb;
break;
case 1:
depth_mid[3*i+2] = 255;
depth_mid[3*i+1] = lb;
depth_mid[3*i+0] = 0;
break;
case 2:
depth_mid[3*i+2] = 255-lb;
depth_mid[3*i+1] = 255;
depth_mid[3*i+0] = 0;
break;
case 3:
depth_mid[3*i+2] = 0;
depth_mid[3*i+1] = 255;
depth_mid[3*i+0] = lb;
break;
case 4:
depth_mid[3*i+2] = 0;
depth_mid[3*i+1] = 255-lb;
depth_mid[3*i+0] = 255;
break;
case 5:
depth_mid[3*i+2] = 0;
depth_mid[3*i+1] = 0;
depth_mid[3*i+0] = 255-lb;
break;
default:
depth_mid[3*i+2] = 0;
depth_mid[3*i+1] = 0;
depth_mid[3*i+0] = 0;
break;
}
}
return image;
}
int main(int argc, char **argv)
{
while (cvWaitKey(100) != 27) {
IplImage *image = freenect_sync_get_rgb_cv(0);
if (!image) {
printf("Error: Kinect not connected?\n");
return -1;
}
cvCvtColor(image, image, CV_RGB2BGR);
IplImage *depth = freenect_sync_get_depth_cv(0);
if (!depth) {
printf("Error: Kinect not connected?\n");
return -1;
}
cvShowImage("RGB", image);
//int d = getDist(depth);
printf("value is %d \n",getDist(depth));
cvShowImage("Depth", GlViewColor(depth));//GlViewColor(depth)
}
cvDestroyWindow("RGB");
cvDestroyWindow("Depth");
//cvReleaseImage(image);
//cvReleaseImage(depth);
return 0;
}
The code seems to be fine. Scale the image of range (150-1147) to (0-255) and display it as gray scale. It will help you to have a better understanding of the image. Doing so will result in nearest object being dark-Colored and farthest being light-colored. It would be better than using GlViewColor function.

Problems with SDL Audio (No output)

I'm facing some problems with understanding how the SDL audio callback works.
I have this simple code, which should generate a simple square wave:
#include "SDL.h"
#include "SDL_audio.h"
#include <stdlib.h>
#include <math.h>
SDL_Surface *screen;
SDL_AudioSpec spec;
Uint32 sound_len=512;
Uint8 *sound_buffer;
int sound_pos = 0;
int counter;
unsigned int phase_delta=600;
unsigned int phase;
unsigned char out;
//Initialization
void init_sdl (void)
{
if (SDL_Init (SDL_INIT_VIDEO|SDL_INIT_AUDIO) < 0)
exit (-1);
atexit (SDL_Quit);
screen = SDL_SetVideoMode (640, 480, 16, SDL_HWSURFACE);
if (screen == NULL)
exit (-1);
}
//Generates a new sample and outputs it to the audio card
void Callback (void *userdata, Uint8 *stream, int len)
{
Uint8 *waveptr;
//Generates a new sample
phase+=phase_delta;
if ((phase>>8)<127) out=255; else out=0;
//End
//Output the current sample to the audio card
waveptr = sound_buffer;
SDL_MixAudio(stream, waveptr, 1, SDL_MIX_MAXVOLUME);
}
void play (void)
{
sound_buffer = new Uint8[512];
sound_len= 512;
spec.freq = 22050;
spec.format = AUDIO_S16SYS;
spec.channels = 1;
spec.silence = 0;
spec.samples = 512;
spec.padding = 0;
spec.size = 0;
spec.userdata = 0;
spec.callback = Callback;
if (SDL_OpenAudio (&spec, NULL) < 0)
{ //Throw an error
printf ("I don't think you like this: %s\n", SDL_GetError ());
exit (-1);
}
SDL_PauseAudio (0);//Start the audio
}
int main(int argc, char* argv[])
{
init_sdl ();
play ();
SDL_Delay (250);
return 0;
}
I know that the callback is not done right, because I have no idea how to output to the buffer. Each time the callback is called, the first part of the callback function code generates the new sample, and stores it in the variabile Out.
Can anyone here modify this code so that the new samples go from Out to the correct position in the audio buffer?
Also, I don't want to have the code modified in a very super-complex way just to generate the square wave - I have already taken care of that. The wave is generated correctly, each new sample appearing in the variable Out. I just need these samples to be routed correctly to the audio buffer.
You need to cast stream to a actual.format-appropriate datatype and then overwrite the values in stream with len / sizeof( <format's datatype> ) samples.
The square-wave will be kinda hard to hear because the given algorithm will only generate a brief high pulse every ~7.1 million samples (~5 minutes #22050Hz) when phase wraps around.
Try something like this:
#include <SDL.h>
#include <SDL_audio.h>
#include <iostream>
using namespace std;
//Generates new samples and outputs them to the audio card
void Callback( void* userdata, Uint8* stream, int len )
{
// the format of stream depends on actual.format in main()
// we're assuming it's AUDIO_S16SYS
short* samples = reinterpret_cast< short* >( stream );
size_t numSamples = len / sizeof( short );
const unsigned int phase_delta = 600;
static unsigned int phase = 0;
// loop over all our samples
for( size_t i = 0; i < numSamples; ++i )
{
phase+=phase_delta;
short out = 0;
if ((phase>>8)<127) out=SHRT_MAX; else out=0;
samples[i] = out;
}
}
int main( int argc, char* argv[] )
{
if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_AUDIO ) < 0 )
return -1;
atexit( SDL_Quit );
SDL_Surface* screen = SDL_SetVideoMode( 640, 480, 16, SDL_ANYFORMAT );
if( screen == NULL)
return -1;
SDL_AudioSpec spec;
spec.freq = 22050;
spec.format = AUDIO_S16SYS;
spec.channels = 1;
spec.samples = 4096;
spec.callback = Callback;
spec.userdata = NULL;
SDL_AudioSpec actual;
if( SDL_OpenAudio( &spec, &actual ) < 0 )
{
cerr << "I don't think you like this: " << SDL_GetError() << endl;
return -1;
}
if( spec.format != actual.format )
{
cerr << "format mismatch!" << endl;
return -1;
}
SDL_PauseAudio( 0 );
SDL_Event ev;
while( SDL_WaitEvent( &ev ) )
{
if( ev.type == SDL_QUIT )
break;
}
SDL_CloseAudio();
SDL_Quit();
return 0;
}

how to convert byte* into jpeg file in VC++

how to convert byte* into jpeg file in VC++
i am capturing Video samples and writing it as bmp files, but i want to write that video samples into jpeg file using MFC support in ATL COM.
Use libjpg. Download from: http://www.ijg.org/
From what it appears, you have the image data in a buffer pointed to by a byte object. Note, that the type actually is BYTE (all uppercase). If the data is in JPEG format already why don't you write that data out to a file (with a suitable '.jpg' or '.jpeg' extension) and try loading it with an image editor? Otherwise, you will need to decode that to raw format and encode in the JPEG format.
Or, you need to explain you problem in more detail, preferably with some code.
Raw image data to JPEG can be acheived by ImageMagick.
You may also try to use CxImage C++ class to save your stills to JPEG-encoded file.
There are some more Windows API oriented alternatives available on CodeProject, for instance CMiniJpegEncoder
It is even possible to render JPEG to file from Windows bitmap using libgd library if compiled with libjpeg support. Here is code of small extension function gdImageTrueColorAttachBuffer I developed for this purpose some time ago:
// libgd ext// libgd extension by Mateusz Loskot <mateusz at loskot dot net>
// Originally developed for Windows CE to enable direct drawing
// on Windows API Device Context using libgd API.
// Complete example available in libgd CVS:
// http://cvs.php.net/viewvc.cgi/gd/libgd/examples/windows.c?diff_format=u&revision=1.1&view=markup
//
gdImagePtr gdImageTrueColorAttachBuffer(int* buffer, int sx, int sy, int stride)
{
int i;
int height;
int* rowptr;
gdImagePtr im;
im = (gdImage *) malloc (sizeof (gdImage));
if (!im) {
return 0;
}
memset (im, 0, sizeof (gdImage));
#if 0
if (overflow2(sizeof (int *), sy)) {
return 0;
}
#endif
im->tpixels = (int **) malloc (sizeof (int *) * sy);
if (!im->tpixels) {
free(im);
return 0;
}
im->polyInts = 0;
im->polyAllocated = 0;
im->brush = 0;
im->tile = 0;
im->style = 0;
height = sy;
rowptr = buffer;
if (stride < 0) {
int startoff = (height - 1) * stride;
rowptr = buffer - startoff;
}
i = 0;
while (height--) {
im->tpixels[i] = rowptr;
rowptr += stride;
i++;
}
im->sx = sx;
im->sy = sy;
im->transparent = (-1);
im->interlace = 0;
im->trueColor = 1;
im->saveAlphaFlag = 0;
im->alphaBlendingFlag = 1;
im->thick = 1;
im->AA = 0;
im->cx1 = 0;
im->cy1 = 0;
im->cx2 = im->sx - 1;
im->cy2 = im->sy - 1;
return im;
}
void gdSaveJPEG(void* bits, int width, int height, const char* filename)
{
bool success = false;
int stride = ((width * 1 + 3) >> 2) << 2;
gdImage* im = gdImageTrueColorAttachBuffer((int*)bits, width, height, -stride);
if (0 != im)
{
FILE* jpegout = fopen(filename, "wb");
gdImageJpeg(im, jpegout, -1);
fclose(jpegout);
success = true;
}
gdImageDestroy(im);
return success;
}
I hope it helps.

Resources