ฉันต้องการปรับขนาดไฟล์ PNG, JPEG และ GIF ฉันจะทำสิ่งนี้โดยใช้ Java ได้อย่างไร?
ฉันต้องการปรับขนาดไฟล์ PNG, JPEG และ GIF ฉันจะทำสิ่งนี้โดยใช้ Java ได้อย่างไร?
คำตอบ:
หลังจากโหลดภาพคุณสามารถลอง:
BufferedImage createResizedCopy(Image originalImage,
int scaledWidth, int scaledHeight,
boolean preserveAlpha)
{
System.out.println("resizing...");
int imageType = preserveAlpha ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, imageType);
Graphics2D g = scaledBI.createGraphics();
if (preserveAlpha) {
g.setComposite(AlphaComposite.Src);
}
g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null);
g.dispose();
return scaledBI;
}
FWIW ฉันเพิ่งเปิดตัว (Apache 2 โฮสต์บน GitHub) ไลบรารีการปรับขนาดภาพอย่างง่ายสำหรับ Java ที่เรียกว่าimgscalr (มีอยู่ในMaven central )
ไลบรารีใช้วิธีการต่างๆในการปรับขนาดภาพ (รวมถึงแนวทางที่เพิ่มขึ้นของ Chris Campbell ด้วยการปรับปรุงเล็กน้อยเล็กน้อย) และจะเลือกแนวทางที่เหมาะสมที่สุดสำหรับคุณหากคุณขอหรือให้วิธีที่เร็วที่สุดหรือดูดีที่สุด (ถ้าคุณ ขอที่).
การใช้งานนั้นง่ายมากเพียงแค่มีวิธีการคงที่มากมาย กรณีการใช้งานที่ง่ายที่สุดคือ:
BufferedImage scaledImage = Scalr.resize(myImage, 200);
การดำเนินการทั้งหมดจะรักษาสัดส่วนเดิมของภาพดังนั้นในกรณีนี้คุณขอให้ imgscalr ปรับขนาดภาพของคุณภายในขอบเขตกว้าง 200 พิกเซลและสูง 200 พิกเซลและโดยค่าเริ่มต้นระบบจะเลือกแนวทางที่ดูดีที่สุดและเร็วที่สุดสำหรับสิ่งนั้นโดยอัตโนมัติเนื่องจากไม่มี ไม่ได้ระบุ
ฉันตระหนักดีว่าในตอนแรกสิ่งนี้ดูเหมือนการโปรโมตตัวเอง (มัน) แต่ฉันใช้เวลาส่วนแบ่งที่ยุติธรรมในการเรียนรู้เรื่องเดียวกันนี้และยังคงได้ผลลัพธ์ / แนวทาง / ความคิด / ข้อเสนอแนะที่แตกต่างออกไปและตัดสินใจนั่งลงและเขียน การใช้งานที่เรียบง่ายซึ่งจะกล่าวถึงกรณีการใช้งาน 80-85% ที่คุณมีภาพและอาจต้องการภาพขนาดย่อสำหรับภาพนั้นโดยเร็วที่สุดหรือดูดีที่สุดเท่าที่จะทำได้ (สำหรับผู้ที่ได้ลองใช้แล้วคุณจะสังเกตเห็น การทำ Graphics.drawImage แม้จะมีการแก้ไข BICUBIC ให้เป็นภาพที่เล็กพอ แต่ก็ยังดูเหมือนขยะ)
new ImageScaler(img).resizeTo(...).rotate(...).cropTo(...).toOutputBuffer()
. ฉันชอบวิธีของคุณเหมือนกันและฉันคิดว่ามันง่ายกว่า
Thumbnailatorเป็นไลบรารีการปรับขนาดรูปภาพแบบโอเพนซอร์สสำหรับ Java พร้อมอินเทอร์เฟซที่คล่องแคล่วซึ่งเผยแพร่ภายใต้ลิขสิทธิ์ MIT
ฉันเขียนไลบรารีนี้เนื่องจากการสร้างภาพขนาดย่อคุณภาพสูงใน Java อาจเป็นเรื่องยากอย่างน่าประหลาดใจและโค้ดที่ได้ก็อาจจะยุ่งเหยิง ด้วย Thumbnailator เป็นไปได้ที่จะแสดงงานที่ค่อนข้างซับซ้อนโดยใช้ API ที่เรียบง่าย
ตัวอย่างง่ายๆ
ตัวอย่างง่ายๆเช่นการถ่ายภาพและปรับขนาดเป็น 100 x 100 (รักษาอัตราส่วนของภาพต้นฉบับ) และบันทึกลงในไฟล์สามารถทำได้ในคำสั่งเดียว:
Thumbnails.of("path/to/image")
.size(100, 100)
.toFile("path/to/thumbnail");
ตัวอย่างขั้นสูง
การดำเนินการปรับขนาดที่ซับซ้อนได้ง่ายขึ้นด้วยอินเทอร์เฟซที่คล่องแคล่วของ Thumbnailator
สมมติว่าเราต้องการทำสิ่งต่อไปนี้:
0.85
,thumbnail.
ต่อท้ายแปลเป็น Thumbnailator เราจะสามารถดำเนินการดังต่อไปนี้:
Thumbnails.of(new File("path/to/directory").listFiles())
.size(100, 100)
.outputFormat("JPEG")
.outputQuality(0.85)
.toFiles(Rename.PREFIX_DOT_THUMBNAIL);
หมายเหตุเกี่ยวกับคุณภาพและความเร็วของภาพ
ไลบรารีนี้ยังใช้วิธีการปรับขนาดทวิภาคีแบบโปรเกรสซีฟที่ไฮไลต์ในFilthy Rich Clientsโดย Chet Haase และ Romain Guy เพื่อสร้างภาพขนาดย่อที่มีคุณภาพสูงในขณะที่รับประกันประสิทธิภาพรันไทม์ที่ยอมรับได้
คุณไม่จำเป็นต้องมีห้องสมุดเพื่อทำสิ่งนี้ คุณสามารถทำได้ด้วย Java เอง
Chris Campbell มีการเขียนที่ยอดเยี่ยมและมีรายละเอียดเกี่ยวกับการปรับขนาดภาพ - ดูบทความนี้บทความนี้
เชษฐ์ฮาและ Romain ผู้ชายยังมีรายละเอียดและข้อมูลมากเขียนขึ้นของการปรับภาพในหนังสือของพวกเขาลูกค้าสกปรกที่อุดมไป
ขณะนี้Java Advanced Imagingเป็นโอเพ่นซอร์สและให้การดำเนินการที่คุณต้องการ
หากคุณกำลังจัดการกับภาพขนาดใหญ่หรือต้องการผลลัพธ์ที่ดูดีมันไม่ใช่เรื่องเล็กน้อยใน java เพียงแค่ทำผ่านการปรับขนาดผ่าน Graphics2D จะไม่สร้างภาพขนาดย่อที่มีคุณภาพสูง คุณสามารถทำได้โดยใช้ JAI แต่ต้องทำงานมากกว่าที่คุณจะคิดว่าจะได้อะไรที่ดูดีและ JAI มีนิสัยที่น่ารังเกียจในการทำให้ JVM ของคุณของคุณมีข้อผิดพลาด OutOfMemory
ฉันขอแนะนำให้ใช้ ImageMagick เป็นไฟล์ปฏิบัติการภายนอกหากคุณสามารถหลีกเลี่ยงได้ ใช้งานง่ายและทำงานได้ดีโดยที่คุณไม่ต้องทำ
Java API ไม่มีคุณสมบัติการปรับมาตราส่วนมาตรฐานสำหรับรูปภาพและการดาวน์เกรดคุณภาพของรูปภาพ
ด้วยเหตุนี้ฉันจึงพยายามใช้ cvResize จาก JavaCV แต่ดูเหมือนว่าจะทำให้เกิดปัญหา
ฉันพบไลบรารีที่ดีสำหรับการปรับขนาดรูปภาพ: เพียงเพิ่มการอ้างอิงสำหรับ "java-image-scaling" ใน pom.xml ของคุณ
<dependency>
<groupId>com.mortennobel</groupId>
<artifactId>java-image-scaling</artifactId>
<version>0.8.6</version>
</dependency>
ในที่เก็บ maven คุณจะได้รับเวอร์ชันล่าสุดสำหรับสิ่งนี้
อดีต ในโปรแกรม java ของคุณ
ResampleOp resamOp = new ResampleOp(50, 40);
BufferedImage modifiedImage = resamOp.filter(originalBufferedImage, null);
คุณสามารถลองใช้ระบบประมวลผลภาพ GraphicsMagickกับim4javaเป็นอินเตอร์เฟส comand-line สำหรับ Java
ข้อดีของ GraphicsMagick มีมากมาย แต่สำหรับทุกคน:
Image Magick ได้รับการกล่าวถึง มีโครงการส่วนหน้าของ JNI ที่เรียกว่า JMagick ไม่ใช่โครงการที่มีเสถียรภาพโดยเฉพาะอย่างยิ่ง (และ Image Magick เองก็เป็นที่ทราบกันดีว่าเปลี่ยนไปมากและยังทำลายความเข้ากันได้) กล่าวได้ว่าเรามีประสบการณ์ที่ดีในการใช้ JMagick และ Image Magick เวอร์ชันที่เข้ากันได้ในสภาพแวดล้อมการใช้งานจริงเพื่อทำการปรับขนาดด้วยอัตราความเร็วที่สูงและมีความหน่วงแฝงต่ำ ความเร็วนั้นดีขึ้นอย่างมากด้วยไลบรารีกราฟิก Java ทั้งหมดที่เราเคยลองก่อนหน้านี้
เพียงใช้คำตอบของ Burkhard แต่เพิ่มบรรทัดนี้หลังจากสร้างกราฟิก:
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
คุณยังสามารถตั้งค่าเป็น BICUBIC ซึ่งจะให้ภาพที่มีคุณภาพดีขึ้น แต่เป็นการดำเนินการที่มีราคาแพงกว่า มีคำแนะนำการเรนเดอร์อื่น ๆ ที่คุณสามารถตั้งค่าได้ แต่ฉันพบว่าการแก้ไขทำให้เกิดเอฟเฟกต์ที่โดดเด่นที่สุด โปรดทราบว่าหากคุณต้องการซูมเข้ามาก ๆ โค้ด java มักจะช้ามาก ฉันพบว่าภาพขนาดใหญ่เริ่มสร้างความล่าช้าในการซูมประมาณ 300% แม้ว่าจะมีการตั้งค่าคำแนะนำการแสดงผลทั้งหมดเพื่อปรับให้เหมาะสมกับความเร็วมากกว่าคุณภาพก็ตาม
คุณสามารถใช้ Marvin (กรอบการประมวลผลภาพ Java บริสุทธิ์) สำหรับการดำเนินการประเภทนี้: http://marvinproject.sourceforge.net
สเกลปลั๊กอิน: http://marvinproject.sourceforge.net/en/plugins/scale.html
ปรากฎว่าการเขียนสเกลเลอร์นักแสดงไม่ใช่เรื่องเล็กน้อย ฉันทำครั้งเดียวสำหรับโครงการโอเพ่นซอร์ส: ImageScaler ImageScaler
โดยหลักการแล้ว 'java.awt.Image # getScaledInstance (int, int, int)' จะทำงานได้เช่นกัน แต่มีข้อบกพร่องที่น่ารังเกียจกับสิ่งนี้ - ดูรายละเอียดในลิงค์ของฉัน
ฉันได้พัฒนาโซลูชันด้วยคลาสที่มีให้ใช้งานฟรี (AnimatedGifEncoder, GifDecoder และ LWZEncoder) สำหรับจัดการภาพเคลื่อนไหว GIF
คุณสามารถดาวน์โหลด jgifcode jar และรันคลาส GifImageUtil ลิงค์: http://www.jgifcode.com
คุณสามารถใช้ผลิตภัณฑ์ยอดนิยมดังต่อไปนี้: ตัวแสดงภาพขนาดย่อ
หากคุณไม่ต้องการนำเข้าimgScalrเช่น @Riyad Kalla คำตอบข้างต้นที่ฉันทดสอบก็ใช้ได้ดีคุณสามารถทำได้จากคำตอบของ Peter Walser @Peter Walser ในประเด็นอื่นแม้ว่า:
/**
* utility method to get an icon from the resources of this class
* @param name the name of the icon
* @return the icon, or null if the icon wasn't found.
*/
public Icon getIcon(String name) {
Icon icon = null;
URL url = null;
ImageIcon imgicon = null;
BufferedImage scaledImage = null;
try {
url = getClass().getResource(name);
icon = new ImageIcon(url);
if (icon == null) {
System.out.println("Couldn't find " + url);
}
BufferedImage bi = new BufferedImage(
icon.getIconWidth(),
icon.getIconHeight(),
BufferedImage.TYPE_INT_RGB);
Graphics g = bi.createGraphics();
// paint the Icon to the BufferedImage.
icon.paintIcon(null, g, 0,0);
g.dispose();
bi = resizeImage(bi,30,30);
scaledImage = bi;// or replace with this line Scalr.resize(bi, 30,30);
imgicon = new ImageIcon(scaledImage);
} catch (Exception e) {
System.out.println("Couldn't find " + getClass().getName() + "/" + name);
e.printStackTrace();
}
return imgicon;
}
public static BufferedImage resizeImage (BufferedImage image, int areaWidth, int areaHeight) {
float scaleX = (float) areaWidth / image.getWidth();
float scaleY = (float) areaHeight / image.getHeight();
float scale = Math.min(scaleX, scaleY);
int w = Math.round(image.getWidth() * scale);
int h = Math.round(image.getHeight() * scale);
int type = image.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
boolean scaleDown = scale < 1;
if (scaleDown) {
// multi-pass bilinear div 2
int currentW = image.getWidth();
int currentH = image.getHeight();
BufferedImage resized = image;
while (currentW > w || currentH > h) {
currentW = Math.max(w, currentW / 2);
currentH = Math.max(h, currentH / 2);
BufferedImage temp = new BufferedImage(currentW, currentH, type);
Graphics2D g2 = temp.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(resized, 0, 0, currentW, currentH, null);
g2.dispose();
resized = temp;
}
return resized;
} else {
Object hint = scale > 2 ? RenderingHints.VALUE_INTERPOLATION_BICUBIC : RenderingHints.VALUE_INTERPOLATION_BILINEAR;
BufferedImage resized = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = resized.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
g2.drawImage(image, 0, 0, w, h, null);
g2.dispose();
return resized;
}
}
ลองใช้วิธีการต่อไปนี้:
ImageIcon icon = new ImageIcon("image.png");
Image img = icon.getImage();
Image newImg = img.getScaledInstance(350, 350, java.evt.Image.SCALE_SMOOTH);
icon = new ImageIcon(img);
JOptionPane.showMessageDialog(null, "image on The frame", "Display Image", JOptionPane.INFORMATION_MESSAGE, icon);