From: jpr Date: Fri, 13 Jul 2007 08:17:19 +0000 (+0000) Subject: First step to sync with v 1.2.2 X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=8b4006ce9e262e36f32ed56d877bc31de0a748a1;p=gdcm.git First step to sync with v 1.2.2 --- diff --git a/Example/CMakeLists.txt b/Example/CMakeLists.txt index 59317ac0..c7e2b0b7 100644 --- a/Example/CMakeLists.txt +++ b/Example/CMakeLists.txt @@ -7,7 +7,8 @@ SET(EXAMPLE_SOURCES #names starting with 'ex' are examples #Txt2Mat #exDicomRTStructSetFile - #exExtractCSA + #exExtractCSA + Dense2007ToDicom exReadPapyrus exReadWriteFile exColorToRGB @@ -38,7 +39,7 @@ SET(EXAMPLE_SOURCES PatchHeader ToInTag ReWrite - ReWriteExtended + #ReWriteExtended RawToDicom TestValidate ToMRIregister @@ -54,7 +55,8 @@ SET(EXAMPLE_SOURCES Volume2Dicom WriteDicomSimple WriteRead - #WriteDicomAsJPEG + WriteDicomAsJPEG2000 + WriteDicomAsJPEG exCTPET #Slice ) diff --git a/Example/RawToDicom.cxx b/Example/RawToDicom.cxx index e39dc416..b8227a23 100755 --- a/Example/RawToDicom.cxx +++ b/Example/RawToDicom.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: RawToDicom.cxx,v $ Language: C++ - Date: $Date: 2007/07/05 13:17:26 $ - Version: $Revision: 1.11 $ + Date: $Date: 2007/07/13 08:17:20 $ + Version: $Revision: 1.12 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -192,7 +192,7 @@ int main(int argc, char *argv[]) return 1; } - std::string strStudyUID; + std::string strStudyUID; std::string strSerieUID; if (userDefinedStudy) @@ -222,8 +222,6 @@ int main(int argc, char *argv[]) // Get the (empty) image header. GDCM_NAME_SPACE::File *fileToBuild = fileH->GetFile(); - - // 'Study Instance UID' // The user is allowed to create his own Study, diff --git a/Example/ReWriteExtended.cxx b/Example/ReWriteExtended.cxx index 6faf1fbc..a4aed09c 100755 --- a/Example/ReWriteExtended.cxx +++ b/Example/ReWriteExtended.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: ReWriteExtended.cxx,v $ Language: C++ - Date: $Date: 2007/05/23 14:18:04 $ - Version: $Revision: 1.5 $ + Date: $Date: 2007/07/13 08:17:20 $ + Version: $Revision: 1.6 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -42,6 +42,7 @@ int main(int argc, char *argv[]) " noshadow : user doesn't want to load Private groups (odd number)", " noseq : user doesn't want to load Sequences ", " rgb : user wants to transform LUT (if any) to RGB pixels ", + " warning : developper wants to run the program in 'warning mode'", " debug : developper wants to run the program in 'debug mode' ", FINISH_USAGE @@ -90,11 +91,10 @@ int main(int argc, char *argv[]) if (am->ArgMgrDefined("debug")) GDCM_NAME_SPACE::Debug::DebugOn(); + if (am->ArgMgrDefined("warning")) + GDCM_NAME_SPACE::Debug::WarningOn(); - - - // ======================================================================= - bool fail = false; + bool fail = false; int *boundRoiVal; bool roi = false; @@ -113,11 +113,9 @@ int main(int argc, char *argv[]) roi = true; } - int beg = am->ArgMgrGetInt("firstFrame",0); - int end = am->ArgMgrGetInt("lastFrame",0); - // ======================================================================= - - + int beg = am->ArgMgrGetInt("firstFrame",-1); + int end = am->ArgMgrGetInt("lastFrame",-1); + // if unused Params we give up if ( am->ArgMgrPrintUnusedLabels() ) { @@ -146,8 +144,7 @@ int main(int argc, char *argv[]) f->Delete(); return 0; } - - + //std::cout <GetTransferSyntaxName(); std::cout << " TransferSyntaxName= [" << transferSyntaxName << "]" << std::endl; - - - + GDCM_NAME_SPACE::FileHelper *fh = GDCM_NAME_SPACE::FileHelper::New(f); void *imageData; int dataSize; - - // ======================================================================= int subImDimX = nX; int subImDimY = nY; - if (roi) { std::cout << " " << boundRoiVal[0] << " " << boundRoiVal[1] << " " << boundRoiVal[2] << " " << @@ -255,14 +247,12 @@ int main(int argc, char *argv[]) std::cout << "Was unable to read pixels " << std::endl; } - // We trust user. (just an example; *never* trust an user !) fh->SetContentType((GDCM_NAME_SPACE::ImageContentType)filecontent); /// \todo Here, give the detail of operations a 'decent' user should perform, /// according to what *he* wants to do. - // an user shouldn't add images to a 'native' serie. // He is allowed to create his own Serie, within a 'native' Study : // if he wants to do so, he has to call GDCM_NAME_SPACE::Util::GetUniqueUID @@ -355,4 +345,3 @@ int main(int argc, char *argv[]) fh->Delete(); return 0; } - diff --git a/Example/WriteDicomAsJPEG2000.cxx b/Example/WriteDicomAsJPEG2000.cxx index d864ea17..e60a9b4c 100644 --- a/Example/WriteDicomAsJPEG2000.cxx +++ b/Example/WriteDicomAsJPEG2000.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: WriteDicomAsJPEG2000.cxx,v $ Language: C++ - Date: $Date: 2007/06/21 15:01:00 $ - Version: $Revision: 1.4 $ + Date: $Date: 2007/07/13 08:17:20 $ + Version: $Revision: 1.5 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -39,15 +39,11 @@ int main(int argc, char *argv[]) std::cerr << "Using quality: " << quality << std::endl; // Step 1 : Create the header of the image - //GDCM_NAME_SPACE::File *f = new GDCM_NAME_SPACE::File(); - // gdcm1.3 syntax. Sorry GDCM_NAME_SPACE::File *f = GDCM_NAME_SPACE::File::New(); f->SetLoadMode ( GDCM_NAME_SPACE::LD_ALL ); // Load everything f->SetFileName( filename ); f->Load(); - //GDCM_NAME_SPACE::FileHelper *tested = new GDCM_NAME_SPACE::FileHelper( f ); - // gdcm1.3 syntax. Sorry GDCM_NAME_SPACE::FileHelper *tested = GDCM_NAME_SPACE::FileHelper::New( f ); std::string PixelType = tested->GetFile()->GetPixelType(); int xsize = f->GetXSize(); @@ -61,30 +57,21 @@ int main(int argc, char *argv[]) // Step 1 : Create the header of the image -// GDCM_NAME_SPACE::File *fileToBuild = new GDCM_NAME_SPACE::File(); - // gdcm1.3 syntax. Sorry ! GDCM_NAME_SPACE::File *fileToBuild = GDCM_NAME_SPACE::File::New(); - std::ostringstream str; // Set the image size str.str(""); str << xsize; - //fileToBuild->InsertValEntry(str.str(),0x0028,0x0011); // Columns - // gdcm1.3 syntax. Sorry ! fileToBuild->InsertEntryString(str.str(),0x0028,0x0011, "US"); // Columns str.str(""); str << ysize; - //fileToBuild->InsertValEntry(str.str(),0x0028,0x0010); // Rows - // gdcm1.3 syntax. Sorry ! fileToBuild->InsertEntryString(str.str(),0x0028,0x0010, "US"); // Rows if(zsize>1) { str.str(""); str << zsize; - //fileToBuild->InsertValEntry(str.str(),0x0028,0x0008); // Number of Frames - // gdcm1.3 syntax. Sorry ! fileToBuild->InsertEntryString(str.str(),0x0028,0x0008, "IS"); // Number of Frames } int bitsallocated = f->GetBitsAllocated(); @@ -96,39 +83,27 @@ int main(int argc, char *argv[]) // Set the pixel type str.str(""); str << bitsallocated; - //fileToBuild->InsertValEntry(str.str(),0x0028,0x0100); // Bits Allocated - // gdcm1.3 syntax. Sorry ! fileToBuild->InsertEntryString(str.str(),0x0028,0x0100,"US"); // Bits Allocated - + str.str(""); - str << bitsstored; - //fileToBuild->InsertValEntry(str.str(),0x0028,0x0101); // Bits Stored - // gdcm1.3 syntax. Sorry ! + str << bitsstored; fileToBuild->InsertEntryString(str.str(),0x0028,0x0101, "US"); // Bits Stored + str.str(""); str << highbit; - //fileToBuild->InsertValEntry(str.str(),0x0028,0x0102); // High Bit - // gdcm1.3 syntax. Sorry ! fileToBuild->InsertEntryString(str.str(),0x0028,0x0102, "US"); // High Bit // Set the pixel representation str.str(""); str << sign; - //fileToBuild->InsertValEntry(str.str(),0x0028,0x0103); // Pixel Representation - // gdcm1.3 syntax. Sorry ! fileToBuild->InsertEntryString(str.str(),0x0028,0x0103, "US"); // Pixel Representation - // Set the samples per pixel str.str(""); str << samplesPerPixel; //img.components; - //fileToBuild->InsertValEntry(str.str(),0x0028,0x0002); // Samples per Pixel - // gdcm1.3 syntax. Sorry ! fileToBuild->InsertEntryString(str.str(),0x0028,0x0002, "US"); // Samples per Pixel // Step 2 : Create the output image - //GDCM_NAME_SPACE::FileHelper *fileH = new GDCM_NAME_SPACE::FileHelper(fileToBuild); - // gdcm1.3 syntax. Sorry ! GDCM_NAME_SPACE::FileHelper *fileH = GDCM_NAME_SPACE::FileHelper::New(fileToBuild); fileH->SetWriteTypeToJPEG2000( ); fileH->SetImageData(testedImageData, testedDataSize); @@ -137,15 +112,11 @@ int main(int argc, char *argv[]) std::cerr << "write fails" << std::endl; } - //delete f; - // gdcm1.3 syntax. Sorry ! f->Delete(); - //delete tested; tested->Delete(); - //delete fileToBuild; fileToBuild->Delete(); - //delete fileH; fileH->Delete(); return 0; } + diff --git a/src/gdcmDirList.h b/src/gdcmDirList.h index cda6dd31..658079ea 100644 --- a/src/gdcmDirList.h +++ b/src/gdcmDirList.h @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmDirList.h,v $ Language: C++ - Date: $Date: 2007/06/08 12:49:37 $ - Version: $Revision: 1.34 $ + Date: $Date: 2007/07/13 08:17:21 $ + Version: $Revision: 1.35 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -35,6 +35,8 @@ typedef std::vector DirListType; // NOTE: Due to a M$VC6 'feature' we cannot export a std::list in a dll, // so GDCM_EXPORT keyword was removed for this class only +// +// We have to supply accessors GetSize(), GetFirst(), GetNext() /** * \brief List containing the file headers of all the 'gdcm readable' files diff --git a/src/gdcmFileHelper.cxx b/src/gdcmFileHelper.cxx index c45142e1..32f79cb6 100644 --- a/src/gdcmFileHelper.cxx +++ b/src/gdcmFileHelper.cxx @@ -4,8 +4,8 @@ Module: $RCSfile: gdcmFileHelper.cxx,v $ Language: C++ - Date: $Date: 2007/07/05 10:53:48 $ - Version: $Revision: 1.116 $ + Date: $Date: 2007/07/13 08:17:21 $ + Version: $Revision: 1.117 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -74,7 +74,10 @@ To re-write the image, user re-uses the gdcm::FileHelper fh->SetImageData( userPixels, userPixelsLength); fh->SetTypeToRaw(); // Even if it was possible to convert Palette to RGB // (WriteMode is set) - + +// If user wants to write the file as MONOCHROME1 (0=white) +fh->SetPhotometricInterpretationToMonochrome1(); + fh->SetWriteTypeToDcmExpl(); // he wants Explicit Value Representation // Little Endian is the default // no other value is allowed @@ -88,7 +91,6 @@ fh->WriteDcmExplVR(newFileName); // ----------------------------- WARNING ------------------------- - These lines will be moved to the document-to-be 'Developer's Guide' WriteMode : WMODE_RAW / WMODE_RGB @@ -511,7 +513,18 @@ void FileHelper::SetImageData(uint8_t *inData, size_t expectedSize) */ void FileHelper::SetUserData(uint8_t *inData, size_t expectedSize) { - PixelWriteConverter->SetUserData(inData, expectedSize); + if( WriteType == JPEG2000 ) + { + PixelWriteConverter->SetCompressJPEG2000UserData(inData, expectedSize, FileInternal); + } + else if( WriteType == JPEG ) + { + PixelWriteConverter->SetCompressJPEGUserData(inData, expectedSize, FileInternal); + } + else + { + PixelWriteConverter->SetUserData(inData, expectedSize); + } } /** @@ -694,7 +707,6 @@ bool FileHelper::WriteAcr (std::string const &fileName) */ bool FileHelper::Write(std::string const &fileName) { - CheckMandatoryElements(); //called once, here ! bool flag = false; @@ -716,6 +728,7 @@ bool FileHelper::Write(std::string const &fileName) // Let's just *dream* about it; *never* trust a user ! // We turn to Implicit VR if at least the VR of one element is unknown. + /// \TODO : better we put vr=UN for undocumented Shadow Groups ! e = FileInternal->GetFirstEntry(); while (e != 0) @@ -758,7 +771,7 @@ bool FileHelper::Write(std::string const &fileName) SetWriteFileTypeToJPEG(); break; - case JPEG2000: + case JPEG2000: SetWriteFileTypeToJPEG2000(); break; } @@ -793,16 +806,17 @@ bool FileHelper::Write(std::string const &fileName) } bool check = CheckWriteIntegrity(); // verifies length - if (WriteType == JPEG || WriteType == JPEG2000) check = true; + if (WriteType == JPEG || WriteType == JPEG2000) + check = true; + if (check) { check = FileInternal->Write(fileName,WriteType); } - RestoreWrite(); + RestoreWrite(); // RestoreWriteFileType(); // RestoreWriteMandatory(); - // -------------------------------------------------------------- // Special Patch to allow gdcm to re-write ACR-LibIDO formated images @@ -818,7 +832,7 @@ bool FileHelper::Write(std::string const &fileName) //----------------------------------------------------------------------------- // Protected /** - * \brief * \brief Verifies the size of the user given PixelData + * \brief Verifies the size of the user given PixelData * @return true if check is successfull */ bool FileHelper::CheckWriteIntegrity() @@ -866,7 +880,6 @@ bool FileHelper::CheckWriteIntegrity() break; } } - return true; } @@ -922,7 +935,7 @@ void FileHelper::SetWriteToRaw() if (!FileInternal->HasLUT() && GetPhotometricInterpretation() == 1) { - ConvertFixGreyLevels( pixel->GetBinArea(), pixel->GetLength() ); + ConvertFixGreyLevels( pixel->GetBinArea(), pixel->GetLength() ); } Archive->Push(photInt); @@ -1032,7 +1045,6 @@ void FileHelper::SetWriteToRGB() */ void FileHelper::RestoreWrite() { - Archive->Restore(0x0028,0x0002); Archive->Restore(0x0028,0x0004); @@ -1090,14 +1102,14 @@ void FileHelper::SetWriteFileTypeToACR() Archive->Push(0x0002,0x0102); } - /** - * \brief Sets in the File the TransferSyntax to 'JPEG2000' - */ +/** + * \brief Sets in the File the TransferSyntax to 'JPEG2000' + */ void FileHelper::SetWriteFileTypeToJPEG2000() { std::string ts = Util::DicomString( Global::GetTS()->GetSpecialTransferSyntax(TS::JPEG2000Lossless) ); - + DataEntry *tss = CopyDataEntry(0x0002,0x0010,"UI"); tss->SetString(ts); @@ -1107,11 +1119,11 @@ void FileHelper::SetWriteFileTypeToJPEG2000() /** * \brief Sets in the File the TransferSyntax to 'JPEG' - */ + */ void FileHelper::SetWriteFileTypeToJPEG() { - std::string ts = Util::DicomString( - Global::GetTS()->GetSpecialTransferSyntax(TS::JPEGBaselineProcess1) ); + std::string ts = Util::DicomString( + Global::GetTS()->GetSpecialTransferSyntax(TS::JPEGLosslessProcess14_1) ); DataEntry *tss = CopyDataEntry(0x0002,0x0010,"UI"); tss->SetString(ts); @@ -1159,9 +1171,6 @@ void FileHelper::SetWriteToLibido() if ( oldRow && oldCol ) { std::string rows, columns; - - //DataEntry *newRow=DataEntry::New(oldRow->GetDictEntry()); - //DataEntry *newCol=DataEntry::New(oldCol->GetDictEntry()); DataEntry *newRow=DataEntry::New(0x0028, 0x0010, "US"); DataEntry *newCol=DataEntry::New(0x0028, 0x0011, "US"); @@ -1238,7 +1247,6 @@ DataEntry *FileHelper::CopyDataEntry(uint16_t group, uint16_t elem, if ( oldE ) { - //newE = DataEntry::New(oldE->GetDictEntry()); newE = DataEntry::New(group, elem, vr); newE->Copy(oldE); } @@ -1296,9 +1304,9 @@ We have to deal with 4 *very* different cases : FILTERED_IMAGE -3) user created a new image, using a set of existing images (eg MIP, MPR, cartography image) CREATED_IMAGE --4) user modified/added some tags *without processing* the pixels (anonymization.. +-4) user modified/added some tags *without processing* the pixels (anonymization...) UNMODIFIED_PIXELS_IMAGE --Probabely some more to be added +-Probabely some more to be added. gdcm::FileHelper::CheckMandatoryElements() deals automatically with these cases. @@ -1435,20 +1443,20 @@ void FileHelper::CheckMandatoryElements() //0002 0000 UL 1 Meta Group Length //0002 0001 OB 1 File Meta Information Version - //0002 0002 UI 1 Media Stored SOP Class UID - //0002 0003 UI 1 Media Stored SOP Instance UID + //0002 0002 UI 1 Media Storage SOP Class UID + //0002 0003 UI 1 Media Storage SOP Instance UID //0002 0010 UI 1 Transfer Syntax UID //0002 0012 UI 1 Implementation Class UID //0002 0013 SH 1 Implementation Version Name //0002 0016 AE 1 Source Application Entity Title //0002 0100 UI 1 Private Information Creator //0002 0102 OB 1 Private Information - + // Push out 'ACR-NEMA-special' entries, if any Archive->Push(0x0008,0x0001); // Length to End Archive->Push(0x0008,0x0010); // Recognition Code - Archive->Push(0x0028,0x0005); // Image Dimension - + Archive->Push(0x0028,0x0005); // Image Dimension + // Create them if not found // Always modify the value // Push the entries to the archive. @@ -1691,17 +1699,17 @@ is only from (0020,0030) and (0020,0035) CopyMandatoryEntry(0x0020, 0x0032,imagePositionRet,"DS"); Archive->Push(0x0020,0x0030); CopyMandatoryEntry(0x0020, 0x0037,imageOrientationRet,"DS"); - Archive->Push(0x0020,0x0035); - } + Archive->Push(0x0020,0x0035); + } */ - + // Samples Per Pixel (type 1) : default to grayscale CheckMandatoryEntry(0x0028,0x0002,"1","US"); // --- Check UID-related Entries --- // At the end, not to overwrite the original ones, - // needed by 'Referenced SOP Instance UID', 'Referenced SOP Class UID' + // needed by 'Referenced SOP Instance UID', 'Referenced SOP Class UID' // 'SOP Instance UID' CopyMandatoryEntry(0x0008,0x0018,sop,"UI"); @@ -1713,7 +1721,7 @@ is only from (0020,0030) and (0020,0035) // See PS 3.3, Page 408 // DV = Digitized Video - // DI = Digital Interface + // DI = Digital Interface // DF = Digitized Film // WSD = Workstation // SD = Scanned Document @@ -1730,7 +1738,7 @@ is only from (0020,0030) and (0020,0035) } */ - + // ---- The user will never have to take any action on the following ---- // new value for 'SOP Instance UID' @@ -1739,7 +1747,7 @@ is only from (0020,0030) and (0020,0035) // Instance Creation Date const std::string &date = Util::GetCurrentDate(); CopyMandatoryEntry(0x0008,0x0012,date,"DA"); - + // Instance Creation Time const std::string &time = Util::GetCurrentTime(); CopyMandatoryEntry(0x0008,0x0013,time,"TM"); @@ -1787,7 +1795,7 @@ is only from (0020,0030) and (0020,0035) // Instance Number CheckMandatoryEntry(0x0020,0x0013,"","IS"); - + // Patient Orientation // Can be computed from (0020|0037) : Image Orientation (Patient) GDCM_NAME_SPACE::Orientation *o = GDCM_NAME_SPACE::Orientation::New(); @@ -1795,7 +1803,7 @@ is only from (0020,0030) and (0020,0035) o->Delete(); if (ori != "\\" && ori != GDCM_UNFOUND) CheckMandatoryEntry(0x0020,0x0020,ori,"CS"); - else + else CheckMandatoryEntry(0x0020,0x0020,"","CS"); // Default Patient Position to HFS @@ -1842,7 +1850,7 @@ is only from (0020,0030) and (0020,0035) CheckMandatoryEntry(it->first, 0x0000, "0"); } // Third stage : update all 'zero level' groups length -*/ +*/ if (PhotometricInterpretation == 1) @@ -1918,7 +1926,6 @@ void FileHelper::RestoreWriteMandatory() Archive->Restore(0x0020,0x000e); } - /** * \brief CallStartMethod */ @@ -1955,12 +1962,12 @@ void FileHelper::Initialize() { UserFunction = 0; ContentType = USER_OWN_IMAGE; - + WriteMode = WMODE_RAW; WriteType = ExplicitVR; PhotometricInterpretation = 2; // Black = 0 - + PixelReadConverter = new PixelReadConvert; PixelWriteConverter = new PixelWriteConvert; Archive = new DocEntryArchive( FileInternal ); @@ -1995,7 +2002,6 @@ uint8_t *FileHelper::GetRaw() return raw; } - /** * \brief Deal with Grey levels i.e. re-arange them * to have low values = dark, high values = bright @@ -2209,9 +2215,7 @@ void RescaleFunction(TBuffer* buffer, TSource *source, case 1: *buffer++ = (TBuffer)(*source++); } while (--n > 0); } - } - - + } } diff --git a/src/gdcmJpeg.cxx b/src/gdcmJpeg.cxx index eb6597fa..9f869336 100644 --- a/src/gdcmJpeg.cxx +++ b/src/gdcmJpeg.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmJpeg.cxx,v $ Language: C++ - Date: $Date: 2007/05/23 14:18:10 $ - Version: $Revision: 1.56 $ + Date: $Date: 2007/07/13 08:17:21 $ + Version: $Revision: 1.57 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -42,7 +42,7 @@ #if defined(__BORLANDC__) #include // for memset -#endif +#endif #include "jdatasrc.cxx" #include "jdatadst.cxx" @@ -51,21 +51,24 @@ namespace GDCM_NAME_SPACE { /** - * \brief routine for JPEG decompression - * @param fp pointer to an already open file descriptor + * \brief routine for JPEG decompression + * @param fp pointer to an already open file descriptor * 8 significant bits per pixel * @param im_buf Points to array (of R,G,B-order) data to compress * @param quality compression quality - * @param image_height Number of rows in image + * @param image_height Number of rows in image * @param image_width Number of columns in image * @return 1 on success, 0 on error */ - -bool gdcm_write_JPEG_file (std::ostream *fp, void *im_buf, - int image_width, int image_height, int quality) + +bool gdcm_write_JPEG_file (std::ostream *fp, char *inputdata, size_t inputlength, + int image_width, int image_height, int numZ, + int sample_pixel, int bitsallocated, int quality) { - JSAMPLE *image_buffer = (JSAMPLE*) im_buf; + (void)bitsallocated; + struct jpeg_compress_struct cinfo; + int row_stride; /* physical row width in image buffer */ /* This struct contains the JPEG compression parameters and pointers to * working space (which is allocated as needed by the JPEG library). @@ -73,7 +76,7 @@ bool gdcm_write_JPEG_file (std::ostream *fp, void *im_buf, * compression/decompression processes, in existence at once. We refer * to any one struct (and its associated working data) as a "JPEG object". */ - struct jpeg_compress_struct cinfo; + //struct jpeg_compress_struct cinfo; /* This struct represents a JPEG error handler. It is declared separately * because applications often want to supply a specialized error handler * (see the second half of this file for an example). But here we just @@ -84,9 +87,6 @@ bool gdcm_write_JPEG_file (std::ostream *fp, void *im_buf, */ struct jpeg_error_mgr jerr; /* More stuff */ - //FILE* outfile; /* target FILE* / - JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ - int row_stride; /* physical row width in image buffer */ /* Step 1: allocate and initialize JPEG compression object */ @@ -102,19 +102,8 @@ bool gdcm_write_JPEG_file (std::ostream *fp, void *im_buf, /* Step 2: specify data destination (eg, a file) */ /* Note: steps 2 and 3 can be done in either order. */ - /* Here we use the library-supplied code to send compressed data to a - * stdio stream. You can also write your own code to do something else. - * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that - * requires it in order to write binary files. - */ - // if ((outfile = fopen(filename, "wb")) == NULL) { - // fprintf(stderr, "can't open %s\n", filename); - // exit(1); - // - // } - assert( 0 ); - (void)fp; - //jpeg_stdio_dest(&cinfo, fp, 0, 0, image_width, image_height, quality); + int fragment_size = inputlength; + jpeg_stdio_dest(&cinfo, fp, fragment_size, 1); /* Step 3: set parameters for compression */ @@ -123,13 +112,36 @@ bool gdcm_write_JPEG_file (std::ostream *fp, void *im_buf, */ cinfo.image_width = image_width;/* image width and height, in pixels */ cinfo.image_height = image_height; - cinfo.input_components = 3; /* # of color components per pixel */ - cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ + if ( sample_pixel == 3 ) + { + cinfo.input_components = 3; /* # of color components per pixel */ + cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ + } + else + { + cinfo.input_components = 1; /* # of color components per pixel */ + cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */ + } /* Now use the library's routine to set default compression parameters. * (You must set at least cinfo.in_color_space before calling this, * since the defaults depend on the source color space.) */ jpeg_set_defaults(&cinfo); + /* + * http://www.koders.com/c/fid80DBBF1D49D004EF71CE7C493C34610C4F17D3D3.aspx + * http://studio.imagemagick.org/pipermail/magick-users/2002-September/004685.html + * You need to set -quality 101 or greater. If quality is 100 or less you + * get regular JPEG output. This is not explained in the documentation, only + * in the comments in coder/jpeg.c. When you have configured libjpeg with + * lossless support, then + * + * quality=predictor*100 + point_transform + * + * If you don't know what these values should be, just use 101. + * They only affect the compression ratio, not the image appearance, + * which is lossless. + */ + jpeg_simple_lossless (&cinfo, 1, 1); /* Now you can set any non-default parameters you wish to. * Here we just illustrate the use of quality (quantization table) scaling: */ @@ -150,25 +162,57 @@ bool gdcm_write_JPEG_file (std::ostream *fp, void *im_buf, * To keep things simple, we pass one scanline per call; you can pass * more if you wish, though. */ - row_stride = image_width * 3;/* JSAMPLEs per row in image_buffer */ + if (sample_pixel == 3) + { + row_stride = image_width * 3;/* JSAMPLEs per row in image_buffer */ + } + else + { + assert( sample_pixel == 1 ); + row_stride = image_width * 1;/* JSAMPLEs per row in image_buffer */ + } + + (void)numZ; + + uint8_t* input_buffer = (uint8_t*)inputdata; + //uint8_t *pbuffer = input_buffer; + //int i; + //for(i=0; itellp(); +// std::cerr << "DIFF: " << end-beg << std::endl; + +// JpegPair &jp = v[i]; +// jp.second = end-beg; + //beg = end; // + // } /* Step 6: Finish compression */ jpeg_finish_compress(&cinfo); - - /* After finish_compress, we can close the output file. */ - - // fclose(fp); --> the caller will close (multiframe treatement) /* Step 7: release JPEG compression object */ diff --git a/src/gdcmJpeg2000.cxx b/src/gdcmJpeg2000.cxx index ed0f09f2..0f3dd173 100644 --- a/src/gdcmJpeg2000.cxx +++ b/src/gdcmJpeg2000.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmJpeg2000.cxx,v $ Language: C++ - Date: $Date: 2007/05/23 14:18:10 $ - Version: $Revision: 1.43 $ + Date: $Date: 2007/07/13 08:17:21 $ + Version: $Revision: 1.44 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -59,6 +59,24 @@ namespace GDCM_NAME_SPACE * @return 1 on success, 0 on error */ +/** +sample error callback expecting a FILE* client object +*/ +void error_callback(const char *msg, void *) { + std::cerr << "Error in gdcmopenjpeg" << msg << std::endl; +} +/** +sample warning callback expecting a FILE* client object +*/ +void warning_callback(const char *msg, void *) { + std::cerr << "Warning in gdcmopenjpeg" << msg << std::endl; +} +/** +sample debug callback expecting no client object +*/ +void info_callback(const char *msg, void *) { + std::cerr << "Info in gdcmopenjpeg" << msg << std::endl; +} #define J2K_CFMT 0 #define JP2_CFMT 1 @@ -114,9 +132,9 @@ bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength) /* get a decoder handle */ dinfo = opj_create_decompress(CODEC_J2K); - + /* catch events using our callbacks and give a local context */ - opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL); + opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); @@ -142,43 +160,46 @@ bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength) for (int compno = 0; compno < image->numcomps; compno++) { opj_image_comp_t *comp = &image->comps[compno]; - + int w = image->comps[compno].w; int wr = int_ceildivpow2(image->comps[compno].w, image->comps[compno].factor); - + //int h = image.comps[compno].h; int hr = int_ceildivpow2(image->comps[compno].h, image->comps[compno].factor); - + if (comp->prec <= 8) { - uint8_t *data8 = (uint8_t*)raw; - for (int i = 0; i < wr * hr; i++) + uint8_t *data8 = (uint8_t*)raw + compno; + for (int i = 0; i < wr * hr; i++) { int v = image->comps[compno].data[i / wr * w + i % wr]; - *data8++ = (uint8_t)v; + *data8 = (uint8_t)v; + data8 += image->numcomps; } } else if (comp->prec <= 16) { - uint16_t *data16 = (uint16_t*)raw; - for (int i = 0; i < wr * hr; i++) + uint16_t *data16 = (uint16_t*)raw + compno; + for (int i = 0; i < wr * hr; i++) { int v = image->comps[compno].data[i / wr * w + i % wr]; - *data16++ = (uint16_t)v; + *data16 = (uint16_t)v; + data16 += image->numcomps; } } else { - uint32_t *data32 = (uint32_t*)raw; - for (int i = 0; i < wr * hr; i++) + uint32_t *data32 = (uint32_t*)raw + compno; + for (int i = 0; i < wr * hr; i++) { int v = image->comps[compno].data[i / wr * w + i % wr]; - *data32++ = (uint32_t)v; + *data32 = (uint32_t)v; + data32 += image->numcomps; } } //free(image.comps[compno].data); } - + /* free remaining structures */ if(dinfo) { @@ -188,6 +209,246 @@ bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength) /* free image data structure */ opj_image_destroy(image); + return true; +} + +template +void rawtoimage_fill(T *inputbuffer, int w, int h, int numcomps, opj_image_t *image) +{ + T *p = inputbuffer; + for (int i = 0; i < w * h; i++) + { + for(int compno = 0; compno < numcomps; compno++) + { + /* compno : 0 = GREY, (0, 1, 2) = (R, G, B) */ + image->comps[compno].data[i] = *p; + ++p; + } + } +} + +opj_image_t* rawtoimage(char *inputbuffer, opj_cparameters_t *parameters, + int fragment_size, int image_width, int image_height, int sample_pixel, + int bitsallocated, int sign, int quality) +{ + (void)quality; + (void)fragment_size; + int w, h; + int numcomps; + OPJ_COLOR_SPACE color_space; + opj_image_cmptparm_t cmptparm[3]; /* maximum of 3 components */ + opj_image_t * image = NULL; + + assert( sample_pixel == 1 || sample_pixel == 3 ); + if( sample_pixel == 1 ) + { + numcomps = 1; + color_space = CLRSPC_GRAY; + } + else // sample_pixel == 3 + { + numcomps = 3; + color_space = CLRSPC_SRGB; + } + int subsampling_dx = parameters->subsampling_dx; + int subsampling_dy = parameters->subsampling_dy; + + // FIXME + w = image_width; + h = image_height; + + /* initialize image components */ + memset(&cmptparm[0], 0, 3 * sizeof(opj_image_cmptparm_t)); + //assert( bitsallocated == 8 ); + for(int i = 0; i < numcomps; i++) { + cmptparm[i].prec = bitsallocated; + cmptparm[i].bpp = bitsallocated; + cmptparm[i].sgnd = sign; + cmptparm[i].dx = subsampling_dx; + cmptparm[i].dy = subsampling_dy; + cmptparm[i].w = w; + cmptparm[i].h = h; + } + + /* create the image */ + image = opj_image_create(numcomps, &cmptparm[0], color_space); + if(!image) { + return NULL; + } + /* set image offset and reference grid */ + image->x0 = parameters->image_offset_x0; + image->y0 = parameters->image_offset_y0; + image->x1 = parameters->image_offset_x0 + (w - 1) * subsampling_dx + 1; + image->y1 = parameters->image_offset_y0 + (h - 1) * subsampling_dy + 1; + + /* set image data */ + + //assert( fragment_size == numcomps*w*h*(bitsallocated/8) ); + if (bitsallocated <= 8) + { + if( sign ) + { + rawtoimage_fill((int8_t*)inputbuffer,w,h,numcomps,image); + } + else + { + rawtoimage_fill((uint8_t*)inputbuffer,w,h,numcomps,image); + } + } + else if (bitsallocated <= 16) + { + if( sign ) + { + rawtoimage_fill((int16_t*)inputbuffer,w,h,numcomps,image); + } + else + { + rawtoimage_fill((uint16_t*)inputbuffer,w,h,numcomps,image); + } + } + else if (bitsallocated <= 32) + { + if( sign ) + { + rawtoimage_fill((int32_t*)inputbuffer,w,h,numcomps,image); + } + else + { + rawtoimage_fill((uint32_t*)inputbuffer,w,h,numcomps,image); + } + } + else + { + abort(); + } + + return image; +} + +/* + * The following function was copy paste from image_to_j2k.c with part from convert.c + */ +bool gdcm_write_JPEG2000_file (std::ostream *fp, char *inputdata, size_t inputlength, + int image_width, int image_height, int numZ, int sample_pixel, int bitsallocated, + int sign, int quality) +{ +//// input_buffer is ONE image +//// fragment_size is the size of this image (fragment) + (void)numZ; + bool bSuccess; + //bool delete_comment = true; + opj_cparameters_t parameters; /* compression parameters */ + opj_event_mgr_t event_mgr; /* event manager */ + opj_image_t *image = NULL; + //quality = 100; + + /* + configure the event callbacks (not required) + setting of each callback is optionnal + */ + memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); + event_mgr.error_handler = error_callback; + event_mgr.warning_handler = warning_callback; + event_mgr.info_handler = info_callback; + + /* set encoding parameters to default values */ + memset(¶meters, 0, sizeof(parameters)); + opj_set_default_encoder_parameters(¶meters); + + /* if no rate entered, lossless by default */ + parameters.tcp_rates[0] = 0; + parameters.tcp_numlayers = 1; + parameters.cp_disto_alloc = 1; + + if(parameters.cp_comment == NULL) { + const char comment[] = "Created by GDCM/OpenJPEG version 1.0"; + parameters.cp_comment = (char*)malloc(strlen(comment) + 1); + strcpy(parameters.cp_comment, comment); + /* no need to delete parameters.cp_comment on exit */ + //delete_comment = false; + } + + + /* decode the source image */ + /* ----------------------- */ + + image = rawtoimage((char*)inputdata, ¶meters, inputlength, + image_width, image_height, + sample_pixel, bitsallocated, sign, quality); + if (!image) { + return 1; + } + + /* encode the destination image */ + /* ---------------------------- */ + parameters.cod_format = J2K_CFMT; /* J2K format output */ + int codestream_length; + opj_cio_t *cio = NULL; + //FILE *f = NULL; + + /* get a J2K compressor handle */ + opj_cinfo_t* cinfo = opj_create_compress(CODEC_J2K); + + /* catch events using our callbacks and give a local context */ + opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr); + + /* setup the encoder parameters using the current image and using user parameters */ + opj_setup_encoder(cinfo, ¶meters, image); + + /* open a byte stream for writing */ + /* allocate memory for all tiles */ + cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0); + + /* encode the image */ + bSuccess = opj_encode(cinfo, cio, image, parameters.index); + if (!bSuccess) { + opj_cio_close(cio); + fprintf(stderr, "failed to encode image\n"); + return 1; + } + codestream_length = cio_tell(cio); + + /* write the buffer to disk */ + //f = fopen(parameters.outfile, "wb"); + //if (!f) { + // fprintf(stderr, "failed to open %s for writing\n", parameters.outfile); + // return 1; + //} + //fwrite(cio->buffer, 1, codestream_length, f); +//#define MDEBUG +#ifdef MDEBUG + static int c = 0; + std::ostringstream os; + os << "/tmp/debug"; + os << c; + c++; + os << ".j2k"; + std::ofstream debug(os.str().c_str()); + debug.write((char*)(cio->buffer), codestream_length); + debug.close(); +#endif + fp->write((char*)(cio->buffer), codestream_length); + //fclose(f); + + /* close and free the byte stream */ + opj_cio_close(cio); + + /* free remaining compression structures */ + opj_destroy_compress(cinfo); + + + /* free user parameters structure */ + //if(delete_comment) { + if(parameters.cp_comment) free(parameters.cp_comment); + //} + if(parameters.cp_matrice) free(parameters.cp_matrice); + + /* free image data */ + opj_image_destroy(image); + + + + return true; } diff --git a/src/gdcmPixelWriteConvert.cxx b/src/gdcmPixelWriteConvert.cxx index 53de1044..94359049 100644 --- a/src/gdcmPixelWriteConvert.cxx +++ b/src/gdcmPixelWriteConvert.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmPixelWriteConvert.cxx,v $ Language: C++ - Date: $Date: 2007/07/04 10:40:56 $ - Version: $Revision: 1.13 $ + Date: $Date: 2007/07/13 08:17:21 $ + Version: $Revision: 1.14 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -18,10 +18,24 @@ #include "gdcmDebug.h" #include "gdcmPixelWriteConvert.h" +#include "gdcmFile.h" +#include "gdcmUtil.h" + +#include + +#define WITHOFFSETTABLE 1 namespace GDCM_NAME_SPACE { //----------------------------------------------------------------------------- +// Public + +//----------------------------------------------------------------------------- +// Protected + +//----------------------------------------------------------------------------- +// Private + // Constructor / Destructor /** * \brief Constructor @@ -33,6 +47,7 @@ PixelWriteConvert::PixelWriteConvert() UserData = 0; UserDataSize = 0; + Compressed = false; } /** @@ -40,10 +55,12 @@ PixelWriteConvert::PixelWriteConvert() */ PixelWriteConvert::~PixelWriteConvert() { + if( Compressed ) + { + delete[] UserData; + } } -//----------------------------------------------------------------------------- -// Public /** * \brief sets Read Data (and size) * @param data data (uint8_t is for prototyping. if your data is not uint8_t @@ -107,8 +124,291 @@ size_t PixelWriteConvert::GetDataSize() } } + +typedef std::pair JpegPair; //offset, jpeg size +typedef std::vector JpegVector; + +bool gdcm_write_JPEG2000_file (std::ostream *of, char *inputdata, size_t inputlength, + int image_width, int image_height, int numZ, int sample_pixel, int bitsallocated, + int sign, int quality); + + +void WriteDICOMItems(std::ostream *fp, JpegVector &v) +{ + // Item tag: + uint16_t group = 0xfffe; + uint16_t elem = 0xe000; + GDCM_NAME_SPACE::binary_write(*fp, group); + GDCM_NAME_SPACE::binary_write(*fp, elem); + // Item Length + uint32_t dummy = 0x12345678; + size_t offset = fp->tellp(); + JpegPair jp; + jp.first = offset; + v.push_back(jp); + GDCM_NAME_SPACE::binary_write(*fp, dummy); +} + +// PS 3.5, page 66 +void EncodeWithoutBasicOffsetTable(std::ostream *fp, int numFrag)// JpegVector& v) //, uint32_t length) +{ + assert( numFrag == 1); + + // Item tag: + uint16_t group = 0xfffe; + uint16_t elem = 0xe000; + GDCM_NAME_SPACE::binary_write(*fp, group); + GDCM_NAME_SPACE::binary_write(*fp, elem); + // Item Length + uint32_t item_length = 0x0000; + GDCM_NAME_SPACE::binary_write(*fp, item_length); + +} + +// PS 3.5, page 67 +void EncodeWithBasicOffsetTable(std::ostream *fp, int numFrag, size_t &start) +{ + // Item tag: + uint16_t group = 0xfffe; + uint16_t elem = 0xe000; + GDCM_NAME_SPACE::binary_write(*fp, group); + GDCM_NAME_SPACE::binary_write(*fp, elem); + // Item Length + uint32_t item_length = numFrag*4; // sizeof(uint32_t) + GDCM_NAME_SPACE::binary_write(*fp, item_length); + + // Just prepare the space + start = fp->tellp(); //to be able to rewind + for(int i=0; iseekp( pos ); + const JpegPair &first = v[0]; + for(i=v.begin(); i!=v.end(); ++i) + { + const JpegPair &jp = *i; + if(i == v.begin() ){ assert( jp.first - first.first == 0); } + uint32_t offset = jp.first - first.first; + GDCM_NAME_SPACE::binary_write(*fp, offset); + //std::cerr << "Updating Table:" << jp.first - first.first << std::endl; + } +} + +void UpdateJpegFragmentSize(std::ostream *fp, JpegVector const &v) +{ + JpegVector::const_iterator i; + for(i= v.begin(); i!=v.end(); ++i) + { + const JpegPair &jp = *i; + fp->seekp( jp.first ); + uint32_t length = jp.second; + GDCM_NAME_SPACE::binary_write(*fp, length); + //std::cerr << "Updating:" << jp.first << "," << jp.second << std::endl; + } +} + +void CloseJpeg(std::ostream *fp, JpegVector &v) +{ + // sequence terminator + uint16_t group = 0xfffe; + uint16_t elem = 0xe0dd; + GDCM_NAME_SPACE::binary_write(*fp, group); + GDCM_NAME_SPACE::binary_write(*fp, elem); + + uint32_t length = 0x0; + GDCM_NAME_SPACE::binary_write(*fp, length); + + // Jpeg is done, now update the frag length + UpdateJpegFragmentSize(fp, v); +} + +// I need to pass the File*. I do not understand how PixelWriteConvert is supposed +// to access this information otherwise +// size can now be computer from File attributes (what an API...) +void PixelWriteConvert::SetCompressJPEG2000UserData(uint8_t *data, size_t size, File *image) +{ + Compressed = true; + //char * userData = reinterpret_cast(UserData); + + std::ostringstream *of = new std::ostringstream(); + int xsize = image->GetXSize(); + int ysize = image->GetYSize(); + int zsize = image->GetZSize(); + int samplesPerPixel = image->GetSamplesPerPixel(); + //std::cout << "X: " << xsize << std::endl; + //std::cout << "Y: " << ysize << std::endl; + //std::cout << "Sample: " << samplesPerPixel << std::endl; + int bitsallocated = image->GetBitsAllocated(); + int sign = image->IsSignedPixelData(); + unsigned int fragment_size = xsize*ysize*samplesPerPixel * (bitsallocated / 8); + assert( fragment_size*zsize == size ); + + JpegVector JpegFragmentSize; +#if WITHOFFSETTABLE + size_t bots; //basic offset table start + EncodeWithBasicOffsetTable(of, zsize, bots); +#else + EncodeWithoutBasicOffsetTable(of, 1); +#endif + uint8_t *pImageData = data; + for(int i=0; itellp(); + gdcm_write_JPEG2000_file(of, (char*)pImageData,size, + image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(), + image->GetBitsAllocated(), sign, 100); + //userData, UserDataSize); + // CreateOneFrame(of, pImageData, fragment_size, xsize, ysize, zsize, + // samplesPerPixel, quality, JpegFragmentSize); + //assert( !(fragment_size % 2) ); + // Update the JpegVector with offset + size_t end = of->tellp(); + //static int i = 0; + JpegPair &jp = JpegFragmentSize[i]; + jp.second = end-beg; + if( ((end-beg) % 2) ) + { + of->put( '\0' ); + jp.second += 1; + } + assert( !(jp.second % 2) ); + //std::cerr << "DIFF: " << i <<" -> " << jp.second << std::endl; + //++i; + pImageData += fragment_size; + } + CloseJpeg(of, JpegFragmentSize); +#if WITHOFFSETTABLE + UpdateBasicOffsetTable(of, JpegFragmentSize, bots); +#endif + + + size_t of_size = of->str().size(); + UserData = new uint8_t[of_size]; + memcpy(UserData, of->str().c_str(), of_size); + UserDataSize = of_size; + +} + +bool gdcm_write_JPEG_file8 (std::ostream *fp, char *inputdata, size_t inputlength, + int image_width, int image_height, int numZ, + int sample_pixel, int bitsallocated, int quality); +bool gdcm_write_JPEG_file12 (std::ostream *fp, char *inputdata, size_t inputlength, + int image_width, int image_height, int numZ, + int sample_pixel, int bitsallocated, int quality); +bool gdcm_write_JPEG_file16 (std::ostream *fp, char *inputdata, size_t inputlength, + int image_width, int image_height, int numZ, + int sample_pixel, int bitsallocated, int quality); + +void PixelWriteConvert::SetCompressJPEGUserData(uint8_t *data, size_t size, File *image) +{ + + std::cerr << "entree ds PixelWriteConvert::SetCompressJPEGUserData" << std::endl; + + (void)data; + (void)size; + (void)image; + Compressed = true; + //char * userData = reinterpret_cast(UserData); + + std::ostringstream *of = new std::ostringstream(); + int xsize = image->GetXSize(); + int ysize = image->GetYSize(); + int zsize = image->GetZSize(); + int samplesPerPixel = image->GetSamplesPerPixel(); + //std::cout << "X: " << xsize << std::endl; + //std::cout << "Y: " << ysize << std::endl; + //std::cout << "Sample: " << samplesPerPixel << std::endl; + int bitsallocated = image->GetBitsAllocated(); + unsigned int fragment_size = xsize*ysize*samplesPerPixel * (bitsallocated / 8); + assert( fragment_size*zsize == size ); + + JpegVector JpegFragmentSize; +#if WITHOFFSETTABLE + size_t bots; //basic offset table start + EncodeWithBasicOffsetTable(of, zsize, bots); +#else + EncodeWithoutBasicOffsetTable(of, 1); +#endif + uint8_t *pImageData = data; + for(int i=0; itellp(); + if( bitsallocated == 8 ) + { + gdcm_write_JPEG_file8(of, (char*)pImageData,size, + image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(), + image->GetBitsAllocated(), 100 ); + } + else if (bitsallocated <= 12) + { + assert( bitsallocated >= 8 ); + gdcm_write_JPEG_file12(of, (char*)pImageData,size, + image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(), + image->GetBitsAllocated(), 100); + } + else if (bitsallocated <= 16) + { + assert( bitsallocated >= 12 ); + gdcm_write_JPEG_file16(of, (char*)pImageData,size, + image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(), + image->GetBitsAllocated(), 100); + } + else + { + abort(); + } + size_t end = of->tellp(); + //static int i = 0; + JpegPair &jp = JpegFragmentSize[i]; + jp.second = end-beg; + if( ((end-beg) % 2) ) + { + of->put( '\0' ); + jp.second += 1; + } + assert( !(jp.second % 2) ); + //std::cerr << "DIFF: " << i <<" -> " << jp.second << std::endl; + //++i; + + //JpegPair &jp = v[0]; + //jp.second = 15328; + + + //userData, UserDataSize); + // CreateOneFrame(of, pImageData, fragment_size, xsize, ysize, zsize, + // samplesPerPixel, quality, JpegFragmentSize); + //assert( !(fragment_size % 2) ); + pImageData += fragment_size; + } + CloseJpeg(of, JpegFragmentSize); +#if WITHOFFSETTABLE + UpdateBasicOffsetTable(of, JpegFragmentSize, bots); +#endif + + + size_t of_size = of->str().size(); + UserData = new uint8_t[of_size]; + memcpy(UserData, of->str().c_str(), of_size); + UserDataSize = of_size; + + std::cerr << "Sortie ds PixelWriteConvert::SetCompressJPEGUserData" << std::endl; +} + + //----------------------------------------------------------------------------- // Protected +//bool PixelWriteConvert::CompressJPEG2000(uint8_t *data, size_t size) +//{ +//} //----------------------------------------------------------------------------- // Private diff --git a/src/gdcmPixelWriteConvert.h b/src/gdcmPixelWriteConvert.h index 59ddb914..c71ff5c9 100644 --- a/src/gdcmPixelWriteConvert.h +++ b/src/gdcmPixelWriteConvert.h @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmPixelWriteConvert.h,v $ Language: C++ - Date: $Date: 2007/05/23 14:18:11 $ - Version: $Revision: 1.9 $ + Date: $Date: 2007/07/13 08:17:21 $ + Version: $Revision: 1.10 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -31,6 +31,7 @@ namespace GDCM_NAME_SPACE * \warning None of the methods may be called by end user (they have no * meaning outside the class FileHelper) */ +class File; class GDCM_EXPORT PixelWriteConvert : public Base { friend class FileHelper; @@ -57,6 +58,9 @@ private: uint8_t *GetData(); size_t GetDataSize(); + void SetCompressJPEG2000UserData(uint8_t *data, size_t size, File *image); + void SetCompressJPEGUserData(uint8_t *data, size_t size, File *image); + // Variables /// Pixel data represented as RGB after LUT color interpretation. uint8_t *ReadData; @@ -67,6 +71,9 @@ private: uint8_t *UserData; /// Size of User image. size_t UserDataSize; + + /// Whether we want to write compressed + bool Compressed; }; } // end namespace gdcm diff --git a/vtk/vtkGdcmReader.h b/vtk/vtkGdcmReader.h index c3da1302..620e7d5a 100644 --- a/vtk/vtkGdcmReader.h +++ b/vtk/vtkGdcmReader.h @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: vtkGdcmReader.h,v $ Language: C++ - Date: $Date: 2007/06/19 13:09:45 $ - Version: $Revision: 1.33 $ + Date: $Date: 2007/07/13 08:17:22 $ + Version: $Revision: 1.34 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -55,7 +55,7 @@ public: //BTX - /// \TODO fix possible problems around VTK pipelining + /// \todo fix possible problems around VTK pipelining void SetUserFunction (VOID_FUNCTION_PUINT8_PFILE_POINTER userFunc ) { UserFunction = userFunc; }