TwelveMonkeys ImageIO menyediakan dukungan format file gambar yang diperluas untuk platform Java, melalui plugin untuk paket javax.imageio.*
.
Tujuan utama dari proyek ini adalah untuk memberikan dukungan untuk format file yang tidak tercakup oleh JDK. Dukungan terhadap format ini penting, untuk dapat membaca data yang ditemukan "di alam liar", serta untuk mempertahankan akses ke data dalam format lama. Karena terdapat banyak data lama di luar sana, kami melihat perlunya implementasi pembaca terbuka untuk format populer.
Pengaya | Format | Keterangan | R | W | Metadata | Catatan |
---|---|---|---|---|---|---|
Batik | SVG | Grafik Vektor yang Dapat Diskalakan | ✔ | - | - | Membutuhkan Batik |
WMF | Metafile MS Windows | ✔ | - | - | Membutuhkan Batik | |
BMP | BMP | Bitmap Independen Perangkat MS Windows dan IBM OS/2 | ✔ | ✔ | Asli, Standar | |
BAJINGAN | Format Kursor MS Windows | ✔ | - | - | ||
ICO | Format Ikon MS Windows | ✔ | ✔ | - | ||
DDS | DDS | Format Permukaan Gambar Langsung MS | ✔ | - | Standar | |
HDR | HDR | Format RGBE Rentang Dinamis Tinggi Radiance | ✔ | - | Standar | |
ICNS | ICNS | Gambar Ikon Apple | ✔ | ✔ | - | |
JIKA | JIKA | Komodor Amiga/Format File Pertukaran Seni Elektronik | ✔ | ✔ | Standar | |
jpeg | jpeg | Kelompok Pakar Fotografer Gabungan | ✔ | ✔ | Asli, Standar | |
JPEG Tanpa Rugi | ✔ | - | Asli, Standar | |||
PCX | PCX | Format Kuas ZSoft | ✔ | - | Standar | |
DCX | Dokumen faks PCX multi-halaman | ✔ | - | Standar | ||
GAMBAR | GAMBAR | Format Gambar QuickTime Apple | ✔ | ✔ | Standar | |
PNTG | Format Gambar Apple MacPaint | ✔ | - | Standar | ||
PNM | PAM | NetPBM Portable Peta Apa Saja | ✔ | ✔ | Standar | |
PBM | Peta Bit Portabel NetPBM | ✔ | - | Standar | ||
PGM | Peta Abu-abu Portabel NetPBM | ✔ | - | Standar | ||
PPM | Peta Pix Portabel NetPBM | ✔ | ✔ | Standar | ||
PFM | Peta Apung Portabel | ✔ | - | Standar | ||
PSD | PSD | Dokumen Adobe Photoshop | ✔ | (#) | Asli, Standar | |
PSB | Dokumen Besar Adobe Photoshop | ✔ | - | Asli, Standar | ||
SGI | SGI | Format Gambar Grafik Silikon | ✔ | - | Standar | |
TGA | TGA | Format Gambar Truevision TGA | ✔ | ✔ | Standar | |
JempolDB | jempol.db | MS Windows Jempol DB | ✔ | - | - | Format berbasis Dokumen Gabungan OLE2 saja |
BERTENGKAR | BERTENGKAR | Format File Gambar Bertanda Aldus/Adobe | ✔ | ✔ | Asli, Standar | |
TIFF Besar | ✔ | ✔ | Asli, Standar | |||
WebP | WebP | Format WebP Google | ✔ | - | Standar | |
XWD | XWD | Format Pembuangan Jendela X11 | ✔ | - | Standar |
Catatan penting dalam menggunakan Batik: Harap baca The Apache™ XML Graphics Project - Keamanan, dan pastikan Anda menggunakan versi terbaru dan aman.
Perhatikan bahwa format GIF, PNG dan WBMP sudah didukung melalui ImageIO API, menggunakan plugin standar JDK. Untuk format BMP, JPEG, dan TIFF, plugin TwelveMonkeys menyediakan dukungan format tambahan dan fitur tambahan.
Seringkali, yang perlu Anda lakukan hanyalah memasukkan plugin ke dalam proyek Anda dan menulis:
BufferedImage image = ImageIO . read ( file );
Ini akan memuat gambar pertama dari file tersebut, seluruhnya ke dalam memori.
Bentuk penulisan dasar dan paling sederhana adalah:
if (! ImageIO . write ( image , format , file )) {
// Handle image not written case
}
Ini akan menulis seluruh gambar ke dalam satu file, menggunakan pengaturan default untuk format yang diberikan.
Plugin ditemukan secara otomatis pada saat run time. Lihat FAQ untuk informasi lebih lanjut tentang cara kerja mekanisme ini.
Jika Anda memerlukan lebih banyak kontrol terhadap parameter pembacaan dan proses membaca, idiom umum untuk membaca adalah seperti:
// Create input stream (in try-with-resource block to avoid leaks)
try ( ImageInputStream input = ImageIO . createImageInputStream ( file )) {
// Get the reader
Iterator < ImageReader > readers = ImageIO . getImageReaders ( input );
if (! readers . hasNext ()) {
throw new IllegalArgumentException ( "No reader for: " + file );
}
ImageReader reader = readers . next ();
try {
reader . setInput ( input );
// Optionally, listen for read warnings, progress, etc.
reader . addIIOReadWarningListener (...);
reader . addIIOReadProgressListener (...);
ImageReadParam param = reader . getDefaultReadParam ();
// Optionally, control read settings like sub sampling, source region or destination etc.
param . setSourceSubsampling (...);
param . setSourceRegion (...);
param . setDestination (...);
// ...
// Finally read the image, using settings from param
BufferedImage image = reader . read ( 0 , param );
// Optionally, read thumbnails, meta data, etc...
int numThumbs = reader . getNumThumbnails ( 0 );
// ...
}
finally {
// Dispose reader in finally block to avoid memory leaks
reader . dispose ();
}
}
Kueri pembaca untuk dimensi gambar sumber menggunakan reader.getWidth(n)
dan reader.getHeight(n)
tanpa membaca keseluruhan gambar ke dalam memori terlebih dahulu.
Dimungkinkan juga untuk membaca banyak gambar dari file yang sama dalam satu lingkaran, menggunakan reader.getNumImages()
.
Jika Anda memerlukan lebih banyak kontrol terhadap parameter penulisan dan proses penulisan, idiom umum untuk menulis adalah seperti:
// Get the writer
Iterator < ImageWriter > writers = ImageIO . getImageWritersByFormatName ( format );
if (! writers . hasNext ()) {
throw new IllegalArgumentException ( "No writer for: " + format );
}
ImageWriter writer = writers . next ();
try {
// Create output stream (in try-with-resource block to avoid leaks)
try ( ImageOutputStream output = ImageIO . createImageOutputStream ( file )) {
writer . setOutput ( output );
// Optionally, listen to progress, warnings, etc.
ImageWriteParam param = writer . getDefaultWriteParam ();
// Optionally, control format specific settings of param (requires casting), or
// control generic write settings like sub sampling, source region, output type etc.
// Optionally, provide thumbnails and image/stream metadata
writer . write (..., new IIOImage (..., image , ...), param );
}
}
finally {
// Dispose writer in finally block to avoid memory leaks
writer . dispose ();
}
Untuk penggunaan lebih lanjut, dan informasi tentang cara menggunakan ImageIO API, saya sarankan Anda membaca Panduan Java Image I/O API dari Oracle.
import com . twelvemonkeys . imageio . path . Paths ;
...
try ( ImageInputStream stream = ImageIO . createImageInputStream ( new File ( "image_with_path.jpg" )) {
BufferedImage image = Paths . readClipped ( stream );
// Do something with the clipped image...
}
Lihat dukungan Adobe Clipping Path di Wiki untuk detail lebih lanjut dan contoh kode.
Pustaka ini dilengkapi dengan operasi pengambilan sampel ulang (pengubahan ukuran gambar), yang berisi banyak algoritme berbeda untuk memberikan hasil luar biasa dengan kecepatan wajar.
import com . twelvemonkeys . image . ResampleOp ;
...
BufferedImage input = ...; // Image to resample
int width , height = ...; // new width/height
BufferedImageOp resampler = new ResampleOp ( width , height , ResampleOp . FILTER_LANCZOS ); // A good default filter, see class documentation for more info
BufferedImage output = resampler . filter ( input , null );
Pustaka dilengkapi dengan operasi dithering, yang dapat digunakan untuk mengonversi BufferedImage
menjadi IndexColorModel
menggunakan dither difusi kesalahan Floyd-Steinberg.
import com . twelvemonkeys . image . DiffusionDither ;
...
BufferedImage input = ...; // Image to dither
BufferedImageOp ditherer = new DiffusionDither ();
BufferedImage output = ditherer . filter ( input , null );
Saat menggunakan pola normal untuk memuat gambar, mencoba memuat gambar yang rusak akan mengakibatkan IOException
dilempar.
BufferedImage image = null ;
try {
image = ImageIO . read ( file );
} catch ( IOException exception ) {
// Handle, log a warning/error etc
}
Dalam skenario ini, jika gambar rusak, dan ImageIO.read
memunculkan pengecualian, image
tetap null
- fungsi tidak mungkin mengembalikan nilai dan memunculkan pengecualian.
Namun, dalam beberapa kasus, data gambar yang dapat digunakan dapat diperoleh dari gambar yang rusak. Cara melakukannya adalah menggunakan ImageReadParam
untuk menetapkan BufferedImage
sebagai tujuan.
int width = reader . getWidth ( 0 );
int height = reader . getHeight ( 0 );
ImageTypeSpecifier imageType = reader . getRawImageType ( 0 );
BufferedImage image = imageType . createBufferedImage ( width , height );
ImageReadParam param = reader . getDefaultReadParam ();
param . setDestination ( image );
try {
reader . read ( 0 , param );
}
catch ( IOException e ) {
// Handle, log a warning/error etc
}
Secara teori ini seharusnya berfungsi untuk semua plugin, tetapi hasilnya sangat spesifik untuk plugin/implementasi. Dengan beberapa format dan beberapa bentuk file rusak, Anda mungkin mendapatkan gambar yang sangat berguna. Namun, Anda harus bersiap menghadapi kemungkinan ini hanya memberikan gambar kosong atau kosong.
Unduh proyek (menggunakan Git):
$ git clone [email protected]:haraldk/TwelveMonkeys.git
Ini akan membuat folder bernama TwelveMonkeys
di direktori Anda saat ini. Ubah direktori ke folder TwelveMonkeys
, dan jalankan perintah di bawah ini untuk membangun.
Bangun proyek (menggunakan Maven):
$ mvn package
Saat ini JDK yang direkomendasikan untuk membuat build adalah Oracle JDK 8.x.
Dimungkinkan untuk membangun menggunakan OpenJDK, namun beberapa pengujian mungkin gagal karena beberapa perbedaan kecil antara sistem manajemen warna yang digunakan. Anda harus menonaktifkan pengujian yang dimaksud, atau membangun tanpa pengujian sama sekali.
Karena pengujian unit memerlukan cukup banyak memori untuk dijalankan, Anda mungkin harus mengatur variabel lingkungan MAVEN_OPTS
untuk memberikan lebih banyak memori pada proses Java yang menjalankan Maven. Saya menyarankan sesuatu seperti -Xmx512m -XX:MaxPermSize=256m
.
Secara opsional, Anda dapat menginstal proyek di repositori Maven lokal Anda menggunakan:
$ mvn install
Untuk menginstal plug-in, gunakan Maven dan tambahkan dependensi yang diperlukan ke proyek Anda, atau tambahkan JAR yang diperlukan secara manual bersama dengan dependensi yang diperlukan di jalur kelas.
Mekanisme pencarian registri dan layanan ImageIO akan memastikan plugin tersedia untuk digunakan.
Untuk memverifikasi bahwa plugin JPEG diinstal dan digunakan pada saat run-time, Anda dapat menggunakan kode berikut:
Iterator < ImageReader > readers = ImageIO . getImageReadersByFormatName ( "JPEG" );
while ( readers . hasNext ()) {
System . out . println ( "reader: " + readers . next ());
}
Baris pertama harus mencetak:
reader: com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReader@somehash
Untuk bergantung pada plugin JPEG dan TIFF menggunakan Maven, tambahkan yang berikut ini ke POM Anda:
...
< dependencies >
...
< dependency >
< groupId >com.twelvemonkeys.imageio</ groupId >
< artifactId >imageio-jpeg</ artifactId >
< version >3.12.0</ version >
</ dependency >
< dependency >
< groupId >com.twelvemonkeys.imageio</ groupId >
< artifactId >imageio-tiff</ artifactId >
< version >3.12.0</ version >
</ dependency >
<!--
Optional dependency. Needed only if you deploy ImageIO plugins as part of a web app.
Make sure you add the IIOProviderContextListener to your web.xml, see above.
-->
< dependency >
< groupId >com.twelvemonkeys.servlet</ groupId >
< artifactId >servlet</ artifactId >
< version >3.12.0</ version >
</ dependency >
<!--
Or Jakarta version, for Servlet API 5.0
-->
< dependency >
< groupId >com.twelvemonkeys.servlet</ groupId >
< artifactId >servlet</ artifactId >
< version >3.12.0</ version >
< classifier >jakarta</ classifier >
</ dependency >
</ dependencies >
Untuk bergantung pada plugin JPEG dan TIFF di IDE atau program Anda, tambahkan semua JAR berikut ke jalur kelas Anda:
twelvemonkeys-common-lang-3.12.0.jar
twelvemonkeys-common-io-3.12.0.jar
twelvemonkeys-common-image-3.12.0.jar
twelvemonkeys-imageio-core-3.12.0.jar
twelvemonkeys-imageio-metadata-3.12.0.jar
twelvemonkeys-imageio-jpeg-3.12.0.jar
twelvemonkeys-imageio-tiff-3.12.0.jar
Karena registri plugin ImageIO
( IIORegistry
) adalah "VM global", ia tidak berfungsi dengan baik dengan konteks servlet apa adanya. Hal ini terutama terlihat jika Anda memuat plugin dari folder WEB-INF/lib
atau classes
. Kecuali Anda menambahkan ImageIO.scanForPlugins()
di suatu tempat dalam kode Anda, plugin mungkin tidak akan pernah tersedia sama sekali.
Selain itu, konteks servlet secara dinamis memuat dan membongkar kelas (menggunakan pemuat kelas baru per konteks). Jika Anda memulai ulang aplikasi, kelas lama secara default akan tetap berada di memori selamanya (karena saat scanForPlugins
dipanggil lagi, ClassLoader
lainlah yang memindai/memuat kelas, dan dengan demikian kelas tersebut akan menjadi instance baru di registri). Jika pembacaan dicoba menggunakan salah satu pembaca "lama" yang tersisa, pengecualian aneh (seperti NullPointerException
saat mengakses bidang static final
atau NoClassDefFoundError
untuk kelas dalam yang tidak diinisialisasi) dapat terjadi.
Untuk mengatasi masalah penemuan dan kebocoran sumber daya, sangat disarankan untuk menggunakan IIOProviderContextListener
yang mengimplementasikan bongkar muat dinamis plugin ImageIO untuk aplikasi web.
< web-app ...>
...
< listener >
< display-name >ImageIO service provider loader/unloader</ display-name >
< listener-class >com.twelvemonkeys.servlet.image.IIOProviderContextListener</ listener-class >
</ listener >
...
</ web-app >
Memuat plugin dari WEB-INF/lib
tanpa memasang pendengar konteks tidak didukung dan tidak akan berfungsi dengan benar.
Pendengar konteks tidak memiliki ketergantungan pada plugin TwelveMonkeys ImageIO, dan juga dapat digunakan dengan JAI ImageIO atau plugin ImageIO lainnya.
Opsi aman lainnya adalah menempatkan file JAR di folder lib bersama atau umum server aplikasi.
Bagi mereka yang melakukan transisi dari paket javax.servlet
lama ke paket jakarta.servlet
baru, tersedia ketergantungan terpisah. Ini berisi kelas servlet yang sama persis seperti yang disebutkan di atas, tetapi dibangun berdasarkan paket Jakarta EE yang baru. Dependensi memiliki nama grup dan pengidentifikasi yang sama seperti sebelumnya, namun ditambahkan pengklasifikasi jakarta
, untuk membedakannya dari paket non-Jakarta.
Lihat contoh ketergantungan Maven untuk cara mengaktifkannya dengan Maven. Gradle atau alat pembangunan lainnya akan memiliki opsi serupa.
Cara yang disarankan untuk menggunakan plugin adalah dengan menyertakan JAR apa adanya dalam proyek Anda, melalui ketergantungan Maven atau serupa. Pengemasan ulang tidak perlu menggunakan perpustakaan, dan tidak disarankan.
Namun, jika Anda ingin membuat JAR yang "gemuk", atau ingin mengemas ulang JAR karena alasan tertentu, penting untuk diingat bahwa penemuan plugin secara otomatis oleh ImageIO bergantung pada mekanisme Antarmuka Penyedia Layanan (SPI). Singkatnya, setiap JAR berisi folder khusus, bernama META-INF/services
yang berisi satu atau lebih file, biasanya javax.imageio.spi.ImageReaderSpi
dan javax.imageio.spi.ImageWriterSpi
. File-file ini ada dengan nama yang sama di setiap JAR , jadi jika Anda hanya membongkar semuanya ke satu folder atau membuat JAR, file akan ditimpa dan perilakunya tidak ditentukan (kemungkinan besar Anda akan mendapatkan satu plugin yang diinstal).
Solusinya adalah memastikan semua file dengan nama yang sama, digabungkan menjadi satu file, yang berisi semua informasi SPI dari setiap jenis. Jika menggunakan plugin Maven Shade, Anda harus menggunakan ServicesResourceTransformer untuk menggabungkan file-file ini dengan benar. Anda mungkin juga ingin menggunakan ManifestResourceTransforme untuk mendapatkan nama vendor yang benar, info versi, dll. Bundel JAR "gemuk" lainnya mungkin memiliki mekanisme serupa untuk menggabungkan entri dengan nama yang sama.
Versi terbaru yang akan berjalan di Java 7 adalah 3.9.4. Versi yang lebih baru memerlukan Java 8 atau lebih baru.
Ketergantungan umum
Ketergantungan ImageIO
Plugin ImageIO
Plugin ImageIO membutuhkan lib pihak ketiga
Dukungan Jalur Photoshop untuk ImageIO
Dukungan servlet
Proyek ini disediakan di bawah lisensi BSD yang disetujui OSI:
Copyright (c) 2008-2022, Harald Kuhr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
o Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
o Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
o Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
T: Bagaimana cara menggunakannya?
a: Cara termudah adalah dengan membangun proyek Anda sendiri menggunakan Maven, Gradle, atau alat pembangunan lainnya dengan manajemen ketergantungan, dan cukup tambahkan dependensi ke plugin spesifik yang Anda perlukan. Jika Anda tidak menggunakan alat pembangunan seperti itu, pastikan Anda memiliki semua JAR yang diperlukan di classpath. Lihat bagian Instal di atas.
q: Perubahan apa yang harus saya lakukan pada kode saya agar dapat menggunakan plug-in?
a: Jawaban singkatnya adalah: Tidak ada. Untuk penggunaan dasar, seperti ImageIO.read(...)
atau ImageIO.getImageReaders(...)
, Anda tidak perlu mengubah kode. Sebagian besar fungsi tersedia melalui API ImageIO standar, dan sangat hati-hati untuk tidak memperkenalkan API tambahan jika tidak diperlukan.
Jika Anda ingin menggunakan fitur yang sangat spesifik/lanjutan dari beberapa format, Anda mungkin harus menggunakan API tertentu, seperti menyetel URL dasar untuk gambar SVG yang terdiri dari banyak file, atau mengontrol kompresi keluaran file TIFF.
T: Bagaimana cara kerjanya?
a: Proyek TwelveMonkeys ImageIO berisi plug-in untuk ImageIO. ImageIO menggunakan mekanisme pencarian layanan, untuk menemukan plug-in saat runtime.
Yang harus Anda lakukan adalah memastikan Anda memiliki ElevenMonkeys ImageIO JAR di classpath Anda.
Anda dapat membaca lebih lanjut tentang registri dan mekanisme pencarian di dokumen IIORegistry API.
Catatan kecilnya: Penyedia layanan TwelveMonkeys untuk JPEG, BMP dan TIFF, mengesampingkan metode onRegistration, dan menggunakan mekanisme pemesanan parsial berpasangan dari IIOServiceRegistry
untuk memastikannya diinstal sebelum Sun/Oracle menyediakan JPEGImageReader
, BMPImageReader
TIFFImageReader
, dan Apple disediakan TIFFImageReader
di OS X, masing-masing. Menggunakan pengurutan berpasangan tidak akan menghapus fungsionalitas apa pun dari implementasi ini, namun dalam sebagian besar kasus, Anda akan menggunakan plug-in TwelveMonkeys sebagai gantinya.
q: Mengapa tidak ada dukungan untuk format umum seperti GIF atau PNG?
a: Jawaban singkatnya adalah dukungan bawaan di ImageIO untuk format ini dianggap cukup baik. Jika Anda mencari kinerja penulisan PNG yang lebih baik di Java 7 dan 8, lihat JDK9 PNG Writer Backport.
q: Kapan rilis berikutnya? Apa jadwal rilis saat ini?
a: Tujuannya adalah untuk membuat rilis bulanan, yang berisi perbaikan bug dan fitur-fitur kecil baru. Dan rilis triwulanan dengan lebih banyak fitur "utama".
q: Saya suka proyek ini! Apa yang bisa saya bantu?
a: Lihat masalah yang masih terbuka, dan lihat apakah ada masalah yang dapat Anda bantu perbaiki, atau berikan file contoh atau buat kasus pengujian. Anda atau organisasi Anda juga dapat menjadi sponsor melalui GitHub Sponsors. Menyediakan dana akan memungkinkan kami menghabiskan lebih banyak waktu untuk memperbaiki bug dan mengimplementasikan fitur-fitur baru.
T: Bagaimana dengan JAI? Beberapa format sudah didukung oleh JAI.
a: Meskipun JAI (dan khususnya jai-imageio) mendukung beberapa format yang sama, JAI memiliki beberapa masalah besar. Yang paling jelas adalah:
q: Bagaimana dengan JMagick atau IM4Java? Tidak bisakah Anda menggunakan apa yang sudah tersedia saja?
a: Meskipun perpustakaan hebat dengan beragam dukungan format, perpustakaan berbasis ImageMagick memiliki beberapa kelemahan dibandingkan dengan ImageIO.
Kami berhasil