Я использую javax.imageio.ImageIO для записи файлов JPEG. По умолчанию: если я пытаюсь написать изображение с миниатюрой, эта миниатюра обрезается до размера 255x255.
Можно ли использовать только классы ImageIO для встраивания миниатюры размером 300x300 пикселей?
Я (думаю, что) понимаю, что это связано с тем, что реализация ImageIO использует старомодный маркер APP0 (с использованием JFIF вместо более современного EXIF), а ширина и высота ДОЛЖНЫ быть выражены в байтах.< /p>
Однако:
Я просматриваю код Sun и думаю (?), что можно будет вставлять миниатюры большего размера, если я смогу запустить код, который будет использовать JFIFThumbJPEG< /код> реализация. Миниатюра по умолчанию записывается в виде необработанной таблицы байтов RGB, но JFIFThumbJPEG (я думаю) встроит в файл отдельный мини-JPEG. Который должен иметь ширину и высоту, не ограниченные 1 байтом.
Вот модульный тест, демонстрирующий ошибку:
import junit.framework.TestCase;
import org.junit.Test;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
/**
* This demonstrates that ImageIO fails to write a JPEG thumbnail that is larger than 255x255.
*
* However, when I did through the implementation/specification, it looks like ImageIO *is*
* capable of supporting different types of thumbnails. I think if I can figure out
* how to write IIOMetaData to use a JFIFThumbJPEG then I may (?) be able to write thumbnails
* of arbitrary size.
*
*/
public class TestThumbnails extends TestCase {
@Test
public void testImageIOThumbnailSizes() throws IOException {
BufferedImage largeImage = new BufferedImage(1000, 1000, BufferedImage.TYPE_INT_RGB);
// a value smaller than 255 will work:
BufferedImage goodThumbnail = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
// a value larger than 255 will be cropped to 255
BufferedImage badThumbnail = new BufferedImage(300, 300, BufferedImage.TYPE_INT_RGB);
testThumbnail(largeImage, goodThumbnail);
System.out.println("first thumbnail passed");
testThumbnail(largeImage, badThumbnail);
System.out.println("second thumbnail passed");
}
private void testThumbnail(BufferedImage largeImage, BufferedImage thumbnail) throws IOException {
Iterator iter = ImageIO.getImageWritersBySuffix("jpg");
ImageWriter w = iter.next();
byte[] jpegData;
try (ByteArrayOutputStream byteOut = new ByteArrayOutputStream()) {
IIOImage iioImage = new IIOImage(largeImage, Arrays.asList(thumbnail), null);
ImageOutputStream stream = ImageIO.createImageOutputStream(byteOut);
w.setOutput(stream);
w.write(iioImage);
jpegData = byteOut.toByteArray();
}
testReadingThumbnail(jpegData, thumbnail.getWidth(), thumbnail.getHeight());
}
private void testReadingThumbnail(byte[] jpegData, int expectedThumbnailWidth, int expectedThumbnailHeight) throws IOException {
Iterator iter = ImageIO.getImageReadersBySuffix("jpg");
ImageReader reader = iter.next();
try (ByteArrayInputStream byteIn = new ByteArrayInputStream(jpegData)) {
reader.setInput(ImageIO.createImageInputStream(byteIn));
// Thumbnails larger than 255x255 are trimmed. I want to read back
// a thumbnail that uses the dimensions I passed in:
assertEquals(expectedThumbnailWidth, reader.getThumbnailWidth(0, 0));
assertEquals(expectedThumbnailHeight, reader.getThumbnailHeight(0, 0));
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/790 ... -thumbnail