+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Private
+/**
+ * \brief Swap the bytes, according to swap code.
+ * \warning not end user intended
+ * @param im area to deal with
+ * @param swap swap code
+ * @param lgr Area Length
+ * @param nb Pixels Bit number
+ */
+void gdcmFile::SwapZone(void* im, int swap, int lgr, int nb)
+{
+ int i;
+
+ if( nb == 16 )
+ {
+ uint16_t* im16 = (uint16_t*)im;
+ switch( swap )
+ {
+ case 0:
+ case 12:
+ case 1234:
+ break;
+ case 21:
+ case 3412:
+ case 2143:
+ case 4321:
+ for(i=0; i < lgr/2; i++)
+ {
+ im16[i]= (im16[i] >> 8) | (im16[i] << 8 );
+ }
+ break;
+ default:
+ std::cout << "SWAP value (16 bits) not allowed :i" << swap <<
+ std::endl;
+ }
+ }
+ else if( nb == 32 )
+ {
+ uint32_t s32;
+ uint16_t fort, faible;
+ uint32_t* im32 = (uint32_t*)im;
+ switch ( swap )
+ {
+ case 0:
+ case 1234:
+ break;
+ case 4321:
+ for(i = 0; i < lgr/4; i++)
+ {
+ faible = im32[i] & 0x0000ffff; // 4321
+ fort = im32[i] >> 16;
+ fort = ( fort >> 8 ) | ( fort << 8 );
+ faible = ( faible >> 8 ) | ( faible << 8);
+ s32 = faible;
+ im32[i] = ( s32 << 16 ) | fort;
+ }
+ break;
+ case 2143:
+ for(i = 0; i < lgr/4; i++)
+ {
+ faible = im32[i] & 0x0000ffff; // 2143
+ fort = im32[i] >> 16;
+ fort = ( fort >> 8 ) | ( fort << 8 );
+ faible = ( faible >> 8) | ( faible << 8);
+ s32 = fort;
+ im32[i] = ( s32 << 16 ) | faible;
+ }
+ break;
+ case 3412:
+ for(i = 0; i < lgr/4; i++)
+ {
+ faible = im32[i] & 0x0000ffff; // 3412
+ fort = im32[i] >> 16;
+ s32 = faible;
+ im32[i] = ( s32 << 16 ) | fort;
+ }
+ break;
+ default:
+ std::cout << "SWAP value (32 bits) not allowed : " << swap <<
+ std::endl;
+ }
+ }
+}
+
+/**
+ * \brief Read pixel data from disk (optionaly decompressing) into the
+ * caller specified memory location.
+ * @param destination where the pixel data should be stored.
+ *
+ */
+bool gdcmFile::ReadPixelData(void* destination)
+{
+ FILE* fp = Header->OpenFile();
+
+ if ( !fp )
+ {
+ return false;
+ }
+ if ( fseek(fp, Header->GetPixelOffset(), SEEK_SET) == -1 )
+ {
+ Header->CloseFile();
+ return false;
+ }
+
+ if ( Header->GetBitsAllocated() == 12 )
+ {
+ ConvertDecompress12BitsTo16Bits( (uint8_t*)destination,
+ Header->GetXSize(),
+ Header->GetYSize(),
+ fp);
+ Header->CloseFile();
+ return true;
+ }
+
+ // ---------------------- Uncompressed File
+ if ( !Header->IsDicomV3() ||
+ Header->IsImplicitVRLittleEndianTransferSyntax() ||
+ Header->IsExplicitVRLittleEndianTransferSyntax() ||
+ Header->IsExplicitVRBigEndianTransferSyntax() ||
+ Header->IsDeflatedExplicitVRLittleEndianTransferSyntax() )
+ {
+ size_t ItemRead = fread(destination, Header->GetPixelAreaLength(), 1, fp);
+ Header->CloseFile();
+ if ( ItemRead != 1 )
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ // ---------------------- Run Length Encoding
+ if ( Header->IsRLELossLessTransferSyntax() )
+ {
+ bool res = gdcm_read_RLE_file (fp,destination);
+ Header->CloseFile();
+ return res;
+ }
+
+ // --------------- SingleFrame/Multiframe JPEG Lossless/Lossy/2000
+ int numberBitsAllocated = Header->GetBitsAllocated();
+ if ( ( numberBitsAllocated == 0 ) || ( numberBitsAllocated == 12 ) )
+ {
+ numberBitsAllocated = 16;
+ }
+
+ int nBytes= numberBitsAllocated/8;
+ int taille = Header->GetXSize() * Header->GetYSize()
+ * Header->GetSamplesPerPixel();
+ long fragmentBegining; // for ftell, fseek
+
+ bool jpg2000 = Header->IsJPEG2000();
+ bool jpgLossless = Header->IsJPEGLossless();
+
+ bool res = true;
+ uint16_t ItemTagGr, ItemTagEl;
+ int ln;
+
+ // Position on begining of Jpeg Pixels
+
+ fread(&ItemTagGr,2,1,fp); // Reading (fffe) : Item Tag Gr
+ fread(&ItemTagEl,2,1,fp); // Reading (e000) : Item Tag El
+ if(Header->GetSwapCode())
+ {
+ ItemTagGr = Header->SwapShort(ItemTagGr);
+ ItemTagEl = Header->SwapShort(ItemTagEl);
+ }
+
+ fread(&ln,4,1,fp);
+ if( Header->GetSwapCode() )
+ {
+ ln = Header->SwapLong( ln ); // Basic Offset Table Item length
+ }
+
+ if ( ln != 0 )
+ {
+ // What is it used for ?!?
+ uint8_t* BasicOffsetTableItemValue = new uint8_t[ln+1];
+ fread(BasicOffsetTableItemValue,ln,1,fp);
+ //delete[] BasicOffsetTableItemValue;
+ }
+
+ // first Fragment initialisation
+ fread(&ItemTagGr,2,1,fp); // Reading (fffe) : Item Tag Gr
+ fread(&ItemTagEl,2,1,fp); // Reading (e000) : Item Tag El
+ if( Header->GetSwapCode() )
+ {
+ ItemTagGr = Header->SwapShort( ItemTagGr );
+ ItemTagEl = Header->SwapShort( ItemTagEl );
+ }
+
+ // parsing fragments until Sequence Delim. Tag found
+ while ( ItemTagGr == 0xfffe && ItemTagEl != 0xe0dd )
+ {
+ // --- for each Fragment
+ fread(&ln,4,1,fp);
+ if( Header->GetSwapCode() )
+ {
+ ln = Header->SwapLong(ln); // Fragment Item length
+ }
+ fragmentBegining = ftell( fp );
+
+ if ( jpg2000 )
+ {
+ // JPEG 2000 : call to ???
+ res = gdcm_read_JPEG2000_file (fp,destination); // Not Yet written
+ // ------------------------------------- endif (JPEG2000)
+ }
+ else if (jpgLossless)
+ {
+ // JPEG LossLess : call to xmedcom Lossless JPEG
+ // Reading Fragment pixels
+ JPEGLosslessDecodeImage (fp, (uint16_t*)destination,
+ Header->GetPixelSize() * 8 * Header->GetSamplesPerPixel(), ln);
+ res = 1; // in order not to break the loop
+
+ } // ------------------------------------- endif (JPEGLossless)
+ else
+ {
+ // JPEG Lossy : call to IJG 6b
+ if ( Header->GetBitsStored() == 8)
+ {
+ // Reading Fragment pixels
+ res = gdcm_read_JPEG_file (fp,destination);
+ }
+ else
+ {
+ // Reading Fragment pixels
+ res = gdcm_read_JPEG_file12 (fp,destination);
+ }
+ // ------------------------------------- endif (JPEGLossy)
+ }
+
+ if ( !res )
+ {
+ break;
+ }
+
+ // location in user's memory
+ // for next fragment (if any)
+ destination = (uint8_t*)destination + taille * nBytes;
+
+ fseek(fp,fragmentBegining, SEEK_SET); // To be sure we start
+ fseek(fp,ln,SEEK_CUR); // at the begining of next fragment
+
+ ItemTagGr = ItemTagEl = 0;
+ fread(&ItemTagGr,2,1,fp); // Reading (fffe) : Item Tag Gr
+ fread(&ItemTagEl,2,1,fp); // Reading (e000) : Item Tag El
+ if( Header->GetSwapCode() )
+ {
+ ItemTagGr = Header->SwapShort( ItemTagGr );
+ ItemTagEl = Header->SwapShort( ItemTagEl );
+ }
+ }
+ // endWhile parsing fragments until Sequence Delim. Tag found
+
+ Header->CloseFile();
+ return res;
+}
+
+/**
+ * \brief Read from file a 12 bits per pixel image and uncompress it
+ * into a 16 bits per pixel image.
+ */
+void gdcmFile::ConvertDecompress12BitsTo16Bits(
+ uint8_t* pixelZone,
+ int sizeX,
+ int sizeY,
+ FILE* filePtr)
+ throw ( gdcmFormatError )
+{
+ int nbPixels = sizeX * sizeY;
+ uint16_t* destination = (uint16_t*)pixelZone;
+
+ for( int p = 0; p < nbPixels; p += 2 )
+ {
+ uint8_t b0, b1, b2;
+ size_t ItemRead;
+
+ ItemRead = fread( &b0, 1, 1, filePtr);
+ if ( ItemRead != 1 )
+ {
+ throw gdcmFormatError( "gdcmFile::ConvertDecompress12BitsTo16Bits()",
+ "Unfound first block" );
+ }
+
+ ItemRead = fread( &b1, 1, 1, filePtr);
+ if ( ItemRead != 1 )
+ {
+ throw gdcmFormatError( "gdcmFile::ConvertDecompress12BitsTo16Bits()",
+ "Unfound second block" );
+ }
+
+ ItemRead = fread( &b2, 1, 1, filePtr);
+ if ( ItemRead != 1 )
+ {
+ throw gdcmFormatError( "gdcmFile::ConvertDecompress12BitsTo16Bits()",
+ "Unfound second block" );
+ }
+
+ // Two steps are necessary to please VC++
+ //
+ // 2 pixels 12bit = [0xABCDEF]
+ // 2 pixels 16bit = [0x0ABD] + [0x0FCE]
+ // A B D
+ *destination++ = ((b0 >> 4) << 8) + ((b0 & 0x0f) << 4) + (b1 & 0x0f);
+ // F C E
+ *destination++ = ((b2 & 0x0f) << 8) + ((b1 >> 4) << 4) + (b2 >> 4);
+
+ /// \todo JPR Troubles expected on Big-Endian processors ?
+ }