Saya perlu mengubah ukuran file PNG, JPEG dan GIF. Bagaimana saya bisa melakukan ini menggunakan Java?
Saya perlu mengubah ukuran file PNG, JPEG dan GIF. Bagaimana saya bisa melakukan ini menggunakan Java?
Jawaban:
Setelah memuat gambar, Anda dapat mencoba:
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 Saya baru saja merilis (Apache 2, host di GitHub) perpustakaan penskalaan gambar sederhana untuk Java yang disebut imgscalr (tersedia di pusat Maven ).
Perpustakaan menerapkan beberapa pendekatan berbeda untuk penskalaan gambar (termasuk pendekatan tambahan Chris Campbell dengan beberapa peningkatan kecil) dan akan memilih pendekatan yang paling optimal untuk Anda jika Anda memintanya, atau memberi Anda tampilan tercepat atau terbaik (jika Anda minta itu).
Penggunaannya sangat sederhana, hanya banyak metode statis. Kasus penggunaan yang paling sederhana adalah:
BufferedImage scaledImage = Scalr.resize(myImage, 200);
Semua operasi mempertahankan proporsi asli gambar, jadi dalam hal ini Anda meminta imgscalr untuk mengubah ukuran gambar Anda dalam batas lebar 200 piksel dan tinggi 200 piksel dan secara default itu akan secara otomatis memilih pendekatan terbaik yang tampak dan tercepat untuk itu karena tidak tidak ditentukan.
Saya menyadari pada awalnya ini terlihat seperti promosi diri (memang), tetapi saya menghabiskan waktu yang adil untuk meneliti topik yang sama persis ini dan terus menghasilkan berbagai hasil / pendekatan / pemikiran / saran dan memutuskan untuk duduk dan menulis implementasi sederhana yang akan mengatasi 80-85% kasus penggunaan di mana Anda memiliki gambar dan mungkin menginginkan thumbnail untuk itu - baik secepat mungkin atau setampan mungkin (bagi yang sudah mencoba, Anda akan melihat melakukan Graphics.drawImage bahkan dengan interpolasi BICUBIC ke gambar yang cukup kecil, masih terlihat seperti sampah).
new ImageScaler(img).resizeTo(...).rotate(...).cropTo(...).toOutputBuffer()
. Saya juga menyukai cara Anda dan saya pikir ini lebih sederhana.
Thumbnailator adalah pustaka pengubahan ukuran sumber gambar terbuka untuk Java dengan antarmuka yang lancar, didistribusikan di bawah lisensi MIT.
Saya menulis perpustakaan ini karena membuat thumbnail berkualitas tinggi di Jawa bisa jadi sangat sulit, dan kode yang dihasilkan bisa sangat berantakan. Dengan Thumbnailator, dimungkinkan untuk mengekspresikan tugas yang cukup rumit menggunakan API lancar yang sederhana.
Contoh sederhana
Sebagai contoh sederhana, mengambil gambar dan mengubah ukurannya menjadi 100 x 100 (mempertahankan rasio aspek dari gambar asli), dan menyimpannya ke file dapat dicapai dalam satu pernyataan:
Thumbnails.of("path/to/image")
.size(100, 100)
.toFile("path/to/thumbnail");
Contoh lanjutan
Melakukan tugas pengubahan ukuran yang rumit disederhanakan dengan antarmuka Thumbnailator yang lancar.
Misalkan kita ingin melakukan hal berikut:
0.85
,thumbnail.
ditambahkan ke awalDiterjemahkan ke Thumbnailator, kami dapat melakukan hal di atas dengan yang berikut:
Thumbnails.of(new File("path/to/directory").listFiles())
.size(100, 100)
.outputFormat("JPEG")
.outputQuality(0.85)
.toFiles(Rename.PREFIX_DOT_THUMBNAIL);
Catatan tentang kualitas dan kecepatan gambar
Perpustakaan ini juga menggunakan metode penskalaan bilinear progresif yang disorot dalam Filthy Rich Clients oleh Chet Haase dan Romain Guy untuk menghasilkan thumbnail berkualitas tinggi sambil memastikan kinerja runtime yang dapat diterima.
Anda tidak perlu perpustakaan untuk melakukan ini. Anda dapat melakukannya dengan Java itu sendiri.
Chris Campbell memiliki tulisan yang luar biasa dan terperinci tentang penskalaan gambar - lihat artikel ini .
Chet Haase dan Romain Guy juga memiliki penulisan skala gambar yang terperinci dan sangat informatif dalam buku mereka, Filthy Rich Clients .
Java Advanced Imaging sekarang open source, dan menyediakan operasi yang Anda butuhkan.
Jika Anda berurusan dengan gambar besar atau ingin hasil yang terlihat bagus, itu bukan tugas sepele di java. Cukup melakukannya melalui operasi skala ulang melalui Graphics2D tidak akan membuat thumbnail berkualitas tinggi. Anda dapat melakukannya menggunakan JAI, tetapi membutuhkan lebih banyak pekerjaan daripada yang Anda bayangkan untuk mendapatkan sesuatu yang terlihat bagus dan JAI memiliki kebiasaan buruk untuk meledakkan JVM kami dengan kesalahan OutOfMemory.
Saya sarankan menggunakan ImageMagick sebagai executable eksternal jika Anda bisa melakukannya. Mudah digunakan dan melakukan pekerjaan dengan benar sehingga Anda tidak perlu melakukannya.
Java API tidak menyediakan fitur penskalaan standar untuk gambar dan menurunkan kualitas gambar.
Karena itu saya mencoba menggunakan cvResize dari JavaCV tetapi tampaknya menyebabkan masalah.
Saya menemukan perpustakaan yang bagus untuk penskalaan gambar: cukup tambahkan ketergantungan untuk "penskalaan java-image" di pom.xml Anda.
<dependency>
<groupId>com.mortennobel</groupId>
<artifactId>java-image-scaling</artifactId>
<version>0.8.6</version>
</dependency>
Di repositori pakar Anda akan mendapatkan versi terbaru untuk ini.
Ex. Dalam program java Anda
ResampleOp resamOp = new ResampleOp(50, 40);
BufferedImage modifiedImage = resamOp.filter(originalBufferedImage, null);
Anda bisa mencoba menggunakan GraphicsMagick Image Processing System dengan im4java sebagai antarmuka perintah-perintah untuk Java.
Ada banyak keuntungan dari GraphicsMagick, tetapi satu untuk semua:
Image Magick telah disebutkan. Ada proyek ujung depan JNI yang disebut JMagick. Ini bukan proyek yang sangat stabil (dan Image Magick sendiri telah dikenal banyak berubah dan bahkan merusak kompatibilitas). Yang mengatakan, kami memiliki pengalaman yang baik menggunakan JMagick dan versi yang kompatibel dari Image Magick di lingkungan produksi untuk melakukan penskalaan pada throughput tinggi, tingkat latensi rendah. Kecepatan jauh lebih baik daripada dengan semua perpustakaan grafis Java yang kami coba sebelumnya.
Cukup gunakan jawaban Burkhard tetapi tambahkan baris ini setelah membuat gambar:
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
Anda juga dapat mengatur nilainya ke BICUBIC, ini akan menghasilkan gambar berkualitas lebih baik tetapi merupakan operasi yang lebih mahal. Ada petunjuk rendering lain yang dapat Anda atur tetapi saya telah menemukan bahwa interpolasi menghasilkan efek yang paling menonjol. Perlu diingat jika Anda ingin memperbesar banyak, kode java kemungkinan besar akan sangat lambat. Saya menemukan gambar yang lebih besar mulai menghasilkan jeda sekitar 300% zoom bahkan dengan semua petunjuk render diatur untuk mengoptimalkan kecepatan di atas kualitas.
Anda dapat menggunakan Marvin (kerangka pemrosesan gambar Java murni) untuk operasi semacam ini: http://marvinproject.sourceforge.net
Plug-in skala: http://marvinproject.sourceforge.net/en/plugins/scale.html
Ternyata menulis scaler pemain tidak sepele. Saya melakukannya sekali untuk proyek sumber terbuka: ImageScaler .
Pada prinsipnya 'java.awt.Image # getScaledInstance (int, int, int)' akan melakukan pekerjaan dengan baik, tetapi ada bug yang buruk dengan ini - lihat tautan saya untuk detail.
Saya telah mengembangkan solusi dengan kelas yang tersedia secara bebas (AnimatedGifEncoder, GifDecoder, dan LWZEncoder) tersedia untuk menangani Animasi GIF.
Anda dapat mengunduh jar jgifcode dan menjalankan kelas GifImageUtil. Tautan: http://www.jgifcode.com
Anda dapat menggunakan produk populer berikut: thumbnailator
Jika Anda tidak ingin mengimpor imgScalr seperti @Riyad Kalla jawaban di atas yang saya uji juga berfungsi dengan baik, Anda dapat melakukan ini diambil dari Peter Walser jawaban @Peter Walser pada masalah lain:
/**
* 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;
}
}
Coba metode berikut ini:
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);