Produced by Araxis Merge on 12/5/2017 12:06:44 PM Central Standard Time. See www.araxis.com for information about Merge. This report uses XHTML and CSS2, and is best viewed with a modern standards-compliant browser. For optimum results when printing this report, use landscape orientation and enable printing of background images and colours in your browser.
| # | Location | File | Last Modified |
|---|---|---|---|
| 1 | IV-eHMP_CIF.zip\IMAG_Source\VISA\Java\ImagingDicomDCFUtilities\src\java\gov\va\med\imaging\dicom\dcftoolkit\utilities\reconstitution | LegacyTGAFileParser.java | Mon Dec 4 21:35:16 2017 UTC |
| 2 | IV-eHMP_CIF.zip\IMAG_Source\VISA\Java\ImagingDicomDCFUtilities\src\java\gov\va\med\imaging\dicom\dcftoolkit\utilities\reconstitution | LegacyTGAFileParser.java | Mon Dec 4 22:02:43 2017 UTC |
| Description | Between Files 1 and 2 |
|
|---|---|---|
| Text Blocks | Lines | |
| Unchanged | 2 | 2044 |
| Changed | 1 | 2 |
| Inserted | 0 | 0 |
| Removed | 0 | 0 |
| Whitespace | |
|---|---|
| Character case | Differences in character case are significant |
| Line endings | Differences in line endings (CR and LF characters) are ignored |
| CR/LF characters | Not shown in the comparison detail |
No regular expressions were active.
| 1 | /** | |
| 2 | * | |
| 3 | Package: MAG - Vis tA Imaging | |
| 4 | WARNING: Per VHA D irective 2 004-038, t his routin e should n ot be modi fied. | |
| 5 | Date Cre ated: Sept ember 26, 2005 | |
| 6 | Site Nam e: Washin gton OI Fi eld Office , Silver S pring, MD | |
| 7 | Developer:
|
|
| 8 | Descript ion: | |
| 9 | ||
| 10 | ;; +-------- ---------- ---------- ---------- ---------- ---------- ---------- + | |
| 11 | ;; Property of the US Government . | |
| 12 | ;; No permis sion to co py or redi stribute t his softwa re is give n. | |
| 13 | ;; Use of un released v ersions of this soft ware requi res the us er | |
| 14 | ;; to execu te a writt en test ag reement wi th the Vis tA Imaging | |
| 15 | ;; Developm ent Office of the De partment o f Veterans Affairs, | |
| 16 | ;; telephon e (301) 73 4-0100. | |
| 17 | ;; | |
| 18 | ;; The Food and Drug A dministrat ion classi fies this software a s | |
| 19 | ;; a Class I I medical device. A s such, it may not b e changed | |
| 20 | ;; in any wa y. Modifi cations to this soft ware may r esult in a n | |
| 21 | ;; adulterat ed medical device un der 21CFR8 20, the us e of which | |
| 22 | ;; is consid ered to be a violati on of US F ederal Sta tutes. | |
| 23 | ;; +-------- ---------- ---------- ---------- ---------- ---------- ---------- + | |
| 24 | */ | |
| 25 | package go v.va.med.i maging.dic om.dcftool kit.utilit ies.recons titution; | |
| 26 | ||
| 27 | import gov .va.med.im aging.Size dInputStre am; | |
| 28 | import gov .va.med.im aging.dico m.common.i nterfaces. IDicomData Set; | |
| 29 | import gov .va.med.im aging.dico m.dcftoolk it.utiliti es.excepti ons.TGAFil eException ; | |
| 30 | import gov .va.med.im aging.dico m.dcftoolk it.utiliti es.excepti ons.TGAFil eNotFoundE xception; | |
| 31 | import gov .va.med.im aging.exch ange.busin ess.dicom. DicomGatew ayConfigur ation; | |
| 32 | import gov .va.med.im aging.exch ange.busin ess.dicom. GatewayDic tionaryCon tents; | |
| 33 | import gov .va.med.im aging.exch ange.busin ess.dicom. ModalityDi cInfo; | |
| 34 | import gov .va.med.im aging.exch ange.busin ess.dicom. ParameterD eviceInfo; | |
| 35 | import gov .va.med.im aging.exch ange.busin ess.dicom. Parameters ; | |
| 36 | import gov .va.med.im aging.exch ange.busin ess.dicom. exceptions .Parameter Decomposit ionExcepti on; | |
| 37 | ||
| 38 | import jav a.io.FileI nputStream ; | |
| 39 | import jav a.io.FileN otFoundExc eption; | |
| 40 | import jav a.io.IOExc eption; | |
| 41 | import jav a.nio.Byte Buffer; | |
| 42 | import jav a.nio.Byte Order; | |
| 43 | import jav a.nio.Mapp edByteBuff er; | |
| 44 | import jav a.nio.chan nels.FileC hannel; | |
| 45 | import jav a.nio.chan nels.FileC hannel.Map Mode; | |
| 46 | import jav a.text.Par seExceptio n; | |
| 47 | import jav a.text.Sim pleDateFor mat; | |
| 48 | import jav a.util.Dat e; | |
| 49 | import jav a.util.Ite rator; | |
| 50 | import jav a.util.Vec tor; | |
| 51 | ||
| 52 | import org .apache.lo gging.log4 j.LogManag er; | |
| 53 | import org .apache.lo gging.log4 j.Logger; | |
| 54 | ||
| 55 | import com .lbs.DCS.A ttributeTa g; | |
| 56 | import com .lbs.DCS.D CM; | |
| 57 | import com .lbs.DCS.D CSExceptio n; | |
| 58 | import com .lbs.DCS.D icomCSElem ent; | |
| 59 | import com .lbs.DCS.D icomDataSe t; | |
| 60 | import com .lbs.DCS.D icomElemen t; | |
| 61 | import com .lbs.DCS.D icomFileIn put; | |
| 62 | import com .lbs.DCS.D icomOBElem ent; | |
| 63 | import com .lbs.DCS.D icomOWElem ent; | |
| 64 | import com .lbs.DCS.U ID; | |
| 65 | ||
| 66 | //FUTURE C onsider ch anging cod e to insta ntiate the parsers o nce. This requires moving | |
| 67 | // al l instance variables . | |
| 68 | /** | |
| 69 | * | |
| 70 | * @author William P eterson | |
| 71 | * | |
| 72 | */ | |
| 73 | public cla ss LegacyT GAFilePars er { | |
| 74 | ||
| 75 | privat e String t gaFile = n ull; | |
| 76 | ||
| 77 | privat e boolean bigFileFla g; | |
| 78 | ||
| 79 | privat e DicomDat aSet toolk itDDS = nu ll; | |
| 80 | ||
| 81 | privat e short tg aRows = 0; | |
| 82 | ||
| 83 | privat e short tg aColumns = 0; | |
| 84 | ||
| 85 | privat e byte tga BitsPerPix el = 0; | |
| 86 | ||
| 87 | privat e int imag ePlanes = 0; | |
| 88 | ||
| 89 | privat e boolean isImageRed uced = fal se; | |
| 90 | ||
| 91 | privat e Original PixelDataI nfo origin alPixelDat aInfo = nu ll; | |
| 92 | ||
| 93 | privat e String a cquisition Site = nul l; | |
| 94 | ||
| 95 | privat e ByteBuff er imageBu ffer=null; | |
| 96 | ||
| 97 | privat e static f inal Logge r logger = LogManage r.getLogge r (LegacyT GAFilePars er.class); | |
| 98 | ||
| 99 | /** | |
| 100 | * Con structor | |
| 101 | */ | |
| 102 | public LegacyTGA FileParser () { | |
| 103 | su per(); | |
| 104 | } | |
| 105 | ||
| 106 | public void upda teDicomDat aSetWithPi xelData(ID icomDataSe t dds, | |
| 107 | String t gaFile, Or iginalPixe lDataInfo originalPi xelDataInf o) | |
| 108 | throws T GAFileNotF oundExcept ion, TGAFi leExceptio n{ | |
| 109 | ||
| 110 | lo gger.info( this.getCl ass().getN ame()+": D icom Toolk it Layer: " + | |
| 111 | "par sing TGA f ile to Dic omDataSet ..."); | |
| 112 | ||
| 113 | th is.origina lPixelData Info = ori ginalPixel DataInfo; | |
| 114 | th is.acquisi tionSite = dds.getAc quisitionS ite(); | |
| 115 | // Extract th e DCF Dico mDataSet o bject out of dicomDa taSet. | |
| 116 | th is.toolkit DDS = (Dic omDataSet) dds.getDic omDataSet( ); | |
| 117 | tr y{ | |
| 118 | bigF ileFlag=tg aFile.toLo werCase(). endsWith(" .big"); | |
| 119 | ||
| 120 | if(! bigFileFla g){ | |
| 121 | tgaFil e = tgaFil e.toLowerC ase(); | |
| 122 | tgaFil e = tgaFil e.replace( ".big", ". tga"); | |
| 123 | logger .warn(this .getClass( ).getName( )+": DICOM Toolkit l ayer: \n"+ | |
| 124 | ".BIG file does not exist. Re verting to subsample d .TGA fil e."); | |
| 125 | } | |
| 126 | ||
| 127 | if(this. isPart10Di comFile(tg aFile)){ | |
| 128 | logg er.error(t his.getCla ss().getNa me()+": DI COM Toolki t layer: \ n"+ | |
| 129 | "Should not be a D ICOM Part 10 file.") ; | |
| 130 | thro w new TGAF ileExcepti on("This i s a DICOM Part 10 Fi le."); | |
| 131 | } | |
| 132 | ||
| 133 | //JUNIT Create tes t to see h ow it fail s if not c orrect per missions. | |
| 134 | //Create a binary stream con nected to the TGA fi le. | |
| 135 | logger.d ebug("TGA filename: "+tgaFile) ; | |
| 136 | ||
| 137 | FileChan nel fc = n ew FileInp utStream(t gaFile).ge tChannel() ; | |
| 138 | MappedBy teBuffer b uffer = fc .map(MapMo de.READ_ON LY, 0, (in t)fc.size( )); | |
| 139 | byte hea der[] = ne w byte[18] ; | |
| 140 | // The 1 8 bytes re presents t he TGA hea der which we do not want in th e pixel da ta. | |
| 141 | // This makes sure the posit ion is at 18 instead of 0. | |
| 142 | buffer = (MappedBy teBuffer)b uffer.get( header, 0, 18); | |
| 143 | int tgaI mageBytes = processT gaHeader(h eader); | |
| 144 | ||
| 145 | // read in only TG A header s izing wort h of image data!! | |
| 146 | // (prev ent incons istent DIC OM file an d compress ion errors ) | |
| 147 | int imag eBytes = b uffer.capa city()-buf fer.positi on(); | |
| 148 | if ((ima geBytes > tgaImageBy tes) && (t gaImageByt es>0)) | |
| 149 | imag eBytes = t gaImageByt es; // pre vent incon sistent DI COM file a nd compres sion error s) | |
| 150 | // do a bulk push (transfer ) to the n ew ByteBuf fer object . The new ByteBuffer | |
| 151 | // will be assign to the Pi xel Data. | |
| 152 | imageBuf fer = Byte Buffer.all ocate(imag eBytes); | |
| 153 | imageBuf fer.put(bu ffer); | |
| 154 | ||
| 155 | processT gaData(dds ); | |
| 156 | } | |
| 157 | ca tch(FileNo tFoundExce ption nofi le){ | |
| 158 | logger.e rror("Erro r: " + nof ile.getMes sage()); | |
| 159 | logger.e rror(this. getClass() .getName() + ": Dico m Toolkit layer: " + | |
| 160 | "Exception thrown wh ile attemp ting to op en TGA fil e, " + tga File+"."); | |
| 161 | throw ne w TGAFileN otFoundExc eption("Co uld not fi nd or open " + tgaFi le+".", no file); | |
| 162 | } | |
| 163 | ca tch(IOExce ption ioe) { | |
| 164 | logger.e rror("Erro r: " + ioe .getMessag e()); | |
| 165 | logger.e rror(this. getClass() .getName() + ": Dico m Toolkit layer: " + | |
| 166 | "Exception thrown wh ile attemp ting to op en TGA fil e, " + tga File+"."); | |
| 167 | throw ne w TGAFileE xception(" Could not find or op en " + tga File + "." , ioe); | |
| 168 | } | |
| 169 | // INFO Keep in the bac k of your mind about if I need to explic it status LittleEndi an | |
| 170 | // or BigEn dian when transferri ng the act ual pixel data. | |
| 171 | } | |
| 172 | ||
| 173 | public void upda teDicomDat aSetWithPi xelData(ID icomDataSe t dds, | |
| 174 | Size dInputStre am sizedTg aStream, O riginalPix elDataInfo originalP ixelDataIn fo) | |
| 175 | throws T GAFileNotF oundExcept ion, TGAFi leExceptio n{ | |
| 176 | ||
| 177 | lo gger.info( "... Dicom Toolkit L ayer: pars ing TGA fi le stream to DicomDa taSet ..." ); | |
| 178 | ||
| 179 | th is.origina lPixelData Info = ori ginalPixel DataInfo; | |
| 180 | th is.acquisi tionSite = dds.getAc quisitionS ite(); | |
| 181 | / /Extract t he DCF Dic omDataSet object out of dicomD ataSet. | |
| 182 | th is.toolkit DDS = (Dic omDataSet) dds.getDic omDataSet( ); | |
| 183 | tr y{ | |
| 184 | //proces s the bina ry stream connected to the TGA file. | |
| 185 | logger.d ebug("... TGA file s tream proc essing ... "); | |
| 186 | int byte Size = siz edTgaStrea m.getByteS ize(); | |
| 187 | bigFileF lag = (byt eSize >= 1 048576); / / ** cpt . big if lar ger than a MB (used for CT log ic only!) | |
| 188 | byte hea der[] = ne w byte[18] ; | |
| 189 | // The 1 8 bytes re presents t he TGA hea der which we do not want in th e pixel da ta. | |
| 190 | // This makes sure the posit ion is at 18 instead of 0. | |
| 191 | int size Read = siz edTgaStrea m.getInStr eam().read (header, 0 , 18); | |
| 192 | if (size Read != 18 ) | |
| 193 | thro w new TGAF ileExcepti on("Could not read T GA file st ream heade r."); | |
| 194 | int tgaI mageBytes = processT gaHeader(h eader); | |
| 195 | ||
| 196 | // read in only TG A header s izing wort h of image data!! | |
| 197 | int imag eBytes = b yteSize-he ader.lengt h; | |
| 198 | if ((ima geBytes > tgaImageBy tes) && (t gaImageByt es>0)) | |
| 199 | imag eBytes = t gaImageByt es; // pre vent incon sistent DI COM file a nd compres sion error s) | |
| 200 | ||
| 201 | imageB uffer = By teBuffer.a llocate(im ageBytes); | |
| 202 | // do a bulk push (transfer ) to the n ew ByteBuf fer object . The new ByteBuffer | |
| 203 | // will be assign to the Pi xel Data. | |
| 204 | sizeRe ad = sized TgaStream. getInStrea m().read(i mageBuffer .array(), 0, imageBy tes); | |
| 205 | // LOGG ER.info(si zeRead + " bytes of " + imageB ytes + " i n imageBuf fer"); | |
| 206 | ||
| 207 | proces sTgaData(d ds); | |
| 208 | } | |
| 209 | ca tch(IOExce ption ioe) { | |
| 210 | logger.e rror("Erro r: " + ioe .getMessag e()); | |
| 211 | logger.e rror("Dico m Toolkit layer: Exc eption thr own while attempting to proces s TGA file stream.") ; | |
| 212 | } | |
| 213 | } | |
| 214 | ||
| 215 | privat e int proc essTgaHead er(byte[] header) | |
| 216 | throws TGAFileEx ception | |
| 217 | { | |
| 218 | in t tgaDataB yteSize=0; | |
| 219 | // Read Byte 2 (1 byte) to confir m it is a "3". If n ot throw e xception. | |
| 220 | if (header[2] != 3){ | |
| 221 | throw ne w TGAFileE xception() ; | |
| 222 | } | |
| 223 | // Read Bytes 12-13 for # of colu mns. | |
| 224 | th is.tgaColu mns = 0; | |
| 225 | th is.tgaColu mns |= (0x FF & heade r[13]); | |
| 226 | th is.tgaColu mns <<=8; | |
| 227 | th is.tgaColu mns |= (0x FF & heade r[12]); | |
| 228 | lo gger.debug ("TGA Numb er of Colu mns: " + t his.tgaCol umns); | |
| 229 | // Read Bytes 14-15 for # of rows . | |
| 230 | th is.tgaRows = 0; | |
| 231 | th is.tgaRows |= (0xFF & header[1 5]); | |
| 232 | th is.tgaRows <<=8; | |
| 233 | th is.tgaRows |= (0xFF & header[1 4]); | |
| 234 | lo gger.debug ("TGA Numb er of Rows : " + this .tgaRows); | |
| 235 | // Read Byte 16 for bit s/pixel. | |
| 236 | th is.tgaBits PerPixel = header[16 ]; | |
| 237 | lo gger.debug ("TGA Bits Per Pixel : " + this .tgaBitsPe rPixel); | |
| 238 | in t bytesAll ocated = ( this.tgaBi tsPerPixel > 8)? 2 : 1; | |
| 239 | tg aDataByteS ize = this .tgaRows * this.tgaC olumns * b ytesAlloca ted; | |
| 240 | re turn tgaDa taByteSize ; | |
| 241 | } | |
| 242 | ||
| 243 | //INFO Keep in t he back of your mind if we nee d explicit status Li ttleEndian | |
| 244 | // or BigEndian when tran sferring t he actual pixel data . | |
| 245 | privat e void pro cessTgaDat a(IDicomDa taSet dds) | |
| 246 | throws TGAFileEx ception | |
| 247 | { | |
| 248 | tr y { | |
| 249 | //SR S This is basically where we i ntroduce P atch 50 He ader fixes . | |
| 250 | //Update Pixel Mod ule with i nformation extracted above. | |
| 251 | this.upd ateImagePi xelInfo(); | |
| 252 | ||
| 253 | //Origin al if stat ement. MR IOD will not have t he same ru les applie d. Thus, I removed | |
| 254 | //MR IOD from if s tatement. Currently , we do no t alter th e MR IOD. | |
| 255 | //if(thi s.isImageC TIOD() || this.isIma geMRIOD()) { | |
| 256 | if(this. isImageCTI OD()){ | |
| 257 | this .updateCTI ODInformat ion(); | |
| 258 | } | |
| 259 | if(this. isMultiFra meIOD()){ | |
| 260 | this .updateMul tiFrameInf oToSingleF rameInfo() ; | |
| 261 | } | |
| 262 | this.che ckVendorCo mpression( ); | |
| 263 | this.upd atesForAll Modalities (); | |
| 264 | //IMRPOV E The foll owing line is active in Patch 66. Uncom ment it ba ck out and test it. | |
| 265 | // this. updateModa lityCode() ; // *** cpt must c heck if th is is ok!! | |
| 266 | //Read f rom Byte 1 8 until th e EOF. Pa ss into Pi xel Data e lement. S ave to DDS . | |
| 267 | //Images looked li ke crap. Had to add statement to resolv e byte ord er from .t ga file. | |
| 268 | imageBuf fer.order( ByteOrder. LITTLE_END IAN); | |
| 269 | if(this. originalPi xelDataInf o.getOrigi nalVR() == DCM.VR_OB ){ | |
| 270 | Dico mOBElement pixelData = new Dic omOBElemen t( | |
| 271 | new At tributeTag ("7FE0,001 0"), image Buffer); | |
| 272 | this .toolkitDD S.insert(p ixelData); | |
| 273 | } | |
| 274 | else if( this.origi nalPixelDa taInfo.get OriginalVR () == DCM. VR_OW){ | |
| 275 | Dico mOWElement pixelData = new Dic omOWElemen t( | |
| 276 | new At tributeTag ("7FE0,001 0"), image Buffer); | |
| 277 | this .toolkitDD S.insert(p ixelData); | |
| 278 | } | |
| 279 | else{ | |
| 280 | thro w new TGAF ileExcepti on("No mat ching VR f or Pixel D ata."); | |
| 281 | } | |
| 282 | //Encaps ulate the DicomDataS et. | |
| 283 | this.enc apsulateDi comDataSet (dds); | |
| 284 | } | |
| 285 | ca tch(DCSExc eption dcs e){ | |
| 286 | logger.e rror("Erro r: " + dcs e.getMessa ge()); | |
| 287 | logger.e rror("Dico m Toolkit layer: Exc eption thr own while attempting to proces s TGA data ."); | |
| 288 | throw ne w TGAFileE xception(" Could not process TG A data.", dcse); | |
| 289 | } | |
| 290 | } | |
| 291 | ||
| 292 | privat e IDicomDa taSet enca psulateDic omDataSet( IDicomData Set dds){ | |
| 293 | ||
| 294 | dd s.setDicom DataSet(th is.toolkit DDS); | |
| 295 | re turn dds; | |
| 296 | } | |
| 297 | ||
| 298 | privat e void upd ateImagePi xelInfo() throws DCS Exception{ | |
| 299 | bo olean isEn oughRows = false; | |
| 300 | bo olean isEn oughColumn s = false; | |
| 301 | bo olean isEn oughBits = false; | |
| 302 | bo olean isSa mplePerPix el = false ; | |
| 303 | ||
| 304 | // Some of Pa tch 50 wor k is locat ed in this method. I had to p erform thi s work rig ht here | |
| 305 | // and not somewhere else at a later date . | |
| 306 | ||
| 307 | // If Rows an d Columns from TGA i s smaller than those in dds. | |
| 308 | // Allow Colu mns-1 to b e accepted . This is due to od d column l ength reso lution. | |
| 309 | lo gger.debug ("Original number of Rows: " + this.tool kitDDS.get ElementStr ingValue(D CM.E_ROWS) ); | |
| 310 | if ((this.tga Rows == (s hort)this. toolkitDDS .getElemen tIntValue( DCM.E_ROWS ))){ | |
| 311 | isEnough Rows = tru e; | |
| 312 | } | |
| 313 | lo gger.debug ("Original number of Columns: " + this.t oolkitDDS. getElement StringValu e(DCM.E_CO LUMNS)); | |
| 314 | if ((this.tga Columns == (short)th is.toolkit DDS.getEle mentIntVal ue(DCM.E_C OLUMNS)) | |
| 315 | || (this.tgaC olumns == (short)((t his.toolki tDDS.getEl ementIntVa lue(DCM.E_ COLUMNS))- 1))){ | |
| 316 | isEnough Columns = true; | |
| 317 | //Had to add this insert() m ethod. Th is is beca use Column s-1 is acc epted, how ever | |
| 318 | // this is a diff erence tha t causes t he image t o be disto rted. | |
| 319 | this.too lkitDDS.in sert(DCM.E _COLUMNS, this.tgaCo lumns); | |
| 320 | } | |
| 321 | // Historical : We have always con verted fro m b16 to b 12 for CT images. H owever, th ere is | |
| 322 | // no missi ng data. The CT onl y used 12b its, not 1 6. This w as a commo n practice for CT | |
| 323 | // as well as some MR and a cou ple of CR/ DX images. The only time the image are really | |
| 324 | // reduced was when u sing the R factors. The R fac tors alway s took it down to 8b its. | |
| 325 | // Thus, an ything abo ve 8bits i s not a re duction. A b12 imag e that was a b16 sti ll | |
| 326 | // contains all the o riginal in formation. | |
| 327 | lo gger.debug ("Original number of Bits Stor ed: " + th is.toolkit DDS.getEle mentString Value(DCM. E_BITS_STO RED)); | |
| 328 | if ((this.tga BitsPerPix el == (byt e)this.too lkitDDS.ge tElementIn tValue(DCM .E_BITS_ST ORED)) | |
| 329 | || ( this.tgaBi tsPerPixel > 8)){ | |
| 330 | isEnoughB its = true ; | |
| 331 | this.tool kitDDS.ins ert(DCM.E_ BITS_STORE D, this.tg aBitsPerPi xel); | |
| 332 | this.tool kitDDS.ins ert(DCM.E_ HIGH_BIT, this.tgaBi tsPerPixel - 1); | |
| 333 | // cpt 04 /16/09 -- handle the rare case where bit s allocate d = 16 but tgaBitsPe rPixel = 8 | |
| 334 | if ((this .tgaBitsPe rPixel==8) && (this. toolkitDDS .getElemen tIntValue( DCM.E_BITS _ALLOCATED ) > this.t gaBitsPerP ixel)) { | |
| 335 | this. toolkitDDS .insert(DC M.E_BITS_A LLOCATED, tgaBitsPer Pixel); | |
| 336 | } | |
| 337 | } | |
| 338 | lo gger.debug ("Original number of Samples P er Pixel: " + this.t oolkitDDS. getElement StringValu e(DCM.E_SA MPLES_PER_ PIXEL)); | |
| 339 | if (this.tool kitDDS.get ElementInt Value(DCM. E_SAMPLES_ PER_PIXEL) == 1){ | |
| 340 | isSample PerPixel = true; | |
| 341 | } | |
| 342 | ||
| 343 | // SRS Patch5 0 3.2.3.5 Update Ima ge Module info based on tga fi le used. | |
| 344 | // SRS Patch5 0 3.2.3.9 Update Ima ge Module info based on tga fi le used. | |
| 345 | if (isEnoughR ows && isE noughColum ns && isEn oughBits & & isSample PerPixel){ | |
| 346 | //if row s, columns , and bits match bet ween DDS a nd TGA, do nothing. | |
| 347 | // i f IOD is a lready Sec ondary Cap ture remov e rescale slope/inte rcept, etc . | |
| 348 | if ( this.isIma geSCIOD()) { | |
| 349 | modify ImageToSCI OD(); | |
| 350 | } | |
| 351 | } | |
| 352 | el se{ | |
| 353 | //add th e tga rows /columns f ields to t he DDS (ea rly, so ot her comput ations are correct). | |
| 354 | this.too lkitDDS.in sert(DCM.E _ROWS, thi s.tgaRows) ; | |
| 355 | this.too lkitDDS.in sert(DCM.E _COLUMNS, this.tgaCo lumns); | |
| 356 | ||
| 357 | int full ImageSize = this.too lkitDDS.ge tElementIn tValue(DCM .E_BITS_AL LOCATED) | |
| 358 | * th is.toolkit DDS.getEle mentIntVal ue(DCM.E_R OWS) | |
| 359 | * th is.toolkit DDS.getEle mentIntVal ue(DCM.E_C OLUMNS) | |
| 360 | * th is.toolkit DDS.getEle mentIntVal ue(DCM.E_S AMPLES_PER _PIXEL); | |
| 361 | ||
| 362 | int bits Allocated; | |
| 363 | if(this. tgaBitsPer Pixel > 8) { | |
| 364 | bits Allocated = 16; | |
| 365 | this .toolkitDD S.insert(D CM.E_BITS_ ALLOCATED, bitsAlloc ated); | |
| 366 | this .toolkitDD S.insert(D CM.E_BITS_ STORED, th is.tgaBits PerPixel); | |
| 367 | if(t his.toolki tDDS.conta insElement (DCM.E_HIG H_BIT)){ | |
| 368 | int highBi t = this.t oolkitDDS. getElement IntValue(D CM.E_HIGH_ BIT); | |
| 369 | if(highBit > this.tg aBitsPerPi xel){ | |
| 370 | this.t oolkitDDS. insert(DCM .E_HIGH_BI T, (this.t gaBitsPerP ixel - 1)) ; | |
| 371 | } | |
| 372 | } | |
| 373 | else { | |
| 374 | this.toolk itDDS.inse rt(DCM.E_H IGH_BIT, ( this.tgaBi tsPerPixel - 1)); | |
| 375 | } | |
| 376 | } | |
| 377 | else{ | |
| 378 | bits Allocated = 8; | |
| 379 | this .toolkitDD S.insert(D CM.E_BITS_ ALLOCATED, bitsAlloc ated); | |
| 380 | this .toolkitDD S.insert(D CM.E_BITS_ STORED, th is.tgaBits PerPixel); | |
| 381 | this .toolkitDD S.insert(D CM.E_HIGH_ BIT, (this .tgaBitsPe rPixel - 1 )); | |
| 382 | } | |
| 383 | int redu cedImageSi ze = this. tgaRows * this.tgaCo lumns * bi tsAllocate d; | |
| 384 | ||
| 385 | if ( !(isEnough Rows && is EnoughColu mns)) | |
| 386 | // cpt - 06/28/0 7: | |
| 387 | // if Columns an d Rows cha nged, and (0028, 003 0) Pixel S pacing and /or | |
| 388 | // (00 18, 1164) Imager Pix el Spacing is presen t, adjust them respe ctively | |
| 389 | adjust PixelSpaci ng(); | |
| 390 | ||
| 391 | Integer reductionF actor = fu llImageSiz e / reduce dImageSize ; | |
| 392 | // ** cpt: set legac y lossy co mpression method for "down-sam pled" imag e | |
| 393 | if (redu ctionFacto r > 1.0) { | |
| 394 | //set Loss y Image Co mpression field to 0 1. | |
| 395 | this.toolk itDDS.inse rt(DCM.E_L OSSY_IMAGE _COMPRESSI ON,"01"); // VR=CS - coded st ring! | |
| 396 | //set Rati o of Lossy Compressi on. | |
| 397 | this.toolk itDDS.inse rt(DCM.E_L OSSY_IMAGE _CMP_RATIO , reductio nFactor); | |
| 398 | //set loss y compress ion method | |
| 399 | th is.toolkit DDS.insert (DCM.E_LOS SY_IMAGE_C MP_METHOD, "DOWN-SAM PLED"); | |
| 400 | } | |
| 401 | //Ch ange Windo w Width an d Level to match pix el depth. | |
| 402 | this.upd ateWindowV alues(); | |
| 403 | //Change Image Typ e to Deriv ed. | |
| 404 | this.upd ateImageTy peToDerive d(); | |
| 405 | //Change SOP Class to Second ary Captur e. | |
| 406 | //VERIFY proper so lution for the follo wing. | |
| 407 | //Soluti on: Csaba and I beli eve this i s right. I will dou ble-check walking th ru code. | |
| 408 | this.upd ateSOPClas sToSeconda ryCapture( ); // *** cpt: this puts every downsampl ed CR into SC IOD!!! | |
| 409 | } | |
| 410 | } | |
| 411 | ||
| 412 | privat e void adj ustPixelSp acing()thr ows DCSExc eption { | |
| 413 | // if presen t adjust ( 0028, 0030 ) Pixel Sp acing and/ or (0018, 1164) Ima ger Pixel Spacing | |
| 414 | // based on changed ro ws and col umns ratio | |
| 415 | ch eckAndUpda tePixelSpa cing(DCM.E _IMAGER_PI XEL_SPACIN G); | |
| 416 | ch eckAndUpda tePixelSpa cing(DCM.E _PIXEL_SPA CING); | |
| 417 | } | |
| 418 | ||
| 419 | privat e void che ckAndUpdat ePixelSpac ing(Attrib uteTag pST ag) throws DCSExcept ion { | |
| 420 | ||
| 421 | Dico mElement d E=null; | |
| 422 | try { | |
| 423 | dE=thi s.toolkitD DS.findEle ment(pSTag ); | |
| 424 | } catch (DCSExcept ion dcse){ | |
| 425 | return ; // nothi ng to adju st | |
| 426 | } | |
| 427 | Stri ng pSStrin g1=null; | |
| 428 | Stri ng pSStrin g2=null; | |
| 429 | try { | |
| 430 | pSStri ng1 = dE.g etStringVa lue(0); | |
| 431 | pSStri ng2 = dE.g etStringVa lue(1); | |
| 432 | } catch (DCSExcept ion dcse){ | |
| 433 | } | |
| 434 | floa t rowsRati o = (short )this.tool kitDDS.get ElementInt Value(DCM. E_ROWS) / this.tgaRo ws; | |
| 435 | floa t columnsR atio = (sh ort)this.t oolkitDDS. getElement IntValue(D CM.E_COLUM NS) / this .tgaColumn s; | |
| 436 | Floa t pSR=null ; | |
| 437 | Floa t pSC=null ; | |
| 438 | ||
| 439 | try { | |
| 440 | String pSString= ""; | |
| 441 | if ((p SString1 ! = null) && (pSString 1.length() > 0)) { | |
| 442 | pSR = (F loat)(Floa t.parseFlo at(pSStrin g1) * rows Ratio); | |
| 443 | pSString = pSR.toS tring(); | |
| 444 | } | |
| 445 | if ((p SString2 ! = null) && (pSString 2.length() > 0)) { | |
| 446 | pSC = (F loat)(Floa t.parseFlo at(pSStrin g2) * colu mnsRatio); | |
| 447 | if (pSSt ring.lengt h() > 0) { | |
| 448 | pSString + = "\\" + p SC.toStrin g(); | |
| 449 | } else { | |
| 450 | pSString = pSC.toS tring(); | |
| 451 | } | |
| 452 | } | |
| 453 | if (pS String.len gth()>0) { | |
| 454 | this.toolk itDDS.inse rt(pSTag, pSString); | |
| 455 | } | |
| 456 | } | |
| 457 | catc h (NumberF ormatExcep tion nfe) {} | |
| 458 | } | |
| 459 | ||
| 460 | privat e void upd ateImageTy peToDerive d()throws DCSExcepti on{ | |
| 461 | ||
| 462 | // SRS Patch5 0 3.2.3.1 All tga im ages shall set Image Type to De rived. | |
| 463 | ||
| 464 | // change Ima ge Type fr om Origina l to Deriv ed. | |
| 465 | // but fir st check i f type 1 f ield Image Type exis ts; if doe s not, cre ate it as DERIVED/PR IMARY | |
| 466 | // -- for ACR-NEMA 2 .0 compati bility | |
| 467 | Di comCSEleme nt imageTy pe=null; | |
| 468 | tr y { | |
| 469 | imag eType = (D icomCSElem ent)this.t oolkitDDS. findElemen t(DCM.E_IM AGE_TYPE); | |
| 470 | } | |
| 471 | ca tch (DCSEx ception dc se) { | |
| 472 | String i mageTypeVa lues[] = { "DERIVED", "PRIMARY" }; | |
| 473 | DicomCSE lement nuI mageType = new Dicom CSElement( DCM.E_IMAG E_TYPE, im ageTypeVal ues); | |
| 474 | this.too lkitDDS.in sert(nuIma geType); | |
| 475 | return; | |
| 476 | } | |
| 477 | St ring image TypeValues [] = new S tring[imag eType.vm() ]; | |
| 478 | if ((imageTyp e.getStrin gValue(0). equals("OR IGINAL"))) { | |
| 479 | for(int i=0; i<ima geType.vm( ); i++){ | |
| 480 | Stri ng singleT ype = imag eType.getS tringValue (i); | |
| 481 | if(i == 0){ | |
| 482 | imageTypeV alues[i] = "DERIVED" ; | |
| 483 | } | |
| 484 | else { | |
| 485 | imageTypeV alues[i] = singleTyp e; | |
| 486 | } | |
| 487 | } | |
| 488 | DicomCSE lement nuI mageType = new Dicom CSElement( DCM.E_IMAG E_TYPE, im ageTypeVal ues); | |
| 489 | this.too lkitDDS.in sert(nuIma geType); | |
| 490 | } | |
| 491 | } | |
| 492 | ||
| 493 | privat e void cha ngePhotome tricInterp retation() throws DCS Exception{ | |
| 494 | ||
| 495 | // SRS Patch5 0 3.2.3.8 Convert al l reconsti tuted imag es to Mono chrome2. | |
| 496 | // set Photom etric Inte rpretation to Monoch rome2. | |
| 497 | th is.toolkit DDS.insert (DCM.E_PHO TOMETRIC_I NTERPRETAT ION, "MONO CHROME2"); | |
| 498 | } | |
| 499 | ||
| 500 | privat e void upd ateSOPClas sToSeconda ryCapture( )throws DC SException { | |
| 501 | ||
| 502 | // SRS Patch5 0 3.2.3.2 Change SOP Class to Secondary Capture. | |
| 503 | // change SOP Class to Secondary Capture. | |
| 504 | // FUTURE I'm doing thi s, but I t hink it is wrong. W e should n ot change the SOP Cl ass. | |
| 505 | // However, this matc hes what i s done in Patch 50. *** cpt: i t is mostl y overprot ection now | |
| 506 | th is.toolkit DDS.insert (new Attri buteTag("0 002,0002") , UID.SOPC LASSSECOND ARYCAPTURE ); | |
| 507 | th is.toolkit DDS.insert (DCM.E_SOP CLASS_UID, UID.SOPCL ASSSECONDA RYCAPTURE) ; | |
| 508 | } | |
| 509 | ||
| 510 | privat e boolean isImageCTI OD()throws DCSExcept ion{ | |
| 511 | ||
| 512 | bo olean CT = false; | |
| 513 | St ring sopCl ass; | |
| 514 | so pClass = t his.toolki tDDS.getEl ementStrin gValue(DCM .E_SOPCLAS S_UID); | |
| 515 | if (sopClass. equals(UID .SOPCLASSC T)){ | |
| 516 | CT = tru e; | |
| 517 | } | |
| 518 | re turn CT; | |
| 519 | } | |
| 520 | ||
| 521 | privat e boolean isImageSCI OD()throws DCSExcept ion{ | |
| 522 | ||
| 523 | bo olean SC = false; | |
| 524 | St ring sopCl ass; | |
| 525 | so pClass = t his.toolki tDDS.getEl ementStrin gValue(DCM .E_SOPCLAS S_UID); | |
| 526 | if (sopClass. equals(UID .SOPCLASSS ECONDARYCA PTURE)){ | |
| 527 | SC = tru e; | |
| 528 | } | |
| 529 | re turn SC; | |
| 530 | } | |
| 531 | ||
| 532 | privat e boolean isImageMRI OD() throw s DCSExcep tion{ | |
| 533 | ||
| 534 | bo olean MR = false; | |
| 535 | St ring sopCl ass; | |
| 536 | so pClass = t his.toolki tDDS.getEl ementStrin gValue(DCM .E_SOPCLAS S_UID); | |
| 537 | if (sopClass. equals(UID .SOPCLASSM R)){ | |
| 538 | MR = true ; | |
| 539 | } | |
| 540 | re turn MR; | |
| 541 | } | |
| 542 | ||
| 543 | privat e void upd ateModalit yCode()thr ows DCSExc eption{ | |
| 544 | ||
| 545 | // SRS Patch5 0 3.2.3.6 Validate/c orrect the re is a si ngle Modal ity Code i n DDS. | |
| 546 | ||
| 547 | Di comCSEleme nt modalit yCodeEleme nt = null; | |
| 548 | SO PClassModa lityCodeMa pping mcMa p = new SO PClassModa lityCodeMa pping(); | |
| 549 | if (this.tool kitDDS.con tainsEleme nt(DCM.E_M ODALITY)){ | |
| 550 | modalityC odeElement = (DicomC SElement)t his.toolki tDDS.findE lement(DCM .E_MODALIT Y); | |
| 551 | String up dateModali tyCode; | |
| 552 | if(modali tyCodeElem ent.vm() > 1){ | |
| 553 | updat eModalityC ode = mcMa p.getModal ityCode(th is.toolkit DDS.getEle mentString Value(DCM. E_SOPCLASS _UID)); | |
| 554 | if(up dateModali tyCode == null){ | |
| 555 | u pdateModal ityCode = modalityCo deElement. getStringV alue(0); | |
| 556 | } | |
| 557 | this. toolkitDDS .insert(DC M.E_MODALI TY, update ModalityCo de); | |
| 558 | } | |
| 559 | } | |
| 560 | el se{ | |
| 561 | String n uModalityC ode = "OT" ; | |
| 562 | if(this. toolkitDDS .containsE lement(DCM .E_SOPCLAS S_UID)){ | |
| 563 | nuMo dalityCode = mcMap.g etModality Code(this. toolkitDDS .getElemen tStringVal ue(DCM.E_S OPCLASS_UI D)); | |
| 564 | } | |
| 565 | this.too lkitDDS.in sert(DCM.E _MODALITY, nuModalit yCode); | |
| 566 | } | |
| 567 | } | |
| 568 | ||
| 569 | privat e boolean isMultiFra meIOD()thr ows DCSExc eption{ | |
| 570 | bo olean mult iFrameChec k = false; | |
| 571 | if (this.too lkitDDS.ge tElementSt ringValue( DCM.E_SOPC LASS_UID). equals( | |
| 572 | UID. SOPCLASSUS MULTIFRAME IMAGE)){ | |
| 573 | multiFra meCheck = true; | |
| 574 | } | |
| 575 | el se if (thi s.toolkitD DS.getElem entStringV alue(DCM.E _SOPCLASS_ UID).equal s( | |
| 576 | UID. SOPCLASSNM )){ | |
| 577 | multiFra meCheck = true; | |
| 578 | } | |
| 579 | el se if ((th is.toolkit DDS.contai nsElement( DCM.E_NUMB ER_OF_FRAM ES)) && | |
| 580 | (Int eger.decod e(this.too lkitDDS.ge tElementSt ringValue( DCM.E_NUMB ER_OF_FRAM ES).toStri ng())!=1)) | |
| 581 | multiFra meCheck = true; | |
| 582 | ||
| 583 | re turn multi FrameCheck ; | |
| 584 | } | |
| 585 | ||
| 586 | privat e void upd ateCTIODIn formation( )throws DC SException { | |
| 587 | ||
| 588 | lo gger.debug (this.getC lass().get Name()+": Dicom Tool kit Layer: "+ | |
| 589 | "... updating C T IOD usin g possible CT Parame ters."); | |
| 590 | Pa rameters p arameters = this.get CTParamete rs(); | |
| 591 | // This metho d determin es if the CT image i s destined as a CT I OD or a SC IOD. | |
| 592 | // If CT Para meters exi st, modify the datas et as CT I OD. | |
| 593 | if (parameter s != null) { | |
| 594 | logger.d ebug("Cont ains valid CT Parame ters. Leav e it as DI COM CT IOD ."); | |
| 595 | this.mod ifyCTImage ToCTIOD(pa rameters); | |
| 596 | } | |
| 597 | // If CT Para meters do not exist, modify th e dataset as SC IOD. | |
| 598 | el se{ | |
| 599 | this.mod ifyImageTo SCIOD(); | |
| 600 | } | |
| 601 | } | |
| 602 | ||
| 603 | privat e void upd ateWindowV alues()thr ows DCSExc eption{ | |
| 604 | ||
| 605 | // SRS Patch5 0 3.2.3.10 Calibrati ng the Win dow and Le vel values to match the | |
| 606 | // reconsti tuted imag e. | |
| 607 | // maximum_pi xel_value = (1 << in put_bits_p er_pixel) - 1; | |
| 608 | ||
| 609 | // Determine Maximum Wi ndow and L evel | |
| 610 | // ** cpt: fixed win dow width (removed - 1) and ce nter ( add ed - 1) | |
| 611 | in t maxWindo wWidthValu e = 1 << t his.tgaBit sPerPixel; | |
| 612 | in t maxWindo wLevelValu e = (maxWi ndowWidthV alue/2) - 1; | |
| 613 | bo olean wWCS et=false; | |
| 614 | ||
| 615 | // See if the current v alues in t he DDS are larger | |
| 616 | if (this.tool kitDDS.con tainsEleme nt(DCM.E_W INDOW_WIDT H)){ | |
| 617 | if(this. toolkitDDS .getElemen tIntValue( DCM.E_WIND OW_WIDTH,0 ) > maxWin dowWidthVa lue){ | |
| 618 | //if true, ass ign new, d efault val ues. | |
| 619 | this .toolkitDD S.insert(D CM.E_WINDO W_WIDTH, m axWindowWi dthValue); | |
| 620 | this .toolkitDD S.insert(D CM.E_WINDO W_CENTER, maxWindowL evelValue) ; | |
| 621 | this .toolkitDD S.removeEl ement(DCM. E_WINDOW_C NTR_AND_WI DTH_EXPL); | |
| 622 | wWCS et=true; | |
| 623 | } | |
| 624 | } | |
| 625 | el se{ | |
| 626 | //if no values, as sign new, default va lues. | |
| 627 | //But fi rst check to make su re there i s no VOI L UT Sequenc e. | |
| 628 | if(!this .toolkitDD S.contains Element(DC M.E_VOI_LU T_SEQUENCE )){ | |
| 629 | this .toolkitDD S.insert(D CM.E_WINDO W_WIDTH,ma xWindowWid thValue); | |
| 630 | this .toolkitDD S.insert(D CM.E_WINDO W_CENTER, maxWindowL evelValue) ; | |
| 631 | this .toolkitDD S.removeEl ement(DCM. E_WINDOW_C NTR_AND_WI DTH_EXPL); | |
| 632 | wWCSet=tru e; | |
| 633 | } | |
| 634 | } | |
| 635 | if (wWCSet) { | |
| 636 | // optio nally adju st W/C exp lanation: take off 2 nd,.. entr ies | |
| 637 | updateWi ndowLevelE xplanation (); | |
| 638 | } | |
| 639 | } | |
| 640 | ||
| 641 | // ** cpt: added met hod to rec ompute win dow/center based on pixel valu es | |
| 642 | privat e void reC omputeWind owValues() throws DCS Exception{ | |
| 643 | ||
| 644 | // Recalculat ing the Wi ndow and L evel value s (for SC IODs only) . | |
| 645 | // maximum_pi xel_value = (1 << in put_bits_p er_pixel) - 1; | |
| 646 | in t pixelMas k = (1 << this.tgaBi tsPerPixel ) - 1; | |
| 647 | ||
| 648 | // find lowe st and hig hest pixel values | |
| 649 | in t minValue = pixelMa sk; | |
| 650 | in t maxValue = 0; | |
| 651 | in t pixelVal ue; | |
| 652 | in t numPxs = this.tgaR ows * this .tgaColumn s; | |
| 653 | if (pixelMas k > 0xFF) { // word | |
| 654 | for (int i=0; i < numPxs ; i++ ) { | |
| 655 | // pix elValue = (imageBuff er.getShor t(i) & pix elMask); | |
| 656 | pixelV alue = ((( imageBuffe r.get((2*i ) + 1) & 0 xFF) * 256 ) + (image Buffer.get (2*i)& 0xF F)) & pixe lMask; | |
| 657 | if (pi xelValue < minValue) minValue = pixelVal ue; | |
| 658 | if (pi xelValue > maxValue) maxValue = pixelVal ue; | |
| 659 | pixelV alue=0; | |
| 660 | } | |
| 661 | } else { | |
| 662 | for (int i=0; i < numPxs ; i++ ) { | |
| 663 | pixelV alue = (im ageBuffer. get(i) & p ixelMask); | |
| 664 | if (pi xelValue < minValue) minValue = pixelVal ue; | |
| 665 | if (pi xelValue > maxValue) maxValue = pixelVal ue; | |
| 666 | pixelV alue=0; | |
| 667 | } | |
| 668 | } | |
| 669 | im ageBuffer. rewind(); | |
| 670 | ||
| 671 | in t windowWi dthValue; | |
| 672 | in t windowLe velValue; | |
| 673 | // Determine Maximum Wi ndow and L evel | |
| 674 | if (maxValue > (minVal ue + 1)) { | |
| 675 | wind owWidthVal ue = maxVa lue - minV alue; | |
| 676 | windowLe velValue = minValue + (windowW idthValue/ 2); | |
| 677 | } else { | |
| 678 | wind owWidthVal ue = 1 << this.tgaBi tsPerPixel ; | |
| 679 | windowLe velValue = (windowWi dthValue/2 ) - 1; | |
| 680 | } | |
| 681 | ||
| 682 | // assign ne w, default values. | |
| 683 | th is.toolkit DDS.insert (DCM.E_WIN DOW_WIDTH, windowWid thValue); | |
| 684 | th is.toolkit DDS.insert (DCM.E_WIN DOW_CENTER , windowLe velValue); | |
| 685 | ||
| 686 | // optionall y adjust W /C explana tion: take off 2nd,. . entries | |
| 687 | up dateWindow LevelExpla nation(); | |
| 688 | } | |
| 689 | ||
| 690 | // ** cpt : added me thod to op tionally a djust W/C explanatio n: take of f 2nd,.. e ntries | |
| 691 | // must be called onl y if W/L w as changed | |
| 692 | privat e void upd ateWindowL evelExplan ation()thr ows DCSExc eption{ | |
| 693 | ||
| 694 | if (this.too lkitDDS.co ntainsElem ent(DCM.E_ WINDOW_CNT R_AND_WIDT H_EXPL)){ | |
| 695 | // t ake first value only | |
| 696 | Stri ng wCExpl= this.toolk itDDS.getE lementStri ngValue(DC M.E_WINDOW _CNTR_AND_ WIDTH_EXPL ); | |
| 697 | // r eplace old value(s) with first value | |
| 698 | this .toolkitDD S.insert(D CM.E_WINDO W_CNTR_AND _WIDTH_EXP L, wCExpl) ; | |
| 699 | } | |
| 700 | } | |
| 701 | ||
| 702 | privat e void upd ateMultiFr ameInfoToS ingleFrame Info()thro ws DCSExce ption{ | |
| 703 | th is.toolkit DDS.insert (DCM.E_NUM BER_OF_FRA MES,1); | |
| 704 | th is.updateS OPClassToS econdaryCa pture(); / / *** cpt: must be u pdated wit h MF SC IO Ds | |
| 705 | } | |
| 706 | ||
| 707 | privat e void che ckVendorCo mpression( ){ | |
| 708 | // Add code t o check in comments field from GE PACS. | |
| 709 | // Here is th e informat ion for GE PACS arch ived image s. | |
| 710 | // 0008,2111| Derivation Descripti on^ST|1,1| Non-revers ible compr essed imag e: For ref erence onl y [99] | |
| 711 | ||
| 712 | tr y{ | |
| 713 | String c ompression Element = this.toolk itDDS.getE lementStri ngValue(ne w Attribut eTag("0008 , 2111")); | |
| 714 | String c onstant = "Non-rever sible comp ressed ima ge: For re ference on ly [99]"; | |
| 715 | if(compr essionElem ent.equals IgnoreCase (constant) ){ | |
| 716 | //se t Lossy Im age Compre ssion fiel d to 01. | |
| 717 | this .toolkitDD S.insert(D CM.E_LOSSY _IMAGE_COM PRESSION," 01"); // VR=CS - co ded string ! | |
| 718 | //Ch ange Image Type to D erived. | |
| 719 | this .updateIma geTypeToDe rived(); | |
| 720 | } | |
| 721 | } | |
| 722 | ca tch (DCSEx ception dc se){ | |
| 723 | return; | |
| 724 | } | |
| 725 | } | |
| 726 | ||
| 727 | privat e void upd atesForAll Modalities ()throws D CSExceptio n{ | |
| 728 | // Convert Sa mples Per Pixel fiel d to 1. | |
| 729 | th is.toolkit DDS.insert (DCM.E_SAM PLES_PER_P IXEL,1); | |
| 730 | // Change Pix el Represe ntation to 0000H. | |
| 731 | // SRS Patch5 0 3.2.3.7 Correct Pi xel Repres entation. | |
| 732 | th is.toolkit DDS.insert (DCM.E_PIX EL_REPRESE NTATION, 0 ); | |
| 733 | // Change Pho tometric t o Monochro me2. | |
| 734 | th is.changeP hotometric Interpreta tion(); | |
| 735 | th is.updateM odalityCod e(); | |
| 736 | } | |
| 737 | ||
| 738 | privat e Paramete rs getCTPa rameters() { | |
| 739 | ||
| 740 | // FUTURE -Th e CT_Param s.dic and Modality.d ic informa tion is re trieved di rectly | |
| 741 | // from these fil es located in \DICOM \Dict\ fol der. The intent is to get thi s | |
| 742 | // info rmation fr om VistA H IS. Due t o time con straints, we will ad dress this later | |
| 743 | // when time perm its. Ther e is no ha rm or limi tation to continue r eading the .dic | |
| 744 | // file s until ti me permits . There i s no curre nt intenti on to run the HDIG o n a | |
| 745 | // box separate f rom the Le gacy DGW. | |
| 746 | ||
| 747 | St ring param eterString = ""; | |
| 748 | Pa rameters a cceptedPar ameters = null; | |
| 749 | ||
| 750 | // 1. Get th e proper D CMTOTGA pa rameters i f pixel de pth is gre ater than 8bits. | |
| 751 | if (this.tgaB itsPerPixe l > 8){ | |
| 752 | //a. If exist, us e the DCMT OTGA param eters from the top s ection of the | |
| 753 | // Text file. Th is starts appearing with Patch 50. | |
| 754 | paramete rString = this.origi nalPixelDa taInfo.get DcmtotgaPa rameters() ; | |
| 755 | if(!(par ameterStri ng == null )){ | |
| 756 | logg er.debug(" The refere nced Text File conta ins DCMTOT GA Paramet ers."); | |
| 757 | try{ | |
| 758 | accept edParamete rs = new P arameters( parameterS tring); | |
| 759 | if(acc eptedParam eters.isDI COMParamet erSet()){ | |
| 760 | logger.w arn(this.g etClass(). getName()+ ": DICOM T oolkit lay er: \n"+ | |
| 761 | "T he DCMTOTG A Paramete r contains <DICOM>. This is n ot valid " + | |
| 762 | "f or a Targa image."); | |
| 763 | accepted Parameters = null; | |
| 764 | } | |
| 765 | return acceptedP arameters; | |
| 766 | } | |
| 767 | catc h(Paramete rDecomposi tionExcept ion pdX){ | |
| 768 | logger .warn(this .getClass( ).getName( )+": DICOM Toolkit l ayer: \n"+ | |
| 769 | "Could not decompose DCMTOTGA Parameters from refe renced Tex t file."); | |
| 770 | return null; | |
| 771 | } | |
| 772 | } | |
| 773 | ||
| 774 | try{ | |
| 775 | //c. If CT Im age is new er than th e date of the CT His torical Se ttings | |
| 776 | // file, use the DCMTOT GA paramet ers from t he current Modality. dic global . | |
| 777 | ||
| 778 | //Ge t the CT_P arameters file Times tamp. Con vert to a Date. | |
| 779 | Stri ng ctParam eterFileTi meStamp = DicomGatew ayConfigur ation.getI nstance(). getCTParam etersTimeS tamp(); | |
| 780 | if(c tParameter FileTimeSt amp == nul l || ctPar ameterFile TimeStamp. equals("") ){ | |
| 781 | logger.deb ug("No CT Parameter file Time Stamp was found."); | |
| 782 | return nul l; | |
| 783 | } | |
| 784 | logg er.debug(" CT Paramet er Date St amp: " + c tParameter FileTimeSt amp); | |
| 785 | // S impleDateF ormat file Pattern = new Simple DateFormat ("d-MMM-yy yy"); | |
| 786 | Simp leDateForm at filePat tern = new SimpleDat eFormat("d -MMM-yyyy hh:mm:ss") ; | |
| 787 | Date ctParamFi leDate; | |
| 788 | ctParamFil eDate = fi lePattern. parse(ctPa rameterFil eTimeStamp ); | |
| 789 | ||
| 790 | //Ge t the Stud y Date fro m the DDS. Convert to a Date. | |
| 791 | Stri ng studyDa teString = this.tool kitDDS.get ElementStr ingValue(D CM.E_STUDY _DATE); | |
| 792 | logg er.debug(" CT Image S tudy Date: "+studyDa teString); | |
| 793 | Simp leDateForm at dicomPa ttern = ne w SimpleDa teFormat(" yyyyMMdd") ; | |
| 794 | Date studyDate = dicomPa ttern.pars e(studyDat eString); | |
| 795 | Moda lityDicInf o deviceIn fo = new M odalityDic Info(); | |
| 796 | devi ceInfo.set Manufactur er(this.to olkitDDS.g etElementS tringValue (DCM.E_MAN UFACTURER) .trim()); | |
| 797 | devi ceInfo.set Model(this .toolkitDD S.getEleme ntStringVa lue(DCM.E_ MANUFACTUR ERS_MODEL_ NAME).trim ()); | |
| 798 | devi ceInfo.set ModalityCo de(this.to olkitDDS.g etElementS tringValue (DCM.E_MOD ALITY)); | |
| 799 | logg er.debug(" Mfg: " + d eviceInfo. getManufac turer() + | |
| 800 | " Mod el: "+devi ceInfo.get Model() + | |
| 801 | " Mod ality: " + deviceInf o.getModal ityCode()) ; | |
| 802 | if(s tudyDate.a fter(ctPar amFileDate ) || study Date.equal s(ctParamF ileDate)){ | |
| 803 | //If the C T_Parmeter s file is older, loo k in Modal ity.dic an d extract | |
| 804 | // the co rrect para meters. | |
| 805 | Vector<Mod alityDicIn fo> modali tyMatching List; | |
| 806 | modalityMa tchingList = Gateway Dictionary Contents.g etInstance ().getModa lityDictio naryEntrie s(); | |
| 807 | if(modalit yMatchingL ist == nul l){ | |
| 808 | return null; | |
| 809 | } | |
| 810 | ||
| 811 | Iterator<M odalityDic Info> iter ator = mod alityMatch ingList.it erator(); | |
| 812 | while(iter ator.hasNe xt()){ | |
| 813 | Modali tyDicInfo temp = (Mo dalityDicI nfo)iterat or.next(); | |
| 814 | if(dev iceInfo.eq uals(temp) ){ | |
| 815 | // Return par ameters fr om modalit y.dic file . | |
| 816 | lo gger.debug ("Found ma tch with M odality.di c file."); | |
| 817 | ac ceptedPara meters = t emp.getDCM TOTGAParam eters(); | |
| 818 | } | |
| 819 | } | |
| 820 | } | |
| 821 | else { | |
| 822 | //If the C T_Paramete rs file is newer, co ntinue wit h the step s below. | |
| 823 | //b. If e xist, retu rn the DCM TOTGA para meters fro m the CT H istorical | |
| 824 | // Settin gs file (E d’s Log). | |
| 825 | Vector<Par ameterDevi ceInfo> ct ParameterL ist; | |
| 826 | ctParamete rList = Ga tewayDicti onaryConte nts.getIns tance().ge tCTParamet ersList(); | |
| 827 | if(ctParam eterList = = null){ | |
| 828 | return null; | |
| 829 | } | |
| 830 | //Find mat ch based o n Site/Mfg /Model | |
| 831 | //Paramete rDeviceInf o device = (Paramete rDeviceInf o) deviceI nfo; | |
| 832 | ParameterD eviceInfo device = n ew Paramet erDeviceIn fo(); | |
| 833 | device.set Manufactur er(deviceI nfo.getMan ufacturer( )); | |
| 834 | device.set Model(devi ceInfo.get Model()); | |
| 835 | device.set ModalityCo de(deviceI nfo.getMod alityCode( )); | |
| 836 | device.set DCMTOTGAPa rameters(d eviceInfo. getDCMTOTG AParameter s()); | |
| 837 | ||
| 838 | if(this.ac quisitionS ite == nul l){ | |
| 839 | return null; | |
| 840 | } | |
| 841 | device.set SiteID(thi s.acquisit ionSite); | |
| 842 | Iterator<P arameterDe viceInfo> iterator = ctParamet erList.ite rator(); | |
| 843 | ||
| 844 | while(iter ator.hasNe xt()){ | |
| 845 | Param eterDevice Info devic eEntry = ( ParameterD eviceInfo) iterator.n ext(); | |
| 846 | if(de vice.equal s(deviceEn try)){ | |
| 847 | D ate device EntryDate = deviceEn try.getCha ngeDate(); | |
| 848 | / /Compare D ate in Lis t to curre nt Study D ate. | |
| 849 | / /You are l ooking for an entry that is sa me or olde r. | |
| 850 | i f((studyDa te.equals( deviceEntr yDate)) | |
| 851 | ||( studyDate. after(devi ceEntryDat e))){ | |
| 852 | //If ab ove condit ion is met , assign t he paramet ers from l ist entry to | |
| 853 | // cur rent devic eInfo. | |
| 854 | logger. debug("Fou nd match i n CT Param eters file ."); | |
| 855 | logger. debug("The Entry Dat e in the C T Paramete rs file is : " + devi ceEntryDat e); | |
| 856 | accepte dParameter s = device Entry.getD CMTOTGAPar ameters(); | |
| 857 | //I hav e to retur n as I fin d the firs t match. I cannot | |
| 858 | // cycl e through entire lis t. | |
| 859 | break; | |
| 860 | } | |
| 861 | } | |
| 862 | } | |
| 863 | } | |
| 864 | //If no match is found i n either s earch, ret urn null. | |
| 865 | if(a cceptedPar ameters == null){ | |
| 866 | return nul l; | |
| 867 | } | |
| 868 | ||
| 869 | //d. If the D CMOTGA par ameters ca nnot be re trieved by the steps | |
| 870 | // above, set to NULL. This happ ens automa tically if nothing i s assigned | |
| 871 | // to accepte dParameter s variable . | |
| 872 | ||
| 873 | //2. Determin e appropri ate action if there is a Rxx v alue (Redu ction Fact or) | |
| 874 | // in the DCM TOTGA para meters. | |
| 875 | if(a cceptedPar ameters.co ntainsRedu ctionFacto r()){ | |
| 876 | if(accepte dParameter s.contains Slash()){ | |
| 877 | //b. Retrieve t he .big im age file i nstead of the .tga i mage file | |
| 878 | // if there is a slash (“ /”) symbol in the DC MTOTGA par ameters. | |
| 879 | // Se t the DCMT OTGA param eters to N ULL if no .big image file exis ts. | |
| 880 | if(big FileFlag){ | |
| 881 | ac ceptedPara meters.set FullParame terSet(); | |
| 882 | } | |
| 883 | else{ | |
| 884 | ac ceptedPara meters = n ull; | |
| 885 | } | |
| 886 | ||
| 887 | } | |
| 888 | else{ | |
| 889 | //a. Set the re trieved DC MTOTGA par ameters to NULL if t here is no | |
| 890 | // sl ash (“/”) symbol in the DCMTOT GA paramet ers. | |
| 891 | accept edParamete rs = null; | |
| 892 | } | |
| 893 | } | |
| 894 | if(a cceptedPar ameters != null){ | |
| 895 | if(acc eptedParam eters.isDI COMParamet erSet()){ | |
| 896 | logger.w arn(this.g etClass(). getName()+ ": DICOM T oolkit lay er: \n"+ | |
| 897 | "T he DCMTOTG A Paramete r contains <DICOM>. This is n ot valid " + | |
| 898 | "f or a Targa image."); | |
| 899 | accepted Parameters = null; | |
| 900 | } | |
| 901 | } | |
| 902 | retu rn accepte dParameter s; | |
| 903 | } | |
| 904 | catch(Pa rseExcepti on noparse ){ | |
| 905 | retu rn null; | |
| 906 | } | |
| 907 | catch(DC SException dcse){ | |
| 908 | retu rn null; | |
| 909 | } | |
| 910 | } | |
| 911 | ret urn null; | |
| 912 | } | |
| 913 | ||
| 914 | privat e void mod ifyCTImage ToCTIOD(Pa rameters p arams) thr ows DCSExc eption{ | |
| 915 | ||
| 916 | ||
| 917 | // SRS Patch5 0 3.2.3.10 Multiple fixes for CT images. | |
| 918 | // Remove sel ected fiel ds from CT Image Mod ule: | |
| 919 | ||
| 920 | // a. Add Sx xxx variab le, if any , to Resca le Interce pt. Subtr act the Ax xxx variab le, | |
| 921 | // if any, from the n ew Rescale Intercept value. U pdate the Rescale In tercept fi eld | |
| 922 | // with the new Resca le Interce pt value. | |
| 923 | in t nuRescal eIntercept = 0; | |
| 924 | if (this.tool kitDDS.con tainsEleme nt(DCM.E_R ESCALE_INT ERCEPT)){ | |
| 925 | nuRescal eIntercept = this.to olkitDDS.g etElementI ntValue(DC M.E_RESCAL E_INTERCEP T); | |
| 926 | } | |
| 927 | el se{ | |
| 928 | nuRescal eIntercept = 0; | |
| 929 | } | |
| 930 | ||
| 931 | if (params.is Subtractio nSet()){ | |
| 932 | nuRescal eIntercept += params .getSubtra ctionParam eter(); | |
| 933 | } | |
| 934 | if (params.is AdditionSe t()){ | |
| 935 | nuRescal eIntercept -= params .getAdditi onParamete r(); | |
| 936 | } | |
| 937 | ||
| 938 | th is.toolkit DDS.insert (DCM.E_RES CALE_INTER CEPT, nuRe scaleInter cept); | |
| 939 | th is.toolkit DDS.insert (DCM.E_RES CALE_SLOPE , 0x01); | |
| 940 | // b. Remove Largest P ixel field . | |
| 941 | th is.toolkit DDS.remove Element(DC M.E_LARGES T_IMAGE_PI XEL_VALUE) ; // E_LAR GEST_IMG_P XL_VAL_PLA NE); | |
| 942 | th is.toolkit DDS.remove Element(DC M.E_LARGES T_VALID_PI XEL_VAL_RE T); | |
| 943 | th is.toolkit DDS.remove Element(DC M.E_LARGES T_PIXEL_VA LUE_SERIES ); | |
| 944 | // c. Remove Smallest Pixel fiel d. | |
| 945 | th is.toolkit DDS.remove Element(DC M.E_LARGES T_IMAGE_PI XEL_VALUE) ; // E_LAR GEST_IMG_P XL_VAL_PLA NE); | |
| 946 | th is.toolkit DDS.remove Element(DC M.E_SMALLE ST_VALID_P XL_VAL_RET ); | |
| 947 | th is.toolkit DDS.remove Element(DC M.E_SMALLE ST_PIXEL_V AL_SERIES) ; | |
| 948 | // d. Remove Largest I mage Pixel field. | |
| 949 | th is.toolkit DDS.remove Element(DC M.E_LARGES T_IMAGE_PI XEL_VALUE) ; | |
| 950 | // e. Remove Smallest Image Pixe l field. | |
| 951 | th is.toolkit DDS.remove Element(DC M.E_SMALLE ST_IMAGE_P IXEL_VALUE ); | |
| 952 | // f. Remove Pixel Pad ding field . | |
| 953 | th is.toolkit DDS.remove Element(DC M.E_PIXEL_ PADDING_VA LUE); | |
| 954 | // Remove VOI LUT Seque nce. | |
| 955 | th is.toolkit DDS.remove Element(DC M.E_VOI_LU T_SEQUENCE ); | |
| 956 | // h. Set Pi xel Repres entation v alue to 00 (unsigned data). | |
| 957 | th is.toolkit DDS.insert (DCM.E_PIX EL_REPRESE NTATION, 0 x00); | |
| 958 | // i. Re-cal culate Win dow Width/ Center val ues if Win dow Width value is g reater | |
| 959 | // than the pixel dep th. | |
| 960 | th is.updateW indowValue s(); | |
| 961 | ||
| 962 | th is.updateI mageTypeTo Derived(); | |
| 963 | } | |
| 964 | ||
| 965 | privat e void mod ifyImageTo SCIOD() th rows DCSEx ception{ | |
| 966 | ||
| 967 | // SRS Patch5 0 3.2.3.10 Multiple fixes for CT images. | |
| 968 | // Remove sel ected fiel ds from CT Image Mod ule | |
| 969 | ||
| 970 | th is.toolkit DDS.insert (DCM.E_CON VERSION_TY PE, "WSD") ; | |
| 971 | // a. Remove Rescale S lope field . | |
| 972 | th is.toolkit DDS.remove Element(DC M.E_RESCAL E_SLOPE); | |
| 973 | // b. Remove Rescale I ntercept f ield. | |
| 974 | th is.toolkit DDS.remove Element(DC M.E_RESCAL E_INTERCEP T); | |
| 975 | // c. Change SOP Class value to Secondary Capture. | |
| 976 | th is.updateS OPClassToS econdaryCa pture(); | |
| 977 | // d. Set Lo ssy Compre ssion valu e to 1. | |
| 978 | // ** cpt: this flag is explic it about l ossy compr ession. | |
| 979 | // The fac t that IOD turns to SC is quit e enough t o emphasiz e data deg radation, | |
| 980 | // but it is not nec essarily c ompression | |
| 981 | // e. Set Pi xel Repres entation v alue to 00 (unsigned data). | |
| 982 | th is.toolkit DDS.insert (DCM.E_PIX EL_REPRESE NTATION, 0 x00); | |
| 983 | // f. Remove Largest P ixel field . | |
| 984 | th is.toolkit DDS.remove Element(DC M.E_LARGES T_IMAGE_PI XEL_VALUE) ; // E_LAR GEST_IMG_P XL_VAL_PLA NE); | |
| 985 | th is.toolkit DDS.remove Element(DC M.E_LARGES T_VALID_PI XEL_VAL_RE T); | |
| 986 | th is.toolkit DDS.remove Element(DC M.E_LARGES T_PIXEL_VA LUE_SERIES ); | |
| 987 | // g. Remove Smallest Pixel fiel d. | |
| 988 | th is.toolkit DDS.remove Element(DC M.E_LARGES T_IMAGE_PI XEL_VALUE) ; // E_LAR GEST_IMG_P XL_VAL_PLA NE); | |
| 989 | th is.toolkit DDS.remove Element(DC M.E_SMALLE ST_VALID_P XL_VAL_RET ); | |
| 990 | th is.toolkit DDS.remove Element(DC M.E_SMALLE ST_PIXEL_V AL_SERIES) ; | |
| 991 | // h. Remove Largest I mage Pixel field. | |
| 992 | th is.toolkit DDS.remove Element(DC M.E_LARGES T_IMAGE_PI XEL_VALUE) ; | |
| 993 | // i. Remove Smallest Image Pixe l field. | |
| 994 | th is.toolkit DDS.remove Element(DC M.E_SMALLE ST_IMAGE_P IXEL_VALUE ); | |
| 995 | // j. Remove Pixel Pad ding field . | |
| 996 | th is.toolkit DDS.remove Element(DC M.E_PIXEL_ PADDING_VA LUE); | |
| 997 | // Remove VOI LUT Seque nce. | |
| 998 | th is.toolkit DDS.remove Element(DC M.E_VOI_LU T_SEQUENCE ); | |
| 999 | // k. Re-cal culate Win dow Width/ Center val ues if Win dow Width value is g reater | |
| 1000 | // than the pixel dep th | |
| 1001 | // ** cpt: always re calculate window/cen ter values for secon dary captu re IODs | |
| 1002 | // as resc ale slope and interc ept is gon e | |
| 1003 | th is.reCompu teWindowVa lues(); | |
| 1004 | ||
| 1005 | // Alter Imag e Type fie ld appropr iately. | |
| 1006 | th is.updateI mageTypeTo Derived(); | |
| 1007 | } | |
| 1008 | ||
| 1009 | ||
| 1010 | privat e boolean isPart10Di comFile(St ring filen ame){ | |
| 1011 | bo olean part 10 = false ; | |
| 1012 | tr y{ | |
| 1013 | Dico mFileInput file = ne w DicomFil eInput(fil ename); | |
| 1014 | part 10 = file. chapter10E ncoding(); | |
| 1015 | file .close(); | |
| 1016 | } | |
| 1017 | ca tch(DCSExc eption dcs X){ | |
| 1018 | //Ig nore. | |
| 1019 | } | |
| 1020 | re turn part1 0; | |
| 1021 | } | |
| 1022 | } | |
| 1023 |
Araxis Merge (but not the data content of this report) is Copyright © 1993-2016 Araxis Ltd (www.araxis.com). All rights reserved.