#java #image-manipulation
#java #обработка изображений
Вопрос:
У меня есть приложение, в котором мне нужно выбрать папку, содержащую изображения, и отобразить миниатюры этих изображений с использованием Java. Я не имею ни малейшего представления о том, как представлять изображения в формате миниатюр.
Любые ресурсы, такие как примеры кода, теория или ссылки, были бы действительно полезны.
Спасибо
Комментарии:
1. Какой бы вы хотели размер миниатюр? Некоторые изображения могут быть больше в ширину, чем в высоту; должны ли они масштабироваться одинаково в направлении x и в направлении y?
Ответ №1:
У меня есть этот код, который я использую в одном из своих проектов. Я нашел в сети некоторое время назад (не уверен, где, но если кто-нибудь узнает это, пожалуйста, дайте мне знать, чтобы я мог сослаться на это):
private static byte[] createThumbnail(byte[] bytes)
{
try
{
double scale;
int sizeDifference, originalImageLargestDim;
Image inImage = ImageIO.read(new ByteArrayInputStream(bytes));
//find biggest dimension
if(inImage.getWidth(null) > inImage.getHeight(null))
{
scale = (double)LARGEST_DIMENSION/(double)inImage.getWidth(null);
sizeDifference = inImage.getWidth(null) - LARGEST_DIMENSION;
originalImageLargestDim = inImage.getWidth(null);
}
else
{
scale = (double)LARGEST_DIMENSION/(double)inImage.getHeight(null);
sizeDifference = inImage.getHeight(null) - LARGEST_DIMENSION;
originalImageLargestDim = inImage.getHeight(null);
}
//create an image buffer to draw to
BufferedImage outImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); //arbitrary init so code compiles
Graphics2D g2d;
AffineTransform tx;
if(scale < 1.0d) //only scale if desired size is smaller than original
{
int numSteps = sizeDifference / 100;
int stepSize = sizeDifference / numSteps;
int stepWeight = stepSize/2;
int heavierStepSize = stepSize stepWeight;
int lighterStepSize = stepSize - stepWeight;
int currentStepSize, centerStep;
double scaledW = inImage.getWidth(null);
double scaledH = inImage.getHeight(null);
if(numSteps % 2 == 1) //if there's an odd number of steps
centerStep = (int)Math.ceil((double)numSteps / 2d); //find the center step
else
centerStep = -1; //set it to -1 so it's ignored later
Integer intermediateSize = originalImageLargestDim, previousIntermediateSize = originalImageLargestDim;
for(Integer i=0; i<numSteps; i )
{
if(i 1 != centerStep) //if this isn't the center step
{
if(i == numSteps-1) //if this is the last step
{
//fix the stepsize to account for decimal place errors previously
currentStepSize = previousIntermediateSize - LARGEST_DIMENSION;
}
else
{
if(numSteps - i > numSteps/2) //if we're in the first half of the reductions
currentStepSize = heavierStepSize;
else
currentStepSize = lighterStepSize;
}
}
else //center step, use natural step size
{
currentStepSize = stepSize;
}
intermediateSize = previousIntermediateSize - currentStepSize;
scale = (double)intermediateSize/(double)previousIntermediateSize;
scaledW = (int)scaledW*scale;
scaledH = (int)scaledH*scale;
outImage = new BufferedImage((int)scaledW, (int)scaledH, BufferedImage.TYPE_INT_RGB);
g2d = outImage.createGraphics();
g2d.setBackground(Color.WHITE);
g2d.clearRect(0, 0, outImage.getWidth(), outImage.getHeight());
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
tx = new AffineTransform();
tx.scale(scale, scale);
g2d.drawImage(inImage, tx, null);
g2d.dispose();
inImage = new ImageIcon(outImage).getImage();
previousIntermediateSize = intermediateSize;
}
}
else
{
//just copy the original
outImage = new BufferedImage(inImage.getWidth(null), inImage.getHeight(null), BufferedImage.TYPE_INT_RGB);
g2d = outImage.createGraphics();
g2d.setBackground(Color.WHITE);
g2d.clearRect(0, 0, outImage.getWidth(), outImage.getHeight());
tx = new AffineTransform();
tx.setToIdentity(); //use identity matrix so image is copied exactly
g2d.drawImage(inImage, tx, null);
g2d.dispose();
}
//JPEG-encode the image and write to file.
ByteArrayOutputStream os = new ByteArrayOutputStream();
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(os);
encoder.encode(outImage);
return os.toByteArray();
}
catch(Exception e)
{
throw new RuntimeException(e);
}
}
Ответ №2:
Следующий код масштабирует все изображение в область. Вы можете скопировать-вставить код и запустить его, чтобы посмотреть, что он делает.
Интересным является вызов, g2d.drawImage(img, 0, 0, thumb.getWidth() - 1, thumb.getHeight() - 1, 0, 0, img.getWidth() - 1, img.getHeight() - 1, null);
который копирует изображение в миниатюру, масштабируя его по размеру.
Если вам нужны другие масштабирования для сохранения соотношения сторон, вы могли бы использовать scale() на g2d или выбрать другие исходные координаты.
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
public class ThumbnailFactory {
public ThumbnailFactory() {
}
public void run(String folder) {
File dir = new File(folder);
for (File file : dir.listFiles()) {
createThumbnail(file);
}
}
private void createThumbnail(File file) {
try {
// BufferedImage is the best (Toolkit images are less flexible)
BufferedImage img = ImageIO.read(file);
BufferedImage thumb = createEmptyThumbnail();
// BufferedImage has a Graphics2D
Graphics2D g2d = (Graphics2D) thumb.getGraphics();
g2d.drawImage(img, 0, 0,
thumb.getWidth() - 1,
thumb.getHeight() - 1,
0, 0,
img.getWidth() - 1,
img.getHeight() - 1,
null);
g2d.dispose();
ImageIO.write(thumb, "PNG", createOutputFile(file));
} catch (Exception e) {
e.printStackTrace();
}
}
private File createOutputFile(File inputFile) {
// You'll want something better than this...
return new File(inputFile.getAbsolutePath()
".thumb.png");
}
private BufferedImage createEmptyThumbnail() {
return new BufferedImage(100, 200,
BufferedImage.TYPE_INT_RGB);
}
public static void main(String[] args) {
ThumbnailFactory fac = new ThumbnailFactory();
fac.run("c:\images");
}
}