4040import java .lang .reflect .Array ;
4141import java .rmi .dgc .VMID ;
4242import java .rmi .server .UID ;
43+ import java .text .DecimalFormat ;
4344import java .util .ArrayList ;
4445import java .util .Arrays ;
4546import java .util .Comparator ;
@@ -1063,7 +1064,8 @@ public void setId(String id) throws FormatException, IOException {
10631064 DicomTag sliceSpace = new DicomTag (SLICE_SPACING , DS );
10641065 Length physicalZ = fixUnits (r .getPixelsPhysicalSizeZ (pyramid ));
10651066 if (physicalZ != null ) {
1066- sliceThickness .value = padString (String .valueOf (physicalZ .value (UNITS .MM )));
1067+ double pz = physicalZ .value (UNITS .MM ).doubleValue ();
1068+ sliceThickness .value = padString (formatFixedWidth (pz , 16 ));
10671069 }
10681070 else {
10691071 // a value of 0 is not allowed, but we don't know the actual thickness or slice spacing
@@ -1076,9 +1078,11 @@ public void setId(String id) throws FormatException, IOException {
10761078 DicomTag pixelSpacing = new DicomTag (PIXEL_SPACING , DS );
10771079 Length physicalX = fixUnits (r .getPixelsPhysicalSizeX (pyramid ));
10781080 Length physicalY = fixUnits (r .getPixelsPhysicalSizeY (pyramid ));
1079- String px = physicalX == null ? "1" : String .valueOf (physicalX .value (UNITS .MM ));
1080- String py = physicalY == null ? "1" : String .valueOf (physicalY .value (UNITS .MM ));
1081- pixelSpacing .value = padString (px + "\\ " + py );
1081+ double px = physicalX == null ? 1.0 : physicalX .value (UNITS .MM ).doubleValue ();
1082+ double py = physicalY == null ? 1.0 : physicalY .value (UNITS .MM ).doubleValue ();
1083+
1084+ pixelSpacing .value =
1085+ padString (formatFixedWidth (px , 15 ) + "\\ " + formatFixedWidth (py , 15 ));
10821086 pixelMeasuresSequence .children .add (pixelSpacing );
10831087
10841088 pixelMeasuresSequence .children .add (makeItemDelimitation ());
@@ -1154,11 +1158,13 @@ public void setId(String id) throws FormatException, IOException {
11541158 plane .children .add (makeItem ());
11551159
11561160 DicomTag offsetX = new DicomTag (X_OFFSET_IN_SLIDE , DS );
1157- offsetX .value = padString (physicalX == null ? "0" : padString (String .valueOf (physicalX .value (UNITS .MM ).floatValue () * width )));
1161+ double ox = physicalX .value (UNITS .MM ).floatValue () * width ;
1162+ offsetX .value = padString (physicalX == null ? "0" : padString (formatFixedWidth (ox , 16 )));
11581163 plane .children .add (offsetX );
11591164
11601165 DicomTag offsetY = new DicomTag (Y_OFFSET_IN_SLIDE , DS );
1161- offsetY .value = padString (physicalY == null ? "0" : padString (String .valueOf (physicalY .value (UNITS .MM ).floatValue () * height )));
1166+ double oy = physicalY .value (UNITS .MM ).floatValue () * height ;
1167+ offsetY .value = padString (physicalY == null ? "0" : padString (formatFixedWidth (oy , 16 )));
11621168 plane .children .add (offsetY );
11631169
11641170 DicomTag positionZ = new DicomTag (Z_OFFSET_IN_SLIDE , DS );
@@ -2214,6 +2220,77 @@ private void checkPixelCount(boolean warn) throws FormatException {
22142220 }
22152221 }
22162222
2223+ private static String getScientificNotationPattern (int intDigits , int signBytes , int width ) {
2224+ int exponentDigits = String .valueOf (Math .abs (intDigits )).length ();
2225+ int mantissaDigits = width - exponentDigits - signBytes - 2 ;
2226+ StringBuffer pattern = new StringBuffer ("." );
2227+ for (int i =0 ; i <mantissaDigits ; i ++) {
2228+ pattern .append ("#" );
2229+ }
2230+ pattern .append ("E" );
2231+ for (int i =0 ; i <exponentDigits ; i ++) {
2232+ pattern .append ("0" );
2233+ }
2234+ return pattern .toString ();
2235+ }
2236+
2237+ /**
2238+ * Format the given double as a string with no more than
2239+ * <code>width</code> characters.
2240+ */
2241+ public static String formatFixedWidth (double v , int width ) {
2242+ // use a smaller value than usual to test double equivalency
2243+ double epsilon = Double .MIN_VALUE ;
2244+ if (Double .isNaN (v )) {
2245+ return "NaN" ;
2246+ }
2247+ else if (Double .isInfinite (v )) {
2248+ if (width >= 9 ) {
2249+ return v < 0 ? "-Infinity" : "+Infinity" ;
2250+ }
2251+ return "" ;
2252+ }
2253+ else if (Math .abs (v - 0 ) < epsilon ) {
2254+ return "0" ;
2255+ }
2256+ // get a decimal formatter for the current default locale
2257+ DecimalFormat formatter = new DecimalFormat ();
2258+ formatter .setGroupingUsed (false );
2259+
2260+ int integerDigitsNeeded = (int ) Math .log10 (Math .abs (v )) + 1 ;
2261+ int signBytes = v < 0 ? 1 : 0 ;
2262+
2263+ if (integerDigitsNeeded + signBytes > width ) {
2264+ String pattern = getScientificNotationPattern (integerDigitsNeeded , signBytes , width );
2265+ LOGGER .debug ("float formatting pattern = {}" , pattern );
2266+ formatter .applyPattern (pattern );
2267+ }
2268+ else {
2269+ if (Math .round (v ) == 0 ) {
2270+ integerDigitsNeeded --;
2271+ }
2272+ int fractionDigits = width - signBytes - integerDigitsNeeded ;
2273+ if (fractionDigits == 0 || fractionDigits == 1 ) {
2274+ formatter .setMaximumFractionDigits (0 );
2275+ }
2276+ else if (fractionDigits > 1 && integerDigitsNeeded >= -4 ) {
2277+ formatter .setMaximumIntegerDigits (Math .max (0 , integerDigitsNeeded ));
2278+ if (integerDigitsNeeded >= 0 ) {
2279+ formatter .setMaximumFractionDigits (fractionDigits - 1 );
2280+ }
2281+ else {
2282+ formatter .setMaximumFractionDigits (width - signBytes - 1 );
2283+ }
2284+ }
2285+ else {
2286+ String pattern = getScientificNotationPattern (integerDigitsNeeded , signBytes , width - 1 );
2287+ LOGGER .debug ("float formatting pattern = {}" , pattern );
2288+ formatter .applyPattern (pattern );
2289+ }
2290+ }
2291+ return formatter .format (v );
2292+ }
2293+
22172294 protected Slf4JStopWatch stopWatch () {
22182295 return new Slf4JStopWatch (LOGGER , Slf4JStopWatch .DEBUG_LEVEL );
22192296 }
0 commit comments