View Javadoc
1   package nom.tam.fits.compression;
2   
3   import static org.junit.Assert.assertEquals;
4   
5   /*
6    * #%L
7    * nom.tam FITS library
8    * %%
9    * Copyright (C) 1996 - 2024 nom-tam-fits
10   * %%
11   * This is free and unencumbered software released into the public domain.
12   *
13   * Anyone is free to copy, modify, publish, use, compile, sell, or
14   * distribute this software, either in source code form or as a compiled
15   * binary, for any purpose, commercial or non-commercial, and by any
16   * means.
17   *
18   * In jurisdictions that recognize copyright laws, the author or authors
19   * of this software dedicate any and all copyright interest in the
20   * software to the public domain. We make this dedication for the benefit
21   * of the public at large and to the detriment of our heirs and
22   * successors. We intend this dedication to be an overt act of
23   * relinquishment in perpetuity of all present and future rights to this
24   * software under copyright law.
25   *
26   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27   * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
29   * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
30   * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
31   * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
32   * OTHER DEALINGS IN THE SOFTWARE.
33   * #L%
34   */
35  
36  import java.awt.BorderLayout;
37  import java.awt.Color;
38  import java.awt.Graphics2D;
39  import java.awt.image.BufferedImage;
40  import java.io.BufferedInputStream;
41  import java.io.File;
42  import java.io.FileInputStream;
43  import java.io.FileNotFoundException;
44  import java.io.FileOutputStream;
45  import java.io.IOException;
46  import java.io.InputStream;
47  import java.lang.reflect.Array;
48  import java.nio.FloatBuffer;
49  import java.nio.IntBuffer;
50  import java.nio.ShortBuffer;
51  import java.util.Random;
52  import java.util.stream.IntStream;
53  
54  import javax.swing.ImageIcon;
55  import javax.swing.JFrame;
56  import javax.swing.JLabel;
57  import javax.swing.WindowConstants;
58  
59  import org.junit.Assert;
60  import org.junit.Before;
61  import org.junit.Test;
62  
63  import nom.tam.fits.BasicHDU;
64  import nom.tam.fits.Fits;
65  import nom.tam.fits.FitsException;
66  import nom.tam.fits.FitsFactory;
67  import nom.tam.fits.Header;
68  import nom.tam.fits.HeaderCard;
69  import nom.tam.fits.ImageData;
70  import nom.tam.fits.ImageHDU;
71  import nom.tam.fits.compression.algorithm.hcompress.HCompressorOption;
72  import nom.tam.fits.compression.algorithm.quant.QuantizeOption;
73  import nom.tam.fits.compression.algorithm.rice.RiceCompressOption;
74  import nom.tam.fits.header.Compression;
75  import nom.tam.fits.header.Standard;
76  import nom.tam.fits.util.BlackBoxImages;
77  import nom.tam.image.StandardImageTiler;
78  import nom.tam.image.compression.hdu.CompressedImageHDU;
79  import nom.tam.util.ArrayFuncs;
80  import nom.tam.util.FitsOutputStream;
81  import nom.tam.util.SafeClose;
82  
83  public class ReadWriteProvidedCompressedImageTest {
84  
85      private ImageHDU m13;
86  
87      private short[][] m13_data;
88  
89      private float[][] m13_data_real;
90  
91      private ImageHDU m13real;
92  
93      private final boolean showImage = false;
94  
95      private static int assertionCounter = 1;
96  
97      @Before
98      public void setDefaults() {
99          FitsFactory.setDefaults();
100     }
101 
102     private void assert_float_image(float[][] actual, float[][] expected, float delta) {
103         Assert.assertEquals(expected.length, actual.length);
104         IntStream.range(0, expected.length).parallel()
105                 .forEach(axis0 -> Assert.assertArrayEquals(expected[axis0], actual[axis0], delta));
106     }
107 
108     private void assert_int_image(int[][] actual, int[][] expected) {
109         Assert.assertEquals(expected.length, actual.length);
110         IntStream.range(0, expected.length).parallel()
111                 .forEach(axis0 -> Assert.assertArrayEquals(expected[axis0], actual[axis0]));
112     }
113 
114     private void assert_short_image(short[][] actual, short[][] expected) {
115         Assert.assertEquals(expected.length, actual.length);
116         IntStream.range(0, expected.length).parallel()
117                 .forEach(axis0 -> Assert.assertArrayEquals(expected[axis0], actual[axis0]));
118     }
119 
120     /**
121      * This is an assertion for a special case when a loss full algorithm is used and a quantification with null checks.
122      * The will result in wrong null values, because some of the values representing blank will be lost.
123      */
124     private void assertArrayEquals(double[] expected, double[] actual, double delta, boolean checkNaN) {
125         Assert.assertEquals(expected.length, actual.length);
126         for (int index = 0; index < actual.length; index++) {
127             double d1 = expected[index];
128             double d2 = actual[index];
129             if (Double.isNaN(d1) || Double.isNaN(d2)) {
130                 if (checkNaN) {
131                     Assert.assertTrue(Double.isNaN(d1) == Double.isNaN(d2)); //
132                 }
133             } else {
134                 Assert.assertEquals(d1, d2, delta);
135             }
136         }
137     }
138 
139     private void assertArrayEquals(float[][] expected, float[][] actual, float delta) {
140         Assert.assertEquals(expected.length, actual.length);
141         for (int index = 0; index < actual.length; index++) {
142             Assert.assertArrayEquals(expected[index], actual[index], delta);
143         }
144     }
145 
146     /**
147      * Assert two files files (one compressed and one uncompressed and use as little memory as possible.
148      */
149     private <T> void assertCompressedToUncompressedImage(String fileName, String unCompfileName, Class<T> clazz,
150             IHDUAsserter<T> reader) throws Exception {
151         Fits f = null;
152 
153         // System.out.println(" checking file: " + fileName);
154 
155         try {
156             f = new Fits(fileName);
157             Fits unFits = new Fits(unCompfileName);
158 
159             int hduIndex = 0;
160             ImageHDU hdu = readHDU(unFits, ImageHDU.class);
161             unFits.deleteHDU(0);
162             CompressedImageHDU uncompHdu = readHDU(f, CompressedImageHDU.class);
163 
164             f.deleteHDU(0);
165             while (hdu != null && uncompHdu != null) {
166                 T compressedData = (T) uncompHdu.asImageHDU().getData().getData();
167                 T orgData = (T) hdu.getData().getData();
168 
169                 // show travis something is going on
170                 System.out.println("Asserting image data! " + (assertionCounter++));
171                 reader.assertData(orgData, compressedData);
172 
173                 hdu = readHDU(unFits, ImageHDU.class);
174                 if (hdu != null) {
175                     unFits.deleteHDU(0);
176                 }
177                 uncompHdu = readHDU(f, CompressedImageHDU.class);
178                 if (uncompHdu != null) {
179                     f.deleteHDU(0);
180                 }
181             }
182             Assert.assertFalse(hdu != null || uncompHdu != null);
183         } finally {
184             SafeClose.close(f);
185         }
186 
187         // System.out.println(" done.");
188     }
189 
190     private void assertData(float[][] data) {
191         for (int x = 0; x < 300; x++) {
192             for (int y = 0; y < 300; y++) {
193                 Assert.assertEquals(m13_data_real[x][y], data[x][y], 1f);
194             }
195         }
196     }
197 
198     private void assertData(short[][] data) {
199         for (int x = 0; x < 300; x++) {
200             for (int y = 0; y < 300; y++) {
201                 Assert.assertEquals(m13_data[x][y], data[x][y]);
202             }
203         }
204     }
205 
206     private void assertFloatImage(FloatBuffer result, float[][] expected, float delta) {
207         float[] real = new float[expected[0].length];
208         for (float[] expectedPart : expected) {
209             result.get(real);
210             Assert.assertEquals(expectedPart.length, real.length);
211             for (int subindex = 0; subindex < expectedPart.length; subindex++) {
212                 float expectedFloat = expectedPart[subindex];
213                 float realFloat = real[subindex];
214                 if (!Float.isNaN(expectedFloat) && !Float.isNaN(realFloat)) {
215                     Assert.assertEquals(expectedFloat, realFloat, delta);
216                 }
217             }
218         }
219     }
220 
221     private void assertIntImage(IntBuffer result, int[][] expected) {
222         int[] real = new int[expected[0].length];
223         for (int index = 0; index < real.length; index++) {
224             int[] expectedPart = expected[index];
225             result.get(real);
226             Assert.assertEquals(expectedPart.length, real.length);
227             for (int subindex = 0; subindex < expectedPart.length; subindex++) {
228                 int expectedFloat = expectedPart[subindex];
229                 int realFloat = real[subindex];
230                 Assert.assertEquals("pixel differes at " + subindex + "x" + index, expectedFloat, realFloat);
231             }
232         }
233     }
234 
235     @Test
236     public void blackboxTest_c4s_060126_182642_zri() throws Exception {
237         assertCompressedToUncompressedImage(resolveLocalOrRemoteFileName("c4s_060126_182642_zri.fits.fz"), //
238                 resolveLocalOrRemoteFileName("c4s_060126_182642_zri.fits"), short[][].class, new IHDUAsserter<short[][]>() {
239 
240                     @Override
241                     public void assertData(short[][] expected, short[][] actual) {
242                         assert_short_image(actual, expected);
243                     }
244                 });
245     }
246 
247     @Test
248     public void blackboxTest_c4s_060127_070751_cri() throws Exception {
249         assertCompressedToUncompressedImage(resolveLocalOrRemoteFileName("c4s_060127_070751_cri.fits.fz"), //
250                 resolveLocalOrRemoteFileName("c4s_060127_070751_cri.fits"), short[][].class, new IHDUAsserter<short[][]>() {
251 
252                     @Override
253                     public void assertData(short[][] expected, short[][] actual) {
254                         assert_short_image(actual, expected);
255                     }
256                 });
257     }
258 
259     @Test
260     public void blackboxTest_kwi_041217_212603_fri() throws Exception {
261         assertCompressedToUncompressedImage(resolveLocalOrRemoteFileName("kwi_041217_212603_fri.fits.fz"), //
262                 resolveLocalOrRemoteFileName("kwi_041217_212603_fri.fits"), short[][].class, new IHDUAsserter<short[][]>() {
263 
264                     @Override
265                     public void assertData(short[][] expected, short[][] actual) {
266                         assert_short_image(actual, expected);
267                     }
268                 });
269     }
270 
271     @Test
272     public void blackboxTest_kwi_041217_213100_fri() throws Exception {
273         assertCompressedToUncompressedImage(resolveLocalOrRemoteFileName("kwi_041217_213100_fri.fits.fz"), //
274                 resolveLocalOrRemoteFileName("kwi_041217_213100_fri.fits"), short[][].class, new IHDUAsserter<short[][]>() {
275 
276                     @Override
277                     public void assertData(short[][] expected, short[][] actual) {
278                         assert_short_image(actual, expected);
279                     }
280                 });
281     }
282 
283     @Test
284     public void blackboxTest_psa_140305_191552_zri() throws Exception {
285         assertCompressedToUncompressedImage(resolveLocalOrRemoteFileName("psa_140305_191552_zri.fits.fz"), //
286                 resolveLocalOrRemoteFileName("psa_140305_191552_zri.fits"), short[][].class, new IHDUAsserter<short[][]>() {
287 
288                     @Override
289                     public void assertData(short[][] expected, short[][] actual) {
290                         assert_short_image(actual, expected);
291                     }
292                 });
293     }
294 
295     @Test
296     public void blackboxTest_psa_140305_194520_fri() throws Exception {
297         assertCompressedToUncompressedImage(resolveLocalOrRemoteFileName("psa_140305_194520_fri.fits.fz"), //
298                 resolveLocalOrRemoteFileName("psa_140305_194520_fri.fits"), short[][].class, new IHDUAsserter<short[][]>() {
299 
300                     @Override
301                     public void assertData(short[][] expected, short[][] actual) {
302                         assert_short_image(actual, expected);
303                     }
304                 });
305     }
306 
307     @Test
308     public void blackboxTest_tu1134529() throws Exception {
309         assertCompressedToUncompressedImage(resolveLocalOrRemoteFileName("tu1134529.fits.fz"), //
310                 resolveLocalOrRemoteFileName("tu1134529.fits"), int[][].class, new IHDUAsserter<int[][]>() {
311 
312                     @Override
313                     public void assertData(int[][] expected, int[][] actual) {
314                         assert_int_image(actual, expected);
315                     }
316                 });
317 
318     }
319 
320     @Test
321     public void blackboxTest_tu1134531() throws Exception {
322         assertCompressedToUncompressedImage(resolveLocalOrRemoteFileName("tu1134531.fits.fz"), //
323                 resolveLocalOrRemoteFileName("tu1134531.fits"), float[][].class, new IHDUAsserter<float[][]>() {
324 
325                     @Override
326                     public void assertData(float[][] expected, float[][] actual) {
327                         assert_float_image(actual, expected, 15f);
328                     }
329                 });
330     }
331 
332     @Test
333     public void blackboxTest1_1() throws Exception {
334         FloatBuffer result = (FloatBuffer) readAll(resolveLocalOrRemoteFileName("DECam_00149774_40_DESX0332-2742.fits.fz"),
335                 1);
336         float[][] expected = (float[][]) readAll(resolveLocalOrRemoteFileName("DECam_00149774_40_DESX0332-2742.fits"), 0);
337         result.rewind();
338         assertFloatImage(result, expected, 6f);
339     }
340 
341     @Test
342     public void blackboxTest1_2() throws Exception {
343         IntBuffer result = (IntBuffer) readAll(resolveLocalOrRemoteFileName("DECam_00149774_40_DESX0332-2742.fits.fz"), 2);
344         int[][] expected = (int[][]) readAll(resolveLocalOrRemoteFileName("DECam_00149774_40_DESX0332-2742.fits"), 1);
345         result.rewind();
346         assertIntImage(result, expected);
347     }
348 
349     @Test
350     public void blackboxTest1_3() throws Exception {
351         FloatBuffer result = (FloatBuffer) readAll(resolveLocalOrRemoteFileName("DECam_00149774_40_DESX0332-2742.fits.fz"),
352                 3);
353         float[][] expected = (float[][]) readAll(resolveLocalOrRemoteFileName("DECam_00149774_40_DESX0332-2742.fits"), 2);
354         result.rewind();
355         assertFloatImage(result, expected, 0.0005f);
356     }
357 
358     @Test
359     public void blackboxTest2() throws Exception {
360         FloatBuffer result = (FloatBuffer) readAll(resolveLocalOrRemoteFileName("unpack_vlos_mag.fits.fz"), 1);
361         float[][] expected = (float[][]) readAll(resolveLocalOrRemoteFileName("unpack_vlos_mag.fits"), 0);
362         result.rewind();
363         assertFloatImage(result, expected, 6500f);
364     }
365 
366     @Test
367     public void blackboxTest3() throws Exception {
368         int lastpix = 0;
369         byte bytevalue = (byte) 0x80;
370         lastpix = lastpix | (bytevalue << 24);
371 
372         IntBuffer result = (IntBuffer) readAll(resolveLocalOrRemoteFileName("hmi.fits.fz"), 1);
373         int[][] expected = (int[][]) readAll(resolveLocalOrRemoteFileName("hmi.fits"), 1);
374         result.rewind();
375         assertIntImage(result, expected);
376 
377     }
378 
379     private void dispayImage(short[][] data) {
380         JFrame frame = new JFrame("FrameDemo");
381         frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
382         frame.pack();
383         frame.setVisible(true);
384 
385         BufferedImage img = (BufferedImage) frame.createImage(300, 300);
386 
387         Graphics2D g = img.createGraphics(); // Get a Graphics2D object
388 
389         for (int y = 0; y < 300; y++) {
390             for (int x = 0; x < 300; x++) {
391                 float grayScale = data[x][y] / 4000f;
392                 g.setColor(new Color(grayScale, grayScale, grayScale));
393                 g.drawRect(x, y, 1, 1);
394             }
395         }
396         ImageIcon icon = new ImageIcon(img);
397         JLabel label = new JLabel(icon);
398         frame.getContentPane().add(label, BorderLayout.CENTER);
399         frame.repaint();
400         frame.pack();
401         frame.setVisible(true);
402     }
403 
404     private HeaderCard findCompressOption(Header header, String key) {
405         int index = 1;
406         while (true) {
407             HeaderCard card = header.getCard(Compression.ZNAMEn.n(index));
408             if (card.getValue().equals(key)) {
409                 return header.findCard(Compression.ZVALn.n(index));
410             }
411             index++;
412         }
413     }
414 
415     private boolean isEmptyImage(BasicHDU<?> result) throws FitsException {
416         return result instanceof ImageHDU && ((ImageHDU) result).getData().getData() == null;
417     }
418 
419     private Object readAll(String fileName, int index) throws Exception {
420         Fits f = null;
421         try {
422             f = new Fits(fileName);
423             BasicHDU<?> hdu = f.getHDU(index);
424             if (hdu instanceof CompressedImageHDU) {
425                 CompressedImageHDU bhdu = (CompressedImageHDU) hdu;
426                 return bhdu.getUncompressedData();
427             }
428             if (hdu instanceof ImageHDU) {
429                 ImageHDU bhdu = (ImageHDU) hdu;
430                 return bhdu.getData().getData();
431             }
432         } finally {
433             SafeClose.close(f);
434         }
435         return null;
436     }
437 
438     private ImageHDU readCompressedHdu(String fileName, int index) throws Exception {
439         Fits f = null;
440         try {
441             f = new Fits(fileName);
442             BasicHDU<?> hdu = f.getHDU(index);
443             if (hdu instanceof CompressedImageHDU) {
444                 CompressedImageHDU bhdu = (CompressedImageHDU) hdu;
445                 return bhdu.asImageHDU();
446             }
447         } finally {
448             SafeClose.close(f);
449         }
450         return null;
451     }
452 
453     @Test
454     public void readGzip() throws Exception {
455         Object result = readAll("src/test/resources/nom/tam/image/provided/m13_gzip.fits", 1);
456 
457         short[][] data = new short[300][300];
458         ArrayFuncs.copyInto(((ShortBuffer) result).array(), data);
459         assertData(data);
460         if (showImage) {
461             dispayImage(data);
462         }
463     }
464 
465     @Test
466     public void readHCompressed() throws Exception {
467         Object result = readAll("src/test/resources/nom/tam/image/provided/m13_hcomp.fits", 1);
468         short[][] data = new short[300][300];
469         ArrayFuncs.copyInto(((ShortBuffer) result).array(), data);
470         assertData(data);
471         if (showImage) {
472             dispayImage(data);
473         }
474     }
475 
476     private <T> T readHDU(Fits fits, Class<T> clazz) throws FitsException, IOException {
477         BasicHDU<?> result = fits.readHDU();
478         while (result != null && (isEmptyImage(result) || !clazz.isAssignableFrom(result.getClass()))) {
479             result = fits.readHDU();
480         }
481         return (T) result;
482     }
483 
484     @Test
485     public void readPLIO() throws Exception {
486         Object result = readAll("src/test/resources/nom/tam/image/provided/m13_plio.fits", 1);
487         short[][] data = new short[300][300];
488         ArrayFuncs.copyInto(((ShortBuffer) result).array(), data);
489         assertData(data);
490         if (showImage) {
491             dispayImage(data);
492         }
493     }
494 
495     @Test
496     public void readReal() throws Exception {
497         Object result = readAll("src/test/resources/nom/tam/image/provided/m13real_rice.fits", 1);
498         float[][] data = new float[300][300];
499         ArrayFuncs.copyInto(((FloatBuffer) result).array(), data);
500         assertData(data);
501 
502     }
503 
504     @Test
505     public void readRice() throws Exception {
506         Object result = readAll("src/test/resources/nom/tam/image/provided/m13_rice.fits", 1);
507 
508         short[][] data = new short[300][300];
509         ArrayFuncs.copyInto(((ShortBuffer) result).array(), data);
510         assertData(data);
511         if (showImage) {
512             dispayImage(data);
513         }
514     }
515 
516     @Test
517     public void readRiceAsImageHDU() throws Exception {
518         ImageHDU image = readCompressedHdu("src/test/resources/nom/tam/image/provided/m13_rice.fits", 1);
519 
520         short[][] data = (short[][]) image.getData().getData();
521         if (showImage) {
522             dispayImage(data);
523         }
524         "to set a breakpoint ;-)".toString();
525         doTile("readRiceAsImageHDU", data, image.getTiler(), 0, 0, 20, 20);
526     }
527 
528     private void doTile(String test, Object data, StandardImageTiler t, int x, int y, int nx, int ny) throws Exception {
529         Class<?> baseClass = ArrayFuncs.getBaseClass(data);
530         Object tile = Array.newInstance(baseClass, nx * ny);
531         t.getTile(tile, new int[] {y, x}, new int[] {ny, nx});
532 
533         float sum0 = 0;
534         float sum1 = 0;
535         int length = Array.getLength(tile);
536         for (int i = 0; i < nx; i++) {
537             for (int j = 0; j < ny; j++) {
538                 int tileOffset = i + j * nx;
539                 if (tileOffset >= length) {
540                     Assert.fail("tile offset wrong");
541                 }
542                 sum0 += ((Number) Array.get(tile, tileOffset)).doubleValue();
543                 sum1 += ((Number) Array.get(Array.get(data, j + y), i + x)).doubleValue();
544             }
545         }
546         assertEquals("Tiler" + test, sum0, sum1, 0);
547     }
548 
549     private String resolveLocalOrRemoteFileName(String fileName) {
550         return BlackBoxImages.getBlackBoxImage(fileName);
551     }
552 
553     @Before
554     public void setup() throws Exception {
555         try (Fits f = new Fits("src/test/resources/nom/tam/image/provided/m13.fits")) {
556             m13 = (ImageHDU) f.getHDU(0);
557             m13_data = (short[][]) m13.getData().getData();
558         }
559         try (Fits f = new Fits("src/test/resources/nom/tam/image/provided/m13real.fits")) {
560             m13real = (ImageHDU) f.getHDU(0);
561             m13_data_real = (float[][]) m13real.getData().getData();
562         }
563     }
564 
565     @Test
566     public void testBlanksInCompressedFloatImage() throws Exception {
567         try {
568             new File("target/testBlanksInCompressedFloatImage.fits").delete();
569             new File("target/testBlanksInCompressedFloatImage.fits.fz").delete();
570         } catch (Exception e) {
571             // ignore
572         }
573         double[][] data = new double[100][100];
574         double value = -1000.0d;
575         int blanks = 0;
576         for (int index1 = 0; index1 < 100; index1++) {
577             for (int index2 = 0; index2 < 100; index2++) {
578                 value += 0.12345d;
579                 if (blanks++ % 20 == 0) {
580                     data[index1][index2] = Double.NaN;
581                 } else {
582                     data[index1][index2] = value;
583                 }
584             }
585         }
586         Fits f = null;
587         try {
588             f = new Fits();
589             FitsOutputStream bdos = new FitsOutputStream(
590                     new FileOutputStream("target/testBlanksInCompressedFloatImage.fits"));
591             ImageData imageData = new ImageData(data);
592             ImageHDU hdu = new ImageHDU(ImageHDU.manufactureHeader(imageData), imageData);
593             f.addHDU(hdu);
594             f.write(bdos);
595         } finally {
596             SafeClose.close(f);
597         }
598         try {
599             f = new Fits();
600             FitsOutputStream bdos = new FitsOutputStream(
601                     new FileOutputStream("target/testBlanksInCompressedFloatImage.fits.fz"));
602             ImageData imageData = new ImageData(data);
603             ImageHDU hdu = new ImageHDU(ImageHDU.manufactureHeader(imageData), imageData);
604             CompressedImageHDU compressedHdu = CompressedImageHDU.fromImageHDU(hdu, 100, 15);
605             compressedHdu.setCompressAlgorithm(Compression.ZCMPTYPE_HCOMPRESS_1)//
606                     .setQuantAlgorithm(Compression.ZQUANTIZ_SUBTRACTIVE_DITHER_2)//
607                     .getCompressOption(HCompressorOption.class)//
608                     /**/.setScale(4);
609             compressedHdu//
610                     .getCompressOption(QuantizeOption.class)//
611                     /**/.setQlevel(1.0)/**/.setCheckNull(true);
612             compressedHdu.compress();
613             f.addHDU(compressedHdu);
614             f.write(bdos);
615         } finally {
616             SafeClose.close(f);
617         }
618         try {
619             f = new Fits("target/testBlanksInCompressedFloatImage.fits.fz");
620             f.readHDU();
621             CompressedImageHDU hdu = (CompressedImageHDU) f.readHDU();
622             double[][] actual = (double[][]) hdu.asImageHDU().getData().getData();
623             for (int index = 0; index < actual.length; index++) {
624                 Assert.assertArrayEquals(data[index], actual[index], 0f);
625             }
626         } finally {
627             SafeClose.close(f);
628         }
629     }
630 
631     @Test
632     public void testGzipFallbackCompressed() throws Exception {
633         short[][] array = new short[][] {{1000, -2000, 3000, -3000, 4000}, {1000, -2000, 3000, -3000, 4000},
634                 {1000, -2000, 3000, -3000, 4000}, {1000, -2000, 3000, -3000, 4000}, {1000, -2000, 3000, -3000, 4000}};
635         Fits f = null;
636         try {
637             f = new Fits();
638             ImageHDU image = (ImageHDU) Fits.makeHDU(array);
639             CompressedImageHDU compressedHdu = CompressedImageHDU.fromImageHDU(image, 5, 1);
640             compressedHdu.setCompressAlgorithm(Compression.ZCMPTYPE_RICE_1)//
641                     .getCompressOption(RiceCompressOption.class)//
642                     /**/.setBlockSize(32);
643             compressedHdu.compress();
644             f.addHDU(compressedHdu);
645             FitsOutputStream bdos = null;
646             try {
647                 bdos = new FitsOutputStream(new FileOutputStream("target/write_fallback.fits.fz"));
648                 f.write(bdos);
649             } finally {
650                 SafeClose.close(bdos);
651             }
652         } finally {
653             SafeClose.close(f);
654         }
655         try {
656             f = new Fits("target/write_fallback.fits.fz");
657             f.readHDU(); // the primary
658             CompressedImageHDU hdu = (CompressedImageHDU) f.readHDU();
659             short[][] actualShortArray = (short[][]) hdu.asImageHDU().getData().getData();
660             Assert.assertArrayEquals(array, actualShortArray);
661         } finally {
662             SafeClose.close(f);
663         }
664     }
665 
666     @Test
667     public void testSomeBlanksInCompressedFloatImage() throws Exception {
668         double[][] data = newTestImageWithSomeBlanks("");
669         Fits f = null;
670         try {
671             f = new Fits();
672             FitsOutputStream bdos = new FitsOutputStream(
673                     new FileOutputStream("target/testSomeBlanksInCompressedFloatImage.fits.fz"));
674             ImageData imageData = new ImageData(data);
675             ImageHDU hdu = new ImageHDU(ImageHDU.manufactureHeader(imageData), imageData);
676             CompressedImageHDU compressedHdu = CompressedImageHDU.fromImageHDU(hdu, 100, 15);
677             compressedHdu.setCompressAlgorithm(Compression.ZCMPTYPE_HCOMPRESS_1)//
678                     .setQuantAlgorithm(Compression.ZQUANTIZ_SUBTRACTIVE_DITHER_2)//
679                     .getCompressOption(HCompressorOption.class)//
680                     /**/.setScale(4);
681             compressedHdu//
682                     .getCompressOption(QuantizeOption.class)//
683                     /**/.setQlevel(1.0)/**/.setCheckNull(true);
684             compressedHdu.compress();
685             f.addHDU(compressedHdu);
686             f.write(bdos);
687             Assert.assertEquals(Compression.COMPRESSED_DATA_COLUMN,
688                     compressedHdu.getHeader().findCard(Standard.TTYPEn.n(1)).getValue());
689         } finally {
690             SafeClose.close(f);
691         }
692         try {
693             f = new Fits("target/testSomeBlanksInCompressedFloatImage.fits.fz");
694             f.readHDU();
695             CompressedImageHDU hdu = (CompressedImageHDU) f.readHDU();
696             double[][] actual = (double[][]) hdu.asImageHDU().getData().getData();
697             for (int index = 0; index < actual.length; index++) {
698                 assertArrayEquals(data[index], actual[index], 1d, false);
699             }
700         } finally {
701             SafeClose.close(f);
702         }
703     }
704 
705     @Test(expected = IllegalStateException.class)
706     public void testUnknownCompression() throws Exception {
707         Fits f = new Fits();
708         try {
709             CompressedImageHDU compressedHdu = CompressedImageHDU.fromImageHDU(m13, -1, 15);
710             compressedHdu.setCompressAlgorithm("NIX");
711             compressedHdu.compress();
712         } finally {
713             SafeClose.close(f);
714         }
715     }
716 
717     @Test
718     public void testMissingTileSize() throws Exception {
719         Fits f = null;
720         try {
721             f = new Fits();
722             CompressedImageHDU compressedHdu = CompressedImageHDU.fromImageHDU(m13, -1, 15);
723             compressedHdu.setCompressAlgorithm(Compression.ZCMPTYPE_HCOMPRESS_1)//
724                     .setQuantAlgorithm((String) null)//
725                     .getCompressOption(HCompressorOption.class)//
726                     /**/.setScale(1);
727             compressedHdu.compress();
728             f.addHDU(compressedHdu);
729             Assert.assertTrue(compressedHdu.isHeader());
730             compressedHdu.getHeader().deleteKey(Compression.ZTILEn.n(1));
731             FitsOutputStream bdos = null;
732             try {
733                 bdos = new FitsOutputStream(new FileOutputStream("target/write_m13_own_h.fits.fz"));
734                 f.write(bdos);
735             } finally {
736                 SafeClose.close(bdos);
737             }
738         } finally {
739             SafeClose.close(f);
740         }
741         try {
742             f = new Fits("target/write_m13_own_h.fits.fz");
743             f.readHDU();// the primary
744             CompressedImageHDU hdu = (CompressedImageHDU) f.readHDU();
745             short[][] actualShortArray = (short[][]) hdu.asImageHDU().getData().getData();
746             Assert.assertArrayEquals(m13_data, actualShortArray);
747         } finally {
748             SafeClose.close(f);
749         }
750     }
751 
752     @Test
753     public void writeHcompress() throws Exception {
754         Fits f = null;
755         try {
756             f = new Fits();
757             CompressedImageHDU compressedHdu = CompressedImageHDU.fromImageHDU(m13, 300, 15);
758             compressedHdu.setCompressAlgorithm(Compression.ZCMPTYPE_HCOMPRESS_1)//
759                     .setQuantAlgorithm((String) null)//
760                     .getCompressOption(HCompressorOption.class)//
761                     /**/.setScale(1);
762             compressedHdu.compress();
763             f.addHDU(compressedHdu);
764             compressedHdu = CompressedImageHDU.fromImageHDU(m13, 300, 1);
765             compressedHdu.setCompressAlgorithm(Compression.ZCMPTYPE_HCOMPRESS_1)//
766                     .setQuantAlgorithm((String) null)//
767                     .getCompressOption(HCompressorOption.class)//
768                     /**/.setScale(1);
769             compressedHdu.compress();
770             f.addHDU(compressedHdu);
771             compressedHdu = CompressedImageHDU.fromImageHDU(m13, 100, 300);
772             compressedHdu.setCompressAlgorithm(Compression.ZCMPTYPE_HCOMPRESS_1)//
773                     .setQuantAlgorithm((String) null)//
774                     .getCompressOption(HCompressorOption.class)//
775                     /**/.setSmooth(true)//
776                     /**/.setScale(1);
777             compressedHdu.compress();
778             f.addHDU(compressedHdu);
779             FitsOutputStream bdos = null;
780             try {
781                 bdos = new FitsOutputStream(new FileOutputStream("target/write_m13_own_h.fits.fz"));
782                 f.write(bdos);
783             } finally {
784                 SafeClose.close(bdos);
785             }
786         } finally {
787             SafeClose.close(f);
788         }
789         try {
790             f = new Fits("target/write_m13_own_h.fits.fz");
791             f.readHDU();// the primary
792             CompressedImageHDU hdu = (CompressedImageHDU) f.readHDU();
793             short[][] actualShortArray = (short[][]) hdu.asImageHDU().getData().getData();
794             Assert.assertArrayEquals(m13_data, actualShortArray);
795             hdu = (CompressedImageHDU) f.readHDU();
796             actualShortArray = (short[][]) hdu.asImageHDU().getData().getData();
797             Assert.assertArrayEquals(m13_data, actualShortArray);
798             hdu = (CompressedImageHDU) f.readHDU();
799             actualShortArray = (short[][]) hdu.asImageHDU().getData().getData();
800             Assert.assertArrayEquals(m13_data, actualShortArray);
801         } finally {
802             SafeClose.close(f);
803         }
804     }
805 
806     @Test
807     public void writeHcompressFloat() throws Exception {
808         Fits f = null;
809         try {
810             f = new Fits();
811             CompressedImageHDU compressedHdu = CompressedImageHDU.fromImageHDU(m13real, 300, 15);
812             HCompressorOption option = compressedHdu.setCompressAlgorithm(Compression.ZCMPTYPE_HCOMPRESS_1)//
813                     .setQuantAlgorithm(Compression.ZQUANTIZ_SUBTRACTIVE_DITHER_2)//
814                     .getCompressOption(QuantizeOption.class)//
815                     /**/.setQlevel(1.0)//
816                     .getCompressOption(HCompressorOption.class)//
817                     /**/.setScale(1);
818             // ansure same instances of the options
819             Assert.assertSame(compressedHdu.getCompressOption(HCompressorOption.class), option);
820             Assert.assertSame(compressedHdu.getCompressOption(QuantizeOption.class),
821                     compressedHdu.getCompressOption(QuantizeOption.class));
822             compressedHdu.compress();
823             f.addHDU(compressedHdu);
824             compressedHdu = CompressedImageHDU.fromImageHDU(m13real, 300, 1);
825             compressedHdu.setCompressAlgorithm(Compression.ZCMPTYPE_HCOMPRESS_1)//
826                     .setQuantAlgorithm(Compression.ZQUANTIZ_SUBTRACTIVE_DITHER_2)//
827                     .getCompressOption(HCompressorOption.class)//
828                     /**/.setScale(1);
829             compressedHdu.getCompressOption(QuantizeOption.class).setQlevel(1.0);
830             compressedHdu.compress();
831             f.addHDU(compressedHdu);
832             compressedHdu = CompressedImageHDU.fromImageHDU(m13real, 100, 300);
833             compressedHdu.setCompressAlgorithm(Compression.ZCMPTYPE_HCOMPRESS_1)//
834                     .setQuantAlgorithm(Compression.ZQUANTIZ_SUBTRACTIVE_DITHER_2)//
835                     .getCompressOption(HCompressorOption.class)//
836                     /**/.setSmooth(true)//
837                     /**/.setScale(1);
838             compressedHdu.getCompressOption(QuantizeOption.class).setQlevel(1.0);
839             compressedHdu.compress();
840             f.addHDU(compressedHdu);
841             FitsOutputStream bdos = null;
842             try {
843                 bdos = new FitsOutputStream(new FileOutputStream("target/write_m13real_own_h.fits.fz"));
844                 f.write(bdos);
845             } finally {
846                 SafeClose.close(bdos);
847             }
848         } finally {
849             SafeClose.close(f);
850         }
851         try {
852             f = new Fits("target/write_m13real_own_h.fits.fz");
853             f.readHDU();
854             CompressedImageHDU hdu = (CompressedImageHDU) f.readHDU();
855             float[][] actualShortArray = (float[][]) hdu.asImageHDU().getData().getData();
856             assertArrayEquals(m13_data_real, actualShortArray, 9f);
857             hdu = (CompressedImageHDU) f.readHDU();
858             actualShortArray = (float[][]) hdu.asImageHDU().getData().getData();
859             assertArrayEquals(m13_data_real, actualShortArray, .000000000001f);
860             hdu = (CompressedImageHDU) f.readHDU();
861             actualShortArray = (float[][]) hdu.asImageHDU().getData().getData();
862             assertArrayEquals(m13_data_real, actualShortArray, 6f);
863         } finally {
864             SafeClose.close(f);
865         }
866     }
867 
868     @Test
869     public void writeRice() throws Exception {
870         Fits f = null;
871         try {
872             f = new Fits();
873             CompressedImageHDU compressedHdu = CompressedImageHDU.fromImageHDU(m13, 300, 15);
874             compressedHdu.setCompressAlgorithm(Compression.ZCMPTYPE_RICE_1)//
875                     .setQuantAlgorithm((String) null)//
876                     .getCompressOption(RiceCompressOption.class)//
877                     /**/.setBlockSize(32)//
878                     /**/.setBytePix(2);
879             compressedHdu.compress();
880             f.addHDU(compressedHdu);
881             compressedHdu = CompressedImageHDU.fromImageHDU(m13, 300, 1);
882             compressedHdu.setCompressAlgorithm(Compression.ZCMPTYPE_RICE_1)//
883                     .setQuantAlgorithm((String) null)//
884                     .getCompressOption(RiceCompressOption.class)//
885                     /**/.setBlockSize(32)//
886                     /**/.setBytePix(2);
887             compressedHdu.compress();
888             f.addHDU(compressedHdu);
889             compressedHdu = CompressedImageHDU.fromImageHDU(m13, 100, 300);
890             compressedHdu.setCompressAlgorithm(Compression.ZCMPTYPE_RICE_1)//
891                     .setQuantAlgorithm((String) null)//
892                     .getCompressOption(RiceCompressOption.class)//
893                     /**/.setBlockSize(32)//
894                     /**/.setBytePix(2);
895             compressedHdu.compress();
896             f.addHDU(compressedHdu);
897             FitsOutputStream bdos = null;
898             try {
899                 bdos = new FitsOutputStream(new FileOutputStream("target/write_m13_own.fits.fz"));
900                 f.write(bdos);
901             } finally {
902                 SafeClose.close(bdos);
903             }
904         } finally {
905             SafeClose.close(f);
906         }
907         try {
908             f = new Fits("target/write_m13_own.fits.fz");
909             f.readHDU();// the primary
910 
911             CompressedImageHDU hdu = (CompressedImageHDU) f.readHDU();
912             Assert.assertEquals("2", findCompressOption(hdu.getHeader(), Compression.BYTEPIX).getValue());
913             short[][] actualShortArray = (short[][]) hdu.asImageHDU().getData().getData();
914             Assert.assertArrayEquals(m13_data, actualShortArray);
915 
916             hdu = (CompressedImageHDU) f.readHDU();
917             Assert.assertEquals("2", findCompressOption(hdu.getHeader(), Compression.BYTEPIX).getValue());
918             actualShortArray = (short[][]) hdu.asImageHDU().getData().getData();
919             Assert.assertArrayEquals(m13_data, actualShortArray);
920 
921             hdu = (CompressedImageHDU) f.readHDU();
922             Assert.assertEquals("2", findCompressOption(hdu.getHeader(), Compression.BYTEPIX).getValue());
923             actualShortArray = (short[][]) hdu.asImageHDU().getData().getData();
924             Assert.assertArrayEquals(m13_data, actualShortArray);
925 
926         } finally {
927             SafeClose.close(f);
928         }
929     }
930 
931     @Test
932     public void writeRiceSpeciaIntOverflow() throws Exception {
933         Fits f = null;
934         int[][] expectedIntData;
935         try {
936             f = new Fits(resolveLocalOrRemoteFileName("hmi.fits"));
937             ImageHDU uncompressed = (ImageHDU) f.getHDU(1);
938             expectedIntData = (int[][]) uncompressed.getData().getData();
939             f.close();
940             f = new Fits();
941             CompressedImageHDU compressedHdu = CompressedImageHDU.fromImageHDU(uncompressed, uncompressed.getAxes()[0], 4);
942             compressedHdu.setCompressAlgorithm(Compression.ZCMPTYPE_RICE_1)//
943                     .setQuantAlgorithm((String) null)//
944                     .getCompressOption(RiceCompressOption.class)//
945                     /**/.setBlockSize(32)//
946                     /**/.setBytePix(4);
947             compressedHdu.compress();
948             f.addHDU(compressedHdu);
949             FitsOutputStream bdos = null;
950             try {
951                 bdos = new FitsOutputStream(new FileOutputStream("target/hmi.fits.fz"));
952                 f.write(bdos);
953             } finally {
954                 SafeClose.close(bdos);
955             }
956         } finally {
957             SafeClose.close(f);
958         }
959         try {
960             f = new Fits("target/hmi.fits.fz");
961             f.readHDU();// the primary
962             CompressedImageHDU hdu = (CompressedImageHDU) f.readHDU();
963             Assert.assertEquals("4", findCompressOption(hdu.getHeader(), Compression.BYTEPIX).getValue());
964             ImageHDU asImageHDU = hdu.asImageHDU();
965             int[][] actualIntArray = (int[][]) asImageHDU.getData().getData();
966 
967             Assert.assertArrayEquals(expectedIntData, actualIntArray);
968             Assert.assertNull(asImageHDU.getHeader().getStringValue(Standard.TFIELDS.key()));
969             Assert.assertNull(asImageHDU.getHeader().getStringValue(Standard.TTYPEn.n(1).key()));
970         } finally {
971             SafeClose.close(f);
972         }
973     }
974 
975     @Test
976     public void writeRiceFloat() throws Exception {
977         Fits f = null;
978 
979         try {
980             f = new Fits();
981             CompressedImageHDU compressedHdu = CompressedImageHDU.fromImageHDU(m13real, 300, 15);
982             compressedHdu.setCompressAlgorithm(Compression.ZCMPTYPE_RICE_1)//
983                     .setQuantAlgorithm(Compression.ZQUANTIZ_SUBTRACTIVE_DITHER_2)//
984                     .getCompressOption(QuantizeOption.class)//
985                     /**/.setQlevel(1.0)//
986                     /**/.getCompressOption(RiceCompressOption.class)//
987                     /*  */.setBlockSize(32);
988             compressedHdu.compress();
989             f.addHDU(compressedHdu);
990             compressedHdu = CompressedImageHDU.fromImageHDU(m13real, 300, 1);
991             compressedHdu.setCompressAlgorithm(Compression.ZCMPTYPE_RICE_1)//
992                     .setQuantAlgorithm(Compression.ZQUANTIZ_SUBTRACTIVE_DITHER_2)//
993                     .getCompressOption(RiceCompressOption.class)//
994                     /**/.setBlockSize(32);
995             compressedHdu.getCompressOption(QuantizeOption.class).setQlevel(1.0);
996             compressedHdu.compress();
997             f.addHDU(compressedHdu);
998             compressedHdu = CompressedImageHDU.fromImageHDU(m13real, 100, 300);
999             compressedHdu.setCompressAlgorithm(Compression.ZCMPTYPE_RICE_1)//
1000                     .setQuantAlgorithm(Compression.ZQUANTIZ_SUBTRACTIVE_DITHER_2)//
1001                     .getCompressOption(RiceCompressOption.class)//
1002                     /**/.setBlockSize(32);
1003             compressedHdu.getCompressOption(QuantizeOption.class).setQlevel(1.0);
1004             compressedHdu.compress();
1005             f.addHDU(compressedHdu);
1006             FitsOutputStream bdos = null;
1007             try {
1008                 bdos = new FitsOutputStream(new FileOutputStream("target/write_m13real_own.fits.fz"));
1009                 f.write(bdos);
1010             } finally {
1011                 SafeClose.close(bdos);
1012             }
1013         } finally {
1014             SafeClose.close(f);
1015         }
1016         try {
1017             f = new Fits("target/write_m13real_own.fits.fz");
1018             f.readHDU();
1019             CompressedImageHDU hdu = (CompressedImageHDU) f.readHDU();
1020             float[][] actualShortArray = (float[][]) hdu.asImageHDU().getData().getData();
1021             assertArrayEquals(m13_data_real, actualShortArray, 9f);
1022             hdu = (CompressedImageHDU) f.readHDU();
1023             actualShortArray = (float[][]) hdu.asImageHDU().getData().getData();
1024             assertArrayEquals(m13_data_real, actualShortArray, 15f);
1025             hdu = (CompressedImageHDU) f.readHDU();
1026             actualShortArray = (float[][]) hdu.asImageHDU().getData().getData();
1027             assertArrayEquals(m13_data_real, actualShortArray, 6f);
1028         } finally {
1029             SafeClose.close(f);
1030         }
1031     }
1032 
1033     @Test
1034     public void writeRiceFloatWithForceNoLoss() throws Exception {
1035         Fits f = null;
1036         try {
1037             f = new Fits();
1038             CompressedImageHDU compressedHdu = CompressedImageHDU.fromImageHDU(m13real, 300, 15);
1039             compressedHdu.setCompressAlgorithm(Compression.ZCMPTYPE_RICE_1)//
1040                     .setQuantAlgorithm(Compression.ZQUANTIZ_SUBTRACTIVE_DITHER_2)//
1041                     .forceNoLoss(140, 140, 20, 20)//
1042                     .getCompressOption(QuantizeOption.class)//
1043                     /**/.setQlevel(1.0)//
1044                     .getCompressOption(RiceCompressOption.class)//
1045                     /**/.setBlockSize(32);
1046             compressedHdu.compress();
1047             f.addHDU(compressedHdu);
1048             FitsOutputStream bdos = null;
1049             try {
1050                 bdos = new FitsOutputStream(new FileOutputStream("target/write_m13real_own_noloss.fits.fz"));
1051                 f.write(bdos);
1052             } finally {
1053                 SafeClose.close(bdos);
1054             }
1055         } finally {
1056             SafeClose.close(f);
1057         }
1058         try {
1059             f = new Fits("target/write_m13real_own_noloss.fits.fz");
1060             f.readHDU();
1061             CompressedImageHDU hdu = (CompressedImageHDU) f.readHDU();
1062             float[][] actualShortArray = (float[][]) hdu.asImageHDU().getData().getData();
1063             assertArrayEquals(m13_data_real, actualShortArray, 3.5f);
1064 
1065             for (int x = 140; x < 160; x++) {
1066                 for (int y = 140; y < 160; y++) {
1067                     Assert.assertEquals(actualShortArray[x][y], m13_data_real[x][y], 0.0f);
1068                 }
1069             }
1070         } finally {
1071             SafeClose.close(f);
1072         }
1073     }
1074 
1075     @Test
1076     public void writeRiceDouble() throws Exception {
1077         double[][] m13_double_data = (double[][]) ArrayFuncs.convertArray(m13_data_real, double.class);
1078         ImageData imagedata = ImageHDU.encapsulate(m13_double_data);
1079         ImageHDU m13_double = new ImageHDU(ImageHDU.manufactureHeader(imagedata), imagedata);
1080         Fits f = null;
1081         try {
1082             f = new Fits();
1083             CompressedImageHDU compressedHdu = CompressedImageHDU.fromImageHDU(m13_double, 300, 15);
1084             compressedHdu.setCompressAlgorithm(Compression.ZCMPTYPE_RICE_1)//
1085                     .setQuantAlgorithm(Compression.ZQUANTIZ_SUBTRACTIVE_DITHER_2)//
1086                     .getCompressOption(QuantizeOption.class)//
1087                     /**/.setQlevel(1.0)//
1088                     .getCompressOption(RiceCompressOption.class)//
1089                     /**/.setBlockSize(32);
1090             compressedHdu.compress();
1091             f.addHDU(compressedHdu);
1092             FitsOutputStream bdos = null;
1093             try {
1094                 bdos = new FitsOutputStream(new FileOutputStream("target/write_m13double.fits.fz"));
1095                 f.write(bdos);
1096             } finally {
1097                 SafeClose.close(bdos);
1098             }
1099         } finally {
1100             SafeClose.close(f);
1101         }
1102         try {
1103             f = new Fits("target/write_m13double.fits.fz");
1104             f.readHDU();
1105             CompressedImageHDU hdu = (CompressedImageHDU) f.readHDU();
1106             double[][] actualShortArray = (double[][]) hdu.asImageHDU().getData().getData();
1107             for (int index = 0; index < actualShortArray.length; index++) {
1108                 assertArrayEquals(m13_double_data[index], actualShortArray[index], 3.5d, false);
1109             }
1110         } finally {
1111             SafeClose.close(f);
1112         }
1113     }
1114 
1115     @Test
1116     public void writeRiceFloatWithNullPixelMask() throws Exception {
1117         double[][] data = newTestImageWithSomeBlanks("ForNull");
1118         Fits f = null;
1119         FitsOutputStream bdos = null;
1120         try {
1121             f = new Fits();
1122             bdos = new FitsOutputStream(new FileOutputStream("target/testSomeBlanksInCompressedFloatImage.fits.fz"));
1123             ImageData imageData = new ImageData(data);
1124             ImageHDU hdu = new ImageHDU(ImageHDU.manufactureHeader(imageData), imageData);
1125             CompressedImageHDU compressedHdu = CompressedImageHDU.fromImageHDU(hdu, 100, 15);
1126             compressedHdu.setCompressAlgorithm(Compression.ZCMPTYPE_HCOMPRESS_1)//
1127                     .setQuantAlgorithm(Compression.ZQUANTIZ_SUBTRACTIVE_DITHER_2)//
1128                     .preserveNulls(Compression.ZCMPTYPE_RICE_1)//
1129                     .getCompressOption(QuantizeOption.class)//
1130                     /**/.setQlevel(1.0)/**/.setCheckNull(true)//
1131                     .getCompressOption(HCompressorOption.class)//
1132                     /**/.setScale(4);
1133             compressedHdu.compress();
1134             f.addHDU(compressedHdu);
1135             f.write(bdos);
1136             Assert.assertEquals(Compression.COMPRESSED_DATA_COLUMN,
1137                     compressedHdu.getHeader().findCard(Standard.TTYPEn.n(1)).getValue());
1138         } finally {
1139             SafeClose.close(bdos);
1140             SafeClose.close(f);
1141         }
1142         try {
1143             f = new Fits("target/testSomeBlanksInCompressedFloatImage.fits.fz");
1144             f.readHDU();
1145             CompressedImageHDU hdu = (CompressedImageHDU) f.readHDU();
1146             double[][] actual = (double[][]) hdu.asImageHDU().getData().getData();
1147             for (int index = 0; index < actual.length; index++) {
1148                 assertArrayEquals(data[index], actual[index], 1d, true); // TODO
1149                 // set
1150                 // to
1151                 // true
1152             }
1153         } finally {
1154             SafeClose.close(f);
1155         }
1156     }
1157 
1158     protected double[][] newTestImageWithSomeBlanks(String suffix)
1159             throws FitsException, IOException, FileNotFoundException {
1160         try {
1161             new File("target/testSomeBlanksInCompressedFloatImage" + suffix + ".fits").delete();
1162             new File("target/testSomeBlanksInCompressedFloatImage" + suffix + ".fits.fz").delete();
1163         } catch (Exception e) {
1164             // ignore
1165         }
1166         double[][] data = new double[100][100];
1167         double value = -1000.0d;
1168         int blanks = 0;
1169         Random random = new Random();
1170         for (int index1 = 0; index1 < 100; index1++) {
1171             for (int index2 = 0; index2 < 100; index2++) {
1172                 data[index1][index2] = value;
1173                 if (blanks++ % 20 == 0) {
1174                     data[index1][index2] = Double.NaN;
1175                 } else {
1176                     data[index1][index2] = value;
1177                     value += 0.12345d + random.nextDouble() / 1000d;
1178                 }
1179             }
1180         }
1181         Fits f = null;
1182         FitsOutputStream bdos = null;
1183         try {
1184             f = new Fits();
1185             bdos = new FitsOutputStream(
1186                     new FileOutputStream("target/testSomeBlanksInCompressedFloatImage" + suffix + ".fits"));
1187             ImageData imageData = new ImageData(data);
1188             ImageHDU hdu = new ImageHDU(ImageHDU.manufactureHeader(imageData), imageData);
1189             f.addHDU(hdu);
1190             f.write(bdos);
1191         } finally {
1192             SafeClose.close(bdos);
1193             SafeClose.close(f);
1194         }
1195         return data;
1196     }
1197 
1198     @Test
1199     public void testImagePlusCompressedImage1() throws Exception {
1200         // Test using a FITS file with junk at the end...
1201         testImagePlusCompressedImage(
1202                 resolveLocalOrRemoteFileName("03h-80dec--C_CVT_2013-12-29-MW1-03h_Light_600SecISO200_000042.fit"));
1203         // No exception thrown
1204     }
1205 
1206     @Test
1207     public void testImagePlusCompressedImage2() throws Exception {
1208         // Test using a FITS file with junk at the end...
1209         testImagePlusCompressedImage(
1210                 resolveLocalOrRemoteFileName("17h-75dec--BINT_C_CVT_2014-06-25-MW1-17h_Light_600SecISO200_000031.fit"));
1211         // No exception thrown
1212     }
1213 
1214     private void testImagePlusCompressedImage(String imageFile) throws Exception {
1215         BasicHDU<?>[] fitsFileHDU = null;
1216         InputStream fileStream = new BufferedInputStream(new FileInputStream(imageFile));
1217         Fits fitsFile = new Fits(fileStream);
1218         fitsFileHDU = fitsFile.read();
1219         for (BasicHDU<?> element : fitsFileHDU) {
1220             if (element.getHeader().containsKey("ZIMAGE")) {
1221                 if (element.getHeader().getBooleanValue("ZIMAGE")) {
1222                     CompressedImageHDU hdu = (CompressedImageHDU) element;
1223                     ImageHDU uncompressedImage = null;
1224                     uncompressedImage = hdu.asImageHDU();
1225                 }
1226             }
1227         }
1228         fitsFile.close();
1229         fileStream.close();
1230     }
1231 
1232     @Test
1233     public void testDitherDecompress() throws Exception {
1234         Fits fits = new Fits("../blackbox-images/fpack.fits.fz");
1235         fits.readHDU();
1236         ImageHDU im = ((CompressedImageHDU) fits.readHDU()).asImageHDU();
1237         fits.close();
1238 
1239         fits = new Fits("../blackbox-images/funpack.fits");
1240         ImageHDU ref = (ImageHDU) fits.readHDU();
1241 
1242         assertArrayEquals((float[][]) ref.getData().getData(), (float[][]) im.getData().getData(), 0.01f);
1243         fits.close();
1244     }
1245 }