测试Spring Boot中的javax.imageio无法找到阅读器

huangapple 未分类评论65阅读模式
标题翻译

Test javax.imageIo within spring boot doesn't find reader

问题

package com.apparence.enlaps.services.pictures;

import com.apparence.enlaps.services.pictures.editor.BasicThumbPictureAdapter;
import com.apparence.enlaps.services.pictures.editor.exceptions.ResizeException;
import com.twelvemonkeys.image.ImageUtil;
import com.twelvemonkeys.imageio.metadata.CompoundDirectory;
import com.twelvemonkeys.imageio.metadata.exif.EXIFReader;
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegment;
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegmentUtil;
import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
import com.twelvemonkeys.imageio.metadata.tiff.TIFFReader;
import com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReaderSpi;
import com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageWriterSpi;
import com.twelvemonkeys.imageio.plugins.tiff.TIFFImageReaderSpi;
import com.twelvemonkeys.imageio.plugins.tiff.TIFFImageWriterSpi;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.test.context.SpringBootContextLoader;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.junit.Assert;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.spi.IIORegistry;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.MemoryCacheImageInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@ActiveProfiles("test")
@DirtiesContext
public class PictureEditorTest {

    BasicThumbPictureAdapter adapter = new BasicThumbPictureAdapter();

    @Before
    public void init() {
        ImageIO.scanForPlugins();
        IIORegistry registry = IIORegistry.getDefaultInstance();
        registry.registerApplicationClasspathSpis();
    }

    @Test
    public void resizeJpgTest() throws IOException, ResizeException {
        Resource resource = new ClassPathResource("img/test2.jpg");
        Assert.assertNotNull("image to check resize exists", resource);
        Assert.assertTrue("image to check resize exists", resource.exists());
        Assert.assertTrue("image to check resize exists", resource.getFile().exists());
        var is = resource.getInputStream();
        Assert.assertTrue("image to check resize exists", is.available() > 0);
        CompoundDirectory sourceExif = getExifData(is);
        Assert.assertNotNull("Source exif have been read", sourceExif);
        var result = adapter.resize(is, 800);
        try (var resultIs = new ByteArrayInputStream(result)) {
            ImageInputStream imageIs = ImageIO.createImageInputStream(resultIs);
            Iterator<ImageReader> readers = ImageIO.getImageReaders(imageIs);
            if (!readers.hasNext()) {
                throw new IllegalArgumentException("No reader found");
            }
            ImageReader reader = readers.next();
            reader.setInput(imageIs);
            Assert.assertEquals("JPEG", reader.getFormatName());
            CompoundDirectory exif = getExifData(resultIs);
            Assert.assertNotNull(exif);
            Assert.assertTrue("width should be <= 800 now", reader.getWidth(0) <= 800);
            Assert.assertTrue("height should be <= 800 now", reader.getHeight(0) <= 800);
            Assert.assertEquals("Orientation has not changed", 5, exif.getEntryByFieldName("orientation").getValue());
        } catch (Exception e) {
            throw new RuntimeException("error while reading result", e);
        }
    }

    private CompoundDirectory getExifData(InputStream resultIs) throws IOException {
        List<JPEGSegment> exifSegment = JPEGSegmentUtil.readSegments(ImageIO.createImageInputStream(resultIs), JPEG.APP1, "Exif");
        if (!exifSegment.isEmpty()) {
            InputStream exifData = exifSegment.get(0).data();
            exifData.read(); // Skip 0-pad for Exif in JFIF
            try (ImageInputStream exifStream = ImageIO.createImageInputStream(exifData)) {
                return (CompoundDirectory) new TIFFReader().read(exifStream);
            }
        }
        return null;
    }
}
英文翻译

currently I would like this test to work within my spring boot. This is a simple unit test on a resizing image function using imageIo, it checks that the resize didn't touch any of the exif data and made a smaller image as requested.
This function work when running the server but fails in unit test on the same image.

saying this :

No reader found
java.lang.IllegalArgumentException: No reader found
	at com.apparence.enlaps.services.pictures.editor.BasicThumbPictureAdapter.resize(BasicThumbPictureAdapter.java:39)
	at com.apparence.enlaps.services.pictures.PictureEditorTest.resizeJpgTest(PictureEditorTest.java:70)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:567)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)

The unit test code is this. How can I make it pass, I believe it's a matter of context no loading all reader methods properly on a unit test context. But my attempt to force loading them seems not working too. I'm out of solutions.

package com.apparence.enlaps.services.pictures;

import com.apparence.enlaps.services.pictures.editor.BasicThumbPictureAdapter;
import com.apparence.enlaps.services.pictures.editor.exceptions.ResizeException;
import com.twelvemonkeys.image.ImageUtil;
import com.twelvemonkeys.imageio.metadata.CompoundDirectory;
import com.twelvemonkeys.imageio.metadata.exif.EXIFReader;
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegment;
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegmentUtil;
import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
import com.twelvemonkeys.imageio.metadata.tiff.TIFFReader;
import com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReaderSpi;
import com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageWriterSpi;
import com.twelvemonkeys.imageio.plugins.tiff.TIFFImageReaderSpi;
import com.twelvemonkeys.imageio.plugins.tiff.TIFFImageWriterSpi;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.test.context.SpringBootContextLoader;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.junit.Assert;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.spi.IIORegistry;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.MemoryCacheImageInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;


@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@ActiveProfiles(&quot;test&quot;)
@DirtiesContext
public class PictureEditorTest {

    BasicThumbPictureAdapter adapter = new BasicThumbPictureAdapter();

    @Before
    public void init() {
        ImageIO.scanForPlugins();
        IIORegistry registry = IIORegistry.getDefaultInstance();
        registry.registerApplicationClasspathSpis();
    }

    // BROKEN test cauz of https://stackoverflow.com/questions/49270343/imageio-unsupported-image-type-twelvemonkeys-plugin-with-fix-not-working
    // IMAGEIO drivers not loaded in test context
    @Test
    public void resizeJpgTest() throws IOException, ResizeException {
        Resource resource = new ClassPathResource(&quot;img/test2.jpg&quot;);
        Assert.assertNotNull(&quot;image to check resize exists&quot;, resource);
        Assert.assertTrue(&quot;image to check resize exists&quot;, resource.exists());
        Assert.assertTrue(&quot;image to check resize exists&quot;, resource.getFile().exists());
        var is = resource.getInputStream();
        Assert.assertTrue(&quot;image to check resize exists&quot;, is.available() &gt; 0);
        CompoundDirectory sourceExif = getExifData(is);
        Assert.assertNotNull(&quot;Source exif have been read&quot;, sourceExif);
        // call resize
        var result = adapter.resize(is, 800);
        // check results
        try (var resultIs = new ByteArrayInputStream(result)) {
            ImageInputStream imageIs = ImageIO.createImageInputStream(resultIs);
            Iterator&lt;ImageReader&gt; readers = ImageIO.getImageReaders(imageIs);
            if (!readers.hasNext()) {
                throw new IllegalArgumentException(&quot;No reader found&quot;);
            }
            ImageReader reader = readers.next();
            reader.setInput(imageIs);
            Assert.assertEquals(&quot;JPEG&quot;, reader.getFormatName());
            CompoundDirectory exif = getExifData(resultIs);
            Assert.assertNotNull(exif);
            Assert.assertTrue(&quot;width should be &lt;= 800 now&quot;, reader.getWidth(0) &lt;= 800);
            Assert.assertTrue(&quot;height should be &lt;= 800 now&quot;, reader.getHeight(0) &lt;= 800);
            Assert.assertEquals(&quot;Orientation has not changed&quot;, 5, exif.getEntryByFieldName(&quot;orientation&quot;).getValue());
        } catch (Exception e) {
            throw new RuntimeException(&quot;error while reading result&quot;, e);
        }
    }

    private CompoundDirectory getExifData(InputStream resultIs) throws IOException {
        List&lt;JPEGSegment&gt; exifSegment = JPEGSegmentUtil.readSegments(ImageIO.createImageInputStream(resultIs), JPEG.APP1, &quot;Exif&quot;);
        if (!exifSegment.isEmpty()) {
            InputStream exifData = exifSegment.get(0).data();
            exifData.read(); // Skip 0-pad for Exif in JFIF
            try (ImageInputStream exifStream = ImageIO.createImageInputStream(exifData)) {
                return (CompoundDirectory) new TIFFReader().read(exifStream);
            }
        }
        return null;
    }
}

huangapple
  • 本文由 发表于 2020年5月30日 16:26:18
  • 转载请务必保留本文链接:https://java.coder-hub.com/62099800.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定