I need to generate a series of CT DICOM images (512x512, MONOCHROME) using the GDCM library. Because of the structure of the application that I am working on, it is ideal for me to separately prepare gdcm::Image and gdcm::File instances for each image and at the end pass them on to gdcmImageWriter using the SetFile() and SetImage() methods.
The gdcmImageWriter::write() fails to write DICOM images. I have already looked at the source code of the VTKGDCMImageWriter class and this GDCM example for hints. It appears that the problem originates from some incompatibilities between gdcm::Image and gdcm::File instances (for instance, both classes contain information about the Photometric Interpretation of a DICOM image) that I pass on to gdcmImageWriter, but I am not sure exactly what those are.
The following simplified C++ code reproduces the error I have been getting:
#include <gdcmFile.h>
#include <gdcmImage.h>
#include <gdcmTag.h>
#include "gdcmDataElement.h"
#include "gdcmByteValue.h"
#include "gdcmPixelFormat.h"
#include "gdcmImageWriter.h"
#include "gdcmAnonymizer.h"
#include <iostream>
#include <string>
InitializeGDCMImage(gdcm::Image* imagePtr);
InitializeGDCMFile( gdcm::File* filePtr );
WriteFile( gdcm::Image* imagePtr , gdcm::File* filePtr , std::string fileName );
int main()
{
std::string fileName = "./TEST.dcm";
// Will be deleted by gdcm::writer.
gdcm::Image* imagePtr = new gdcm::Image;
gdcm::File* filePtr = new gdcm::File;
InitializeGDCMImage(imagePtr);
InitializeGDCMFile( filePtr );
WriteFile( imagePtr , filePtr , fileName );
return 0;
}
where,
void WriteFile( gdcm::Image* imagePtr , gdcm::File* filePtr , std::string fileName )
{
gdcm::ImageWriter* writer = new gdcm::ImageWriter;
writer->SetFileName( fileName.c_str() );
writer->SetImage( *imagePtr );
writer->SetFile( *filePtr );
if( !writer->Write() ){
std::cerr << "ERROR: Could not write to \"" << fileName << "\"" << std::endl;
}
delete writer;
}
WriteFile() sets gdcm::File and gdcm::Image and invokes write().
InitializeGDCMFile() modifies a few DICOM tags using gdcm::Anonymizer, and InitializeGDCMImage() sets the actual pixel values (skipped here for brevity).
void InitializeGDCMFile( gdcm::File* origianlFilePtr )
{
gdcm::File* filePtr = new gdcm::File;
gdcm::Anonymizer anon;
anon.SetFile( *filePtr );
anon.Replace( gdcm::Tag(0x0028,0x0002) , "1" ); //SamplesperPixel
anon.Replace( gdcm::Tag(0x0028,0x0004) , "MONOCHROME2" ); //PhotometricInterpretation
anon.Replace( gdcm::Tag(0x0028,0x0010) , "512" ); //Rows
anon.Replace( gdcm::Tag(0x0028,0x0011) , "512" ); //Columns
anon.Replace( gdcm::Tag(0x0028,0x0030) , "0.781\\0.781" ); //PixelSpacing
anon.Replace( gdcm::Tag(0x0028,0x1050) , "0" ); //WindowCenter
anon.Replace( gdcm::Tag(0x0028,0x1051) , "100" ); //WindowWidth
anon.Replace( gdcm::Tag(0x0028,0x1052) , "0" ); //RescaleIntercept
anon.Replace( gdcm::Tag(0x0028,0x1053) , "1" ); //RescaleSlope
*origianlFilePtr = *filePtr;
}
void InitializeGDCMImage(gdcm::Image* imagePtr)
{
imagePtr->SetPhotometricInterpretation( gdcm::PhotometricInterpretation::MONOCHROME2 );
imagePtr->SetNumberOfDimensions(2);
unsigned int dims[2]={512,512};
imagePtr->SetDimensions( dims );
imagePtr->SetSpacing( 0 , 1. );
imagePtr->SetSpacing( 1 , 1. );
imagePtr->SetIntercept(0.);
imagePtr->SetSlope(1.);
double dirCos[6]={1.,0.,0.,0.,1.,0.};
imagePtr->SetDirectionCosines( dirCos );
char *buffer = new char[512*512*sizeof(int16_t)];
imagePtr->SetPixelFormat( gdcm::PixelFormat::INT16 );
imagePtr->GetDataElement().SetByteValue( buffer , 512*512*sizeof(int16_t) );
imagePtr->GetPixelFormat().SetSamplesPerPixel(1);
delete[] buffer;
}
Related
I would like to compress a bunch of data in a buffer and write to a file such that it is gzip compatible. The reason for doing this is that I have multiple threads that can be compressing their own data in parallel and require a lock only when writing to the common output file.
I have some dummy code below based on the zlib.h docs for writing a gz compatible, but I get a gzip: test.gz: unexpected end of file when I try to decompress the output. Can anyone tell me what might be going wrong ?
Thank you
#include <cassert>
#include <fstream>
#include <string.h>
#include <zlib.h>
int main()
{
char compress_in[50] = "I waaaaaaaant tooooooo beeeee compressssssed";
char compress_out[100];
z_stream bufstream;
bufstream.zalloc = Z_NULL;
bufstream.zfree = Z_NULL;
bufstream.opaque = Z_NULL;
bufstream.avail_in = ( uInt )strlen(compress_in) + 1;
bufstream.next_in = ( Bytef * ) compress_in;
bufstream.avail_out = ( uInt )sizeof( compress_out );
bufstream.next_out = ( Bytef * ) compress_out;
int res = deflateInit2( &bufstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY );
assert ( res == Z_OK );
res = deflate( &bufstream, Z_FINISH );
assert( res == Z_STREAM_END );
deflateEnd( &bufstream );
std::ofstream outfile( "test.gz", std::ios::binary | std::ios::out );
outfile.write( compress_out, strlen( compress_out ) + 1 );
outfile.close();
return 0;
}
The length of the compressed data written to the output buffer is the space you provided for the output buffer minus the space remaining in the output buffer. So, sizeof( compress_out ) - bufstream.avail_out. Do:
outfile.write( compress_out, sizeof( compress_out ) - bufstream.avail_out );
Am working in vc++ and trying to load an xml file and load the entire data into a string but am not getting the results
char text[700] = {""};
TiXmlDocument doc( "'demotest.xml" );
bool loadOkay = doc.LoadFile();
if ( !loadOkay )
{
printf( "Could not load test file 'demotest.xml'. Error='%s'. Exiting.\n", doc.ErrorDesc() );
system("PAUSE");
exit( 1 );
}
printf( "** Demo doc read from disk: ** \n\n" );
printf( "** Printing via doc.Print **\n" );
//doc.Print( stdout );
{
printf( "** Printing via TiXmlPrinter **\n" );
TiXmlPrinter printer;
doc.Accept( &printer );
fprintf( stdout, "%s", printer.CStr() );
//upto this line its working fine in console. but when I convert this string am getting struck
wsprintf(text, "%s", (char*)printer.CStr());
AddLOG_message(text, 0, true);
}
Last two lines I should get the entire content of the xml including header, elements and values.
Please help.
I'd do it like this, with less C code, more C++ code and deprecating the risky char array of length magic number 700:
TiXmlPrinter printer;
doc.Accept( &printer );
doc.Print(); // simpler for stdout output
std::string text = printer.CStr(); // easier, safer this way
AddLOG_message( text.c_str(), 0, true );
This question already has answers here:
Unzip a zip file using zlib
(4 answers)
Closed 7 years ago.
Is there a simple example of how to unzip a .zip file and extract the files to a directory? I am currently using zlib, and while I understand that zlib does not directly deal with zip files, there seems to be several additional things in zlibs's "contrib" library. I noticed and read about "minizip", and after reading some documents and looking at some of the code, I do not see a simple example of how to unzip a .zip file and extract the files to a directory.
I would like to find a platform independent way of doing so, but if that is not possible then I need to find a way for windows and mac.
zlib handles the deflate compression/decompression algorithm, but there is more than that in a ZIP file.
You can try libzip. It is free, portable and easy to use.
UPDATE: Here I attach quick'n'dirty example of libzip, with all the error controls ommited:
#include <zip.h>
int main()
{
//Open the ZIP archive
int err = 0;
zip *z = zip_open("foo.zip", 0, &err);
//Search for the file of given name
const char *name = "file.txt";
struct zip_stat st;
zip_stat_init(&st);
zip_stat(z, name, 0, &st);
//Alloc memory for its uncompressed contents
char *contents = new char[st.size];
//Read the compressed file
zip_file *f = zip_fopen(z, name, 0);
zip_fread(f, contents, st.size);
zip_fclose(f);
//And close the archive
zip_close(z);
//Do something with the contents
//delete allocated memory
delete[] contents;
}
Minizip does have an example programs to demonstrate its usage - the files are called minizip.c and miniunz.c.
Update: I had a few minutes so I whipped up this quick, bare bones example for you. It's very smelly C, and I wouldn't use it without major improvements. Hopefully it's enough to get you going for now.
// uzip.c - Simple example of using the minizip API.
// Do not use this code as is! It is educational only, and probably
// riddled with errors and leaks!
#include <stdio.h>
#include <string.h>
#include "unzip.h"
#define dir_delimter '/'
#define MAX_FILENAME 512
#define READ_SIZE 8192
int main( int argc, char **argv )
{
if ( argc < 2 )
{
printf( "usage:\n%s {file to unzip}\n", argv[ 0 ] );
return -1;
}
// Open the zip file
unzFile *zipfile = unzOpen( argv[ 1 ] );
if ( zipfile == NULL )
{
printf( "%s: not found\n" );
return -1;
}
// Get info about the zip file
unz_global_info global_info;
if ( unzGetGlobalInfo( zipfile, &global_info ) != UNZ_OK )
{
printf( "could not read file global info\n" );
unzClose( zipfile );
return -1;
}
// Buffer to hold data read from the zip file.
char read_buffer[ READ_SIZE ];
// Loop to extract all files
uLong i;
for ( i = 0; i < global_info.number_entry; ++i )
{
// Get info about current file.
unz_file_info file_info;
char filename[ MAX_FILENAME ];
if ( unzGetCurrentFileInfo(
zipfile,
&file_info,
filename,
MAX_FILENAME,
NULL, 0, NULL, 0 ) != UNZ_OK )
{
printf( "could not read file info\n" );
unzClose( zipfile );
return -1;
}
// Check if this entry is a directory or file.
const size_t filename_length = strlen( filename );
if ( filename[ filename_length-1 ] == dir_delimter )
{
// Entry is a directory, so create it.
printf( "dir:%s\n", filename );
mkdir( filename );
}
else
{
// Entry is a file, so extract it.
printf( "file:%s\n", filename );
if ( unzOpenCurrentFile( zipfile ) != UNZ_OK )
{
printf( "could not open file\n" );
unzClose( zipfile );
return -1;
}
// Open a file to write out the data.
FILE *out = fopen( filename, "wb" );
if ( out == NULL )
{
printf( "could not open destination file\n" );
unzCloseCurrentFile( zipfile );
unzClose( zipfile );
return -1;
}
int error = UNZ_OK;
do
{
error = unzReadCurrentFile( zipfile, read_buffer, READ_SIZE );
if ( error < 0 )
{
printf( "error %d\n", error );
unzCloseCurrentFile( zipfile );
unzClose( zipfile );
return -1;
}
// Write data to file.
if ( error > 0 )
{
fwrite( read_buffer, error, 1, out ); // You should check return of fwrite...
}
} while ( error > 0 );
fclose( out );
}
unzCloseCurrentFile( zipfile );
// Go the the next entry listed in the zip file.
if ( ( i+1 ) < global_info.number_entry )
{
if ( unzGoToNextFile( zipfile ) != UNZ_OK )
{
printf( "cound not read next file\n" );
unzClose( zipfile );
return -1;
}
}
}
unzClose( zipfile );
return 0;
}
I built and tested it with MinGW/MSYS on Windows like this:
contrib/minizip/$ gcc -I../.. -o unzip uzip.c unzip.c ioapi.c ../../libz.a
contrib/minizip/$ ./unzip.exe /j/zlib-125.zip
I'm trying to achieve tail-like functionality in my Visual Studio 2008 C++ application. (i.e. show in real-time the changes to a file not owned by my process.)
/// name of the file to tail
std::string file_name_;
/// position of the last-known end of the file
std::ios::streampos file_end_;
// start by getting the position of the end of the file.
std::ifstream file( file_name_.c_str() );
if( file.is_open() )
{
file.seekg( 0, std::ios::end );
file_end_ = file.tellg();
}
/// callback activated when the file has changed
void Tail::OnChanged()
{
// re-open the file
std::ifstream file( file_name_.c_str() );
if( file.is_open() )
{
// locate the current end of the file
file.seekg( 0, std::ios::end );
std::streampos new_end = file.tellg();
// if the file has been added to
if( new_end > file_end_ )
{
// move to the beginning of the additions
file.seekg( 0, new_end - file_end_ );
// read the additions to a character buffer
size_t added = new_end - file_end_;
std::vector< char > buffer( added + 1 );
file.read( &buffer.front(), added );
// display the additions to the user
// this is always the correct number of bytes added to the file
std::cout << "added " << added << " bytes:" << std::endl;
// this always prints nothing
std::cout << &buffer.front() << std::endl << std::endl;
}
// remember the new end of the file
file_end_ = new_end;
}
}
While it always knows how many bytes have been added to the file, the read buffer is always empty.
What do I need to do to get the functionality I'm after?
Thanks,
PaulH
EDIT: nevermind. I got it sorted. I was using seekg() incorrectly. This is what I should have been doing:
if( new_end > file_end_ )
{
size_t added = new_end - file_end_;
file.seekg( -added, std::ios::end );
Thanks
On Linux you could look at inotify to be notified of changes to a file. It allows you to poll or select an inotify descriptor and get notified when a file or directory has changed.
Hey, hopefully this should be my last PTY-related question and I can move onto more exciting issues. (c;
Here's a set of small functions I have written for creating and reading/writing to a pty: http://pastebin.com/m4fcee34d The only problem is that they don't work! After I run the initializer and writeToPty( "ls -l" ) , 'output' from readFromPty is still empty.
Ubuntu, QT C++
EDITED: Ok, I can confirm all this stuff works except for the read loop. In the debuggers' locals/watchers tab it shows that the QString 'output' actually does get the right data put in it, but after it ( the read() ) runs out of characters from the output it runs and then hangs. What is going on and how can I fix it?
Thanks! (c:
#include <iostream>
#include <unistd.h>
#include <utmp.h>
#include <pty.h>
#include <QString>
#include <QThread>
// You also need libutil in your .pro file for this to compile.
class CMkPty
{
public:
CMkPty( int *writeChannel, int *readChannel );
~CMkPty();
int runInPty( char *command );
int writeToPty( char *input );
int readFromPty( QString output );
int m_nPid;
private:
int m_nMaster, m_nSlave, m_nPosition, m_nBytes;
char *m_chName;
void safe_print( char *s );
char m_output;
};
CMkPty::CMkPty( int *masterFD, int *slaveFD )
{
openpty( &m_nMaster, &m_nSlave, (char*)0, __null, __null );
m_nPid = fork();
*masterFD = m_nMaster;
*slaveFD = m_nSlave;
if( m_nPid == 0 )
{
login_tty( m_nSlave );
execl( "/bin/bash", "-l", (char*)0 );
return;
}
else if( m_nPid > 0 )
{
return;
}
else if( m_nPid < 0 )
{
std::cout << "Failed to fork." ;
return;
}
}
CMkPty::~CMkPty()
{
close( m_nMaster );
close( m_nSlave );
}
int CMkPty::writeToPty( char *szInput )
{
int nWriteTest;
write( m_nMaster, szInput, sizeof( szInput ) );
nWriteTest = write( m_nMaster, "\n", 1 );
if( nWriteTest < 0 )
{
std::cout << "Write to PTY failed" ;
return -1;
}
return 0;
}
int CMkPty::readFromPty( QString output )
{
char buffer[ 160 ];
m_nBytes = sizeof( buffer );
while ( ( m_nPosition = read( m_nMaster, buffer, m_nBytes ) ) > 0 )
{
buffer[ m_nPosition ] = 0;
output += buffer;
}
return 0;
}
EDIT: Here's a link to the question with the code that finally worked for me.
I'm note entirely familiar with posix, but after reading this page http://pwet.fr/man/linux/fonctions_bibliotheques/posix/read I had some insight. What's more, I don't see you adjusting your M_nBytes value if you haven't read as much as you were expecting on the first pass of the loop.
edit: from that link, perhaps this will be of some help:
If some process has the pipe open for writing and O_NONBLOCK is clear, read() shall block the calling thread until some data is written or the pipe is closed by all processes that had the pipe open for writing.
When attempting to read a file (other than a pipe or FIFO) that supports non-blocking reads and has no data currently available:
*
If O_NONBLOCK is clear, read() shall block the calling thread until some data becomes available.
so essentially, if you're not in an error state, and you tell it to keep reading, it will block until it finds something to read.