#include "gdcmFile.h"
#include "gdcmUtil.h"
+
+
+// TODO : remove DEBUG
+#define DEBUG 0
+
+
#include "iddcmjpeg.h"
+using namespace std;
/////////////////////////////////////////////////////////////////
/**
SetPixelDataSizeFromHeader();
}
-
-/////////////////////////////////////////////////////////////////
/**
* \ingroup gdcmFile
* \brief calcule la longueur (in bytes) A ALLOUER pour recevoir les
- * pixels de l'image
+ * pixels de l'image
* ou DES images dans le cas d'un multiframe
* ATTENTION : il ne s'agit PAS de la longueur du groupe des Pixels
* (dans le cas d'images compressees, elle n'a pas de sens).
*
* @return longueur a allouer
*/
-
void gdcmFile::SetPixelDataSizeFromHeader(void) {
int nb;
string str_nb;
nb = atoi(str_nb.c_str() );
if (nb == 12) nb =16;
}
- lgrTotale = GetXSize() * GetYSize() * GetZSize() * (nb/8);
+ lgrTotale = GetXSize() * GetYSize() * GetZSize() * (nb/8)* GetSamplesPerPixel();;
}
+/////////////////////////////////////////////////////////////////
/**
* \ingroup gdcmFile
- * \brief Accessor
+ * \brief Returns the size (in bytes) of required memory to hold
+ * the pixel data represented in this file.
+ * @return The size of pixel data in bytes.
*/
size_t gdcmFile::GetImageDataSize(void) {
return (lgrTotale);
}
+/////////////////////////////////////////////////////////////////
/**
* \ingroup gdcmFile
* \brief Read pixel data from disk (optionaly decompressing) into the
bool gdcmFile::ReadPixelData(void* destination) {
if ( !OpenFile())
return false;
- if ( fseek(fp, GetPixelOffset(), SEEK_SET) == -1 ) {
+
+ printf("GetPixelOffset() %d\n",GetPixelOffset() );
+
+ if ( fseek(fp, GetPixelOffset(), SEEK_SET) == -1 ) {
CloseFile();
return false;
- }
- if (IsJPEGLossless()) {
- destination = _IdDcmJpegRead(fp);
- } else {
+ }
+
+ if ( !IsDicomV3() ||
+ IsImplicitVRLittleEndianTransferSyntax() ||
+ IsExplicitVRLittleEndianTransferSyntax() ||
+ IsExplicitVRBigEndianTransferSyntax() ||
+ IsDeflatedExplicitVRLittleEndianTransferSyntax() ) {
+
size_t ItemRead = fread(destination, lgrTotale, 1, fp);
if ( ItemRead != 1 ) {
CloseFile();
return false;
+ } else {
+ CloseFile();
+ return true;
}
- }
- CloseFile();
- return true;
+ }
+
+ // ------------------------------- Position on begining of Jpeg Pixels
+
+ int ln;
+ fseek(fp,4,SEEK_CUR);
+ fread(&ln,4,1,fp);
+ if(GetSwapCode())
+ ln=SwapLong(ln);
+ if (DEBUG)
+ printf ("ln %d\n",ln);
+ fseek(fp,ln,SEEK_CUR);
+ fseek(fp,4,SEEK_CUR);
+ fread(&ln,4,1,fp);
+ if(GetSwapCode())
+ ln=SwapLong(ln);
+ if (DEBUG)
+ printf ("ln image comprimée %d\n",ln);
+
+
+ // ------------------------------- JPEG LossLess : call to Jpeg Libido
+
+ if (IsJPEGLossless()) {
+
+ ClbJpeg* jpg = _IdDcmJpegRead(fp);
+ if(jpg == NULL) {
+ CloseFile();
+ return false;
+ }
+ // Gros soucis :
+ // jpg->DataImg est alloue en int32 systematiquement :
+ // il faut le copier pixel par pixel dans destination ...
+ // ... qui est un void *
+ // --> du CAST sportif a faire ...
+
+ // memcpy(destination,jpg->DataImg,lgrTotale);
+
+ // Bon ...
+ // ... y'a p't etre + ruse (?)
+
+ int nb;
+ string str_nb=gdcmHeader::GetPubElValByNumber(0x0028,0x0100);
+ if (str_nb == "gdcm::Unfound" ) {
+ nb = 16;
+ } else {
+ nb = atoi(str_nb.c_str() );
+ if (nb == 12) nb =16;
+ }
+ int nBytes= nb/8;
+ int * dataJpg = jpg->DataImg;
+ int taille = GetXSize() * GetYSize() * GetZSize() * GetSamplesPerPixel();
+
+ switch (nBytes) {
+
+ case 1:
+ {
+ unsigned short *dest = (unsigned short *)destination;
+ for (int i=0; i<taille; i++) {
+ if (DEBUG)
+ if (*(dataJpg +i) >255) printf("data %d\n",*(dataJpg +i) );
+ *((unsigned char *)dest+i) = *(dataJpg +i);
+ }
+ }
+ break;
+
+ case 2:
+ {
+ unsigned short *dest = (unsigned short *)destination;
+
+ // etonnant (?)
+ // la ligne commentee ci-dessous fait passer l'exec de 0.15 sec a 5.5 sec
+ // pour la meme image 512*512 ...
+ // optimiseur pas mis en oeuvre (?)
+ //for (int i=0; i<GetXSize() * GetYSize() * GetZSize(); i++) {
+
+ for (int i=0; i<taille; i++) {
+ *((unsigned short *)dest+i) = *(dataJpg +i);
+ }
+ }
+ break;
+
+ case 4:
+ {
+ unsigned int *dest=(unsigned int *)destination;
+ for (int i=0;i<taille; i++) {
+ *((unsigned int *)dest+i) = *(dataJpg +i);
+ }
+ }
+ break;
+ }
+
+ _IdDcmJpegFree (jpg);
+ return true;
+ }
+
+ // ------------------------------- JPEG Lossy : call to IJG 6b
+
+ // TODO : faire qq chose d'intelligent pour limiter
+ // la duplication du code JPEG <bits=8 / bits=12>
+ // TODO : eplucher icelui pour traiter *egalement* bits=16
+ int nBS;
+ if ((nBS = GetBitsStored()) != 12) {
+ printf("Sorry, Bits Stored = %d not yet taken into account\n",nBS);
+ return false;
+ }
+
+ int res = gdcm_read_JPEG_file (destination);
+ if (DEBUG)
+ printf ("res : %d\n",res);
+ return res;
+
}
-/////////////////////////////////////////////////////////////////
/**
* \ingroup gdcmFile
* \brief Allocates necessary memory, copies the pixel data
- * (image[s]/volume[s]) to newly allocated zone and return a
- * pointer to it:
+ * (image[s]/volume[s]) to newly allocated zone.
+ * @return Pointer to newly allocated pixel data.
*/
void * gdcmFile::GetImageData (void) {
PixelData = (void *) malloc(lgrTotale);
return(PixelData);
}
-/////////////////////////////////////////////////////////////////
/**
- * \ingroup gdcmFile
- * \brief amene en mémoire dans une zone précisee par l'utilisateur
- * les Pixels d'une image
- *
- * @param destination
- * @param MaxSize
- *
- * @return The number of bytes actually copied.
+ * \ingroup gdcmFile
+ * \brief Copies at most MaxSize bytes of pixel data to caller's
+ * memory space.
+ * @param destination Address (in caller's memory space) at which the
+ * pixel data should be copied
+ * @param MaxSize Maximum number of bytes to be copied. When MaxSize
+ * is not sufficient to hold the pixel data the copy is not
+ * executed (i.e. no partial copy).
+ * @return On success, the number of bytes actually copied. Zero on
+ * failure e.g. MaxSize is lower than necessary.
*/
size_t gdcmFile::GetImageDataIntoVector (void* destination, size_t MaxSize) {
* \ingroup gdcmFile
* \brief TODO JPR
* \warning doit-etre etre publique ? FIXME JPR
+ * TODO : y a-t-il un inconvenient à fusioner ces 2 fonctions
*
* @param inData TODO JPR
* @param ExpectedSize TODO JPR
SetImageDataSize(ExpectedSize);
PixelData = inData;
lgrTotale = ExpectedSize;
+
+
return(1);
}
* \brief TODO JPR
* \
* \warning WARNING doit-etre etre publique ? FIXME JPR
+ * TODO : y aurait il un inconvenient à fusionner ces 2 fonctions
*
* @param ImageDataSize TODO JPR
*
void gdcmFile::SetImageDataSize(size_t ImageDataSize) {
string content1;
- string content2;
char car[20];
// suppose que le ElValue (0x7fe0, 0x0010) existe ...
sprintf(car,"%d",ImageDataSize);
- content2=car;
- SetPubElValByNumber(content2, 0x7fe0, 0x0010);
-
+
+ gdcmElValue*a = GetElValueByNumber(0x7fe0, 0x0010);
+ a->SetLength(ImageDataSize);
+
ImageDataSize+=8;
sprintf(car,"%d",ImageDataSize);
content1=car;
return WriteBase(nomFichier, ImplicitVR);
}
+/////////////////////////////////////////////////////////////////
+/**
+ * \ingroup gdcmFile
+ *
+ * @param nomFichier TODO JPR
+ *
+ * @return TODO JPR
+ */
+
int gdcmFile::WriteDcmImplVR (const char* nomFichier) {
return WriteDcmImplVR (string (nomFichier));
}
return WriteBase(nomFichier, ACR);
}
+/////////////////////////////////////////////////////////////////
+/**
+ * \ingroup gdcmFile
+ *
+ * @param nomFichier TODO JPR
+ * @param type TODO JPR
+ *
+ * @return TODO JPR
+ */
int gdcmFile::WriteBase (string nomFichier, FileType type) {
FILE * fp1;