Bagaimana saya boleh mengubah saiz gambar menggunakan Java?

1. Pengenalan

Dalam tutorial ini, kita akan belajar bagaimana mengubah ukuran (skala) gambar menggunakan Java. Kami akan meneroka kedua-dua inti Java dan perpustakaan pihak ketiga sumber terbuka yang menawarkan ciri ukuran gambar.

Penting untuk disebutkan bahawa kita dapat menskalakan gambar ke atas dan ke bawah. Dalam contoh kod dalam tutorial ini, kami akan mengubah ukuran gambar menjadi lebih kecil kerana, dalam praktiknya, itulah senario yang paling biasa.

2. Ubah saiz Imej Menggunakan Java Core

Core Java menawarkan pilihan berikut untuk mengubah ukuran gambar:

  • Ubah saiz menggunakan java.awt.Graphics2D
  • Ubah saiz menggunakan Image # getScaledInstance

2.1. java.awt.Grafik2D

Graphics2D adalah kelas asas untuk membuat bentuk, teks, dan gambar 2 dimensi pada platform Java.

Mari mulakan dengan mengubah saiz gambar menggunakan Graphics2D :

BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) throws IOException { BufferedImage resizedImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB); Graphics2D graphics2D = resizedImage.createGraphics(); graphics2D.drawImage(originalImage, 0, 0, targetWidth, targetHeight, null); graphics2D.dispose(); return resizedImage; }

Mari lihat seperti apa gambar sebelum dan selepas mengubah saiz:

The BufferedImage.TYPE_INT_RGB parameter menunjukkan model warna imej. Senarai lengkap nilai yang tersedia terdapat dalam dokumentasi Java BufferedImage rasmi .

Graphics2D menerima parameter tambahan yang disebut RenderingHints . Kami menggunakan RenderingHints untuk mempengaruhi aspek pemprosesan gambar yang berbeza dan yang paling penting kualiti dan masa pemprosesan.

Kita boleh menambahkan RenderingHint menggunakan kaedah setRenderingHint :

graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);

Senarai lengkap RenderingHints boleh didapati dalam tutorial Oracle ini.

2.2. Image.getScaledInstance ()

Pendekatan menggunakan Gambar ini sangat mudah dan menghasilkan gambar dengan kualiti yang memuaskan:

BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) throws IOException { Image resultingImage = originalImage.getScaledInstance(targetWidth, targetHeight, Image.SCALE_DEFAULT); BufferedImage outputImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB); outputImage.getGraphics().drawImage(resultingImage, 0, 0, null); return outputImage; }

Mari lihat apa yang berlaku dengan gambar sesuatu yang sedap:

Kami juga dapat mengarahkan mekanisme penskalaan untuk menggunakan salah satu pendekatan yang tersedia dengan memberikan metode getScaledInstance () dengan bendera yang menunjukkan jenis algoritma yang akan digunakan untuk keperluan pengambilan sampel gambar kami:

Image resultingImage = originalImage.getScaledInstance(targetWidth, targetHeight, Image.SCALE_SMOOTH);

Semua bendera yang ada dijelaskan dalam dokumentasi Java Image rasmi.

3. Imgscalr

Imgscalr menggunakan Graphic2D di latar belakang. Ia mempunyai API sederhana dengan beberapa kaedah yang berbeza untuk mengubah ukuran gambar.

Imgscalr memberi kita hasil yang paling baik, hasil terpantas, atau hasil seimbang bergantung pada pilihan penskalaan yang kita pilih. Ciri manipulasi gambar lain juga tersedia - seperti ciri pemotongan dan penggiliran. Mari tunjukkan bagaimana ia berfungsi dalam contoh mudah.

Kami akan menambahkan kebergantungan Maven berikut:

 org.imgscalr imgscalr-lib 4.2 

Periksa Maven Central untuk versi terkini.

Cara termudah untuk menggunakan Imgscalr adalah:

BufferedImage simpleResizeImage(BufferedImage originalImage, int targetWidth) throws Exception { return Scalr.resize(originalImage, targetWidth); }

Di mana originalImage adalah BufferedImage yang akan diubah saiznya dan targetWidth adalah lebar gambar hasil. Pendekatan ini akan mengekalkan perkadaran gambar asal dan menggunakan parameter lalai - Kaedah.AUTOMATIK dan Mode.AUTOMATIK .

Bagaimana kaitannya dengan gambar buah yang sedap? Mari lihat:

Perpustakaan juga membolehkan pelbagai pilihan konfigurasi, dan, ia menangani ketelusan gambar di latar belakang.

Parameter yang paling penting adalah:

  • mod - digunakan untuk menentukan mod perubahan saiz yang akan digunakan algoritma. Sebagai contoh, kita dapat menentukan sama ada kita ingin mengekalkan bahagian gambar (pilihannya adalah AUTOMATIK, FIT_EXACT, FIT_TO_HEIGHT, dan FIT_TO_WIDTH )
  • kaedah - memerintahkan proses pengubahan saiz sehingga fokusnya adalah pada kelajuan, kualiti, atau kedua-duanya. Nilai yang mungkin adalah AUTOMATIK, DIimbangkan, KUALITI, SPEED, ULTRA_QUALITY

Juga mungkin untuk menentukan sifat ubah saiz tambahan yang akan memberi kita log atau mengarahkan perpustakaan untuk melakukan beberapa pengubahsuaian warna pada gambar (menjadikannya lebih ringan, lebih gelap, skala kelabu, dan sebagainya).

Mari gunakan parameterisasi kaedah ukuran penuh () :

BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) throws Exception { return Scalr.resize(originalImage, Scalr.Method.AUTOMATIC, Scalr.Mode.AUTOMATIC, targetWidth, targetHeight, Scalr.OP_ANTIALIAS); }

Dan sekarang kita mendapat:

Imgscalr berfungsi dengan semua fail yang disokong oleh Java Image IO - JPG, BMP, JPEG, WBMP, PNG, dan GIF.

4. Thumbnailator

Thumbnailator adalah pustaka pengubah saiz gambar sumber terbuka untuk Java yang menggunakan penskalaan bilinear progresif. Ia menyokong JPG, BMP, JPEG, WBMP, PNG, dan GIF.

We'll include it in our project by adding the following Maven dependency to our pom.xml:

 net.coobird thumbnailator 0.4.11 

Available dependency versions can be found on Maven Central.

It has a very simple API and allows us to set output quality in percentage:

BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) throws Exception { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); Thumbnails.of(originalImage) .size(targetWidth, targetHeight) .outputFormat("JPEG") .outputQuality(1) .toOutputStream(outputStream); byte[] data = outputStream.toByteArray(); ByteArrayInputStream inputStream = new ByteArrayInputStream(data); return ImageIO.read(inputStream); }

Let's see how this smiling photograph looks before and after resizing:

It also has an option for batch processing:

Thumbnails.of(new File("path/to/directory").listFiles()) .size(300, 300) .outputFormat("JPEG") .outputQuality(0.80) .toFiles(Rename.PREFIX_DOT_THUMBNAIL);

As Imgscalr, Thumblinator works with all files supported by Java Image IO – JPG, BMP, JPEG, WBMP, PNG, and GIF.

5. Marvin

Marvin is a handy tool for image manipulation and it offers a lot of useful basic (crop, rotate, skew, flip, scale) and advanced (blur, emboss, texturing) features.

As before, we'll add Maven dependencies needed for Marvin resizing:

 com.github.downgoon marvin 1.5.5 pom   com.github.downgoon MarvinPlugins 1.5.5 

Available Marvin dependency versions can be found on Maven Central, along with the Marvin Plugins versions.

The downside of Marvin is that it doesn't offer an additional scaling configuration. Also, the scale method requires an image and image clone which is a bit cumbersome:

BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) { MarvinImage image = new MarvinImage(originalImage); Scale scale = new Scale(); scale.load(); scale.setAttribute("newWidth", targetWidth); scale.setAttribute("newHeight", targetHeight); scale.process(image.clone(), image, null, null, false); return image.getBufferedImageNoAlpha(); }

Let's now resize an image of a flower and see how it goes:

6. Best Practice

Image processing is an expensive operation in terms of resources, so picking the highest quality is not necessarily the best option when we don't really need it.

Let's see the performance of all of the approaches. We took one 1920×1920 px image, and scaled it to 200×200 px. The resulting observed times are as follows:

  • java.awt.Graphics2D – 34ms
  • Image.getScaledInstance() – 235ms
  • Imgscalr – 143ms
  • Thumbnailator – 547ms
  • Marvin – 361ms

Juga, semasa menentukan lebar dan tinggi gambar sasaran, kita harus memperhatikan nisbah aspek gambar. Dengan cara ini gambar akan mengekalkan bahagian asalnya dan tidak akan diregangkan.

7. Kesimpulannya

Artikel ini menggambarkan beberapa cara untuk mengubah ukuran gambar di Java. Kami juga mengetahui berapa banyak faktor yang berbeza yang dapat mempengaruhi proses pengubahan saiz.

Contoh kod lengkap boleh didapati di GitHub.