Bagaimana saya bisa mengubah ukuran gambar menggunakan Java?

126

Saya perlu mengubah ukuran file PNG, JPEG dan GIF. Bagaimana saya bisa melakukan ini menggunakan Java?

mengacau
sumber
14
sejak Anda meminta pustaka, jawaban sebenarnya ada di sini: stackoverflow.com/questions/244164/… . Ini jauh lebih mudah digunakan daripada kode dalam jawaban yang diterima;)
Artur Gajowy
Saya tidak setuju pada bagian perpustakaan: Graphics2D adalah bagian dari perpustakaan awt dan itu adalah open source. Untuk bagian terakhir (open source) saya tidak 100% yakin, tetapi siapa yang akan melihat kode awt?
Burkhard

Jawaban:

87

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;
    }
Burkhard
sumber
9
Saya menemukan teknik ini menciptakan gambar yang tidak berkualitas cukup tinggi untuk kebutuhan saya.
morgancodes
1
akan Image.getScaledInstance (lebar, tinggi, petunjuk) juga lakukan?
Codeplay
1
Apakah preserveAlpha mengecek jalan yang salah (untuk imageType)?
Thilo
Saya setuju dengan @morgancodes. Kualitas gambar jauh lebih buruk daripada yang Anda dapatkan misalnya Pratinjau OS X ketika mengubah ukuran ke dimensi yang sama. Akan mencoba beberapa pustaka sumber terbuka untuk melihat apakah pustaka mereka lebih baik.
Thilo
1
"Akan mencoba beberapa pustaka sumber terbuka untuk melihat apakah pustaka mereka lebih baik." +1 untuk imgscalr dari jawaban @ RiyadKalla.
Thilo
182

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).

Riyad Kalla
sumber
1
Riyad, saya suka menggunakan Scalr. Saya ingin tahu, bagaimana Anda akhirnya memilih API dengan semua metode statis? Saya telah menulis api serupa yang lebih dekat ke pembangun. Seperti new ImageScaler(img).resizeTo(...).rotate(...).cropTo(...).toOutputBuffer(). Saya juga menyukai cara Anda dan saya pikir ini lebih sederhana.
Amir Raminfar
4
Amir, pola pembangun bekerja sangat baik untuk jenis perpustakaan ini juga, saya kebetulan pergi dengan pendekatan metode statis karena saya pikir itu adalah rambut yang lebih mudah diikuti untuk pengguna baru dan pola penggunaan yang saya harapkan dari imgscalr (awalnya hanya metode pengubahan ukuran tunggal) yang tidak mendapat manfaat dari memiliki status holding instance (Instan pembuat) Jadi saya menyimpan objek instantiation dan pergi dengan metode statis. Saya telah mengambil sikap yang kuat terhadap penciptaan objek di dalam imgscalr di setiap tempat yang bisa saya hindari. Kedua pendekatan tersebut bekerja dengan baik.
Riyad Kalla
5
+1 untuk menjadikan ini tersedia di repositori Maven pusat!
Grilse
Apa kelas BufferedImage ini, Mengapa studio android tidak menemukannya? @Riyad Kalla
Milad
3
@ xe4me BufferedImage adalah kelas di J2SE JDK (bagian dari kerangka Java2D) yang digunakan untuk mewakili data piksel mentah dan tidak terkompresi. Ini tidak tersedia di Android, Android menyediakan kelasnya sendiri untuk bekerja dengan data gambar.
Riyad Kalla
54

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:

  1. ambil gambar dalam direktori dan,
  2. ubah ukurannya menjadi 100 x 100, dengan rasio aspek gambar asli,
  3. simpan semuanya ke JPEG dengan pengaturan kualitas 0.85,
  4. di mana nama file diambil dari aslinya dengan thumbnail.ditambahkan ke awal

Diterjemahkan 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.

coobird
sumber
1
coobird, pekerjaan yang sangat bagus dengan API. Sangat lurus ke depan dan mudah digunakan.
Riyad Kalla
@ LordT: Saya senang Anda menemukan Thumbnailator mudah digunakan :)
coobird
Bagaimana saya bisa membuat thumbnail 80x80 dengan gambar asli 500x400? Saya tidak melihat opsi untuk itu. Terima kasih!
terry
".outputFormat (" JPEG ")" tidak ditulis di mana pun dalam dokumentasi.
Vincent Cantin
@Vincent Daftar lengkap metode yang dapat digunakan adalah dalam Dokumentasi Thumbnailator API - thumbnailator.googlecode.com/hg/javadoc/net/coobird/…
coobird
12

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 .

David Koelle
sumber
7
Artikel Chris adalah yang memotivasi saya untuk menulis imgscalr sejak awal; dan pertanyaan seperti ini (dan jawaban seperti milik Anda). Banyak orang bertanya berulang kali bagaimana mendapatkan thumbnail yang terlihat bagus dari sebuah gambar. Ada sejumlah cara untuk melakukannya, cara Chris tidak selalu merupakan cara terbaik, tergantung pada apa yang Anda coba lakukan dan seberapa besar pengurangannya. alamat imgscalr semua itu dan itu 1 kelas.
Riyad Kalla
2
+1, saya setuju, klien Kaya Kotor adalah salah satu buku java terbaik di luar sana yang setara dengan "java Efektif", Tapi ImgScalr adalah apa yang saya gunakan karena saya malas.
Shawn Vader
9

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.

Joel Carranza
sumber
4

Jika, memasang imagemagick pada maschine Anda adalah opsi, saya sarankan im4java . Ini adalah lapisan abstraksi yang sangat tipis pada antarmuka baris perintah, tetapi melakukan tugasnya dengan sangat baik.

naltatis
sumber
3

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);
Ruju
sumber
Ini juga tersedia di GitHub ( github.com/mortennobel/java-image-scaling.git ) dan memiliki versi 8.7 seperti untuk saat ini. Itu perlu diperbaiki di pom.xml, kau (mengubah sumber dan target menjadi setidaknya 1,6 karena Maven yang lebih baru tidak mendukung 1,5 lagi).
Cromax
2

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:

  • GM digunakan untuk memproses miliaran file di situs foto terbesar di dunia (misalnya Flickr dan Etsy).
kajo
sumber
1

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.

http://www.jmagick.org/index.html

Jice
sumber
1

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.

The One True Colter
sumber
1

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.

aanno
sumber
0

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

Rohit Tiwari
sumber
1
Harap sebutkan dalam jawaban jika Anda berafiliasi dengan produk yang Anda rekomendasikan.
Hans Olsson
waw ... apakah itu untuk mengubah ukuran gambar Animasi GIF? dan gratis ?? Wwaww ... saya harus mencobanya sekarang ...
gumuruh
Ya ini dikembangkan oleh saya. Ini adalah kode sumbernya github.com/rt29/jgifcode - Ini sekarang di sini. Saya tidak mendukungnya lagi.
Rohit Tiwari 3-15
0

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;
        }
    }
shareef
sumber
0

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);
Fridjato Part Fridjat
sumber