Tôi cần thay đổi kích thước các tệp PNG, JPEG và GIF. Làm thế nào tôi có thể làm điều này bằng cách sử dụng Java?
Tôi cần thay đổi kích thước các tệp PNG, JPEG và GIF. Làm thế nào tôi có thể làm điều này bằng cách sử dụng Java?
Câu trả lời:
Sau khi tải hình ảnh, bạn có thể thử:
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 Tôi vừa phát hành (Apache 2, được lưu trữ trên GitHub) một thư viện chia tỷ lệ hình ảnh đơn giản cho Java có tên là imgscalr (có sẵn trên trung tâm Maven ).
Thư viện triển khai một vài cách tiếp cận khác nhau để nhân rộng hình ảnh (bao gồm cả cách tiếp cận gia tăng của Chris Campbell với một vài cải tiến nhỏ) và sẽ chọn cách tiếp cận tối ưu nhất cho bạn nếu bạn hỏi nó, hoặc cho bạn cách nhìn nhanh nhất hoặc tốt nhất (nếu bạn yêu cầu điều đó).
Cách sử dụng rất đơn giản, chỉ là một loạt các phương thức tĩnh. Trường hợp sử dụng đơn giản nhất là:
BufferedImage scaledImage = Scalr.resize(myImage, 200);
Tất cả các thao tác đều duy trì tỷ lệ ban đầu của hình ảnh, vì vậy trong trường hợp này, bạn đang yêu cầu imgscalr thay đổi kích thước hình ảnh của bạn trong phạm vi rộng 200 pixel và cao 200 pixel và theo mặc định, nó sẽ tự động chọn cách tiếp cận nhanh nhất và đẹp nhất cho nó. 'được chỉ định.
Tôi nhận ra ngay từ đầu, nó trông giống như tự quảng cáo (nhưng nó), nhưng tôi đã dành thời gian chia sẻ công bằng chính xác chủ đề này và tiếp tục đưa ra các kết quả / cách tiếp cận / suy nghĩ / đề xuất khác nhau và quyết định ngồi xuống và viết triển khai đơn giản sẽ giải quyết 80-85% trường hợp sử dụng mà bạn có hình ảnh và có thể muốn có hình thu nhỏ cho nó - nhanh nhất có thể hoặc đẹp nhất có thể (đối với những người đã thử, bạn sẽ nhận thấy thực hiện Graphics.drawImage ngay cả với phép nội suy BICUBIC thành một hình ảnh đủ nhỏ, nó vẫn trông giống như rác).
new ImageScaler(img).resizeTo(...).rotate(...).cropTo(...).toOutputBuffer()
. Tôi cũng thích cách của bạn và tôi nghĩ nó đơn giản hơn.
Thumbnailator là một thư viện thay đổi kích thước hình ảnh nguồn mở cho Java với giao diện lưu loát, được phân phối theo giấy phép MIT.
Tôi đã viết thư viện này bởi vì việc tạo các hình thu nhỏ chất lượng cao trong Java có thể khó khăn một cách đáng ngạc nhiên và mã kết quả có thể khá lộn xộn. Với Thumbnailator, có thể thể hiện các tác vụ khá phức tạp bằng cách sử dụng API trôi chảy đơn giản.
Một ví dụ đơn giản
Ví dụ đơn giản, lấy một hình ảnh và thay đổi kích thước của nó thành 100 x 100 (giữ nguyên tỷ lệ khung hình của ảnh gốc) và lưu nó vào một tệp có thể đạt được trong một câu lệnh:
Thumbnails.of("path/to/image")
.size(100, 100)
.toFile("path/to/thumbnail");
Một ví dụ nâng cao
Thực hiện các tác vụ thay đổi kích thước phức tạp được đơn giản hóa với giao diện lưu loát của Thumbnailator.
Giả sử chúng ta muốn làm như sau:
0.85
,thumbnail.
gắn vào đầuĐược dịch sang Thumbnailator, chúng tôi có thể thực hiện những điều trên với những điều sau:
Thumbnails.of(new File("path/to/directory").listFiles())
.size(100, 100)
.outputFormat("JPEG")
.outputQuality(0.85)
.toFiles(Rename.PREFIX_DOT_THUMBNAIL);
Một lưu ý về chất lượng và tốc độ hình ảnh
Thư viện này cũng sử dụng phương pháp chia tỷ lệ lũy tiến lũy tiến được tô sáng trong Filthy Rich Client của Chet Haase và Romain Guy để tạo hình thu nhỏ chất lượng cao trong khi vẫn đảm bảo hiệu suất thời gian chạy chấp nhận được.
Bạn không cần một thư viện để làm điều này. Bạn có thể làm điều đó với chính Java.
Chris Campbell có một bài viết tuyệt vời và chi tiết về tỷ lệ hình ảnh - xem bài viết này .
Chet Haase và Romain Guy cũng có một bài viết chi tiết và rất nhiều thông tin về nhân rộng hình ảnh trong cuốn sách của họ, Khách hàng giàu có bẩn thỉu .
Java Advanced Imaging hiện là nguồn mở và cung cấp các hoạt động bạn cần.
Nếu bạn đang xử lý các hình ảnh lớn hoặc muốn có một kết quả đẹp mắt thì đó không phải là một nhiệm vụ tầm thường trong java. Chỉ cần thực hiện thông qua opcale op thông qua Graphics2D sẽ không tạo ra hình thu nhỏ chất lượng cao. Bạn có thể làm điều đó bằng cách sử dụng JAI, nhưng nó đòi hỏi nhiều công việc hơn bạn tưởng để có được thứ gì đó có vẻ tốt và JAI có thói quen khó chịu khi thổi JVM của chúng tôi với các lỗi OutOfMemory.
Tôi đề nghị sử dụng ImageMagick như một tệp thực thi bên ngoài nếu bạn có thể thoát khỏi nó. Nó đơn giản để sử dụng và nó thực hiện đúng công việc mà bạn không phải làm.
Nếu, có cài đặt hình ảnh trên maschine của bạn là một tùy chọn, tôi khuyên dùng im4java . Nó là một lớp trừu tượng rất mỏng trên giao diện dòng lệnh, nhưng thực hiện công việc của nó rất tốt.
API Java không cung cấp tính năng chia tỷ lệ chuẩn cho hình ảnh và hạ thấp chất lượng hình ảnh.
Vì điều này tôi đã cố gắng sử dụng cvResize từ JavaCV nhưng dường như nó gây ra sự cố.
Tôi đã tìm thấy một thư viện tốt để chia tỷ lệ hình ảnh: chỉ cần thêm phụ thuộc cho "java-image-scaleing" trong tệp pom.xml của bạn.
<dependency>
<groupId>com.mortennobel</groupId>
<artifactId>java-image-scaling</artifactId>
<version>0.8.6</version>
</dependency>
Trong kho lưu trữ maven, bạn sẽ nhận được phiên bản gần đây cho việc này.
Ví dụ. Trong chương trình java của bạn
ResampleOp resamOp = new ResampleOp(50, 40);
BufferedImage modifiedImage = resamOp.filter(originalBufferedImage, null);
Bạn có thể thử sử dụng Hệ thống xử lý ảnh GraphicsMagick với im4java làm giao diện comand-line cho Java.
Có rất nhiều lợi thế của GraphicsMagick, nhưng một ưu điểm cho tất cả:
Hình ảnh Magick đã được đề cập. Có một dự án kết thúc trước JNI được gọi là JMagick. Đây không phải là một dự án đặc biệt ổn định (và Image Magick đã được biết là thay đổi rất nhiều và thậm chí phá vỡ tính tương thích). Điều đó nói rằng, chúng tôi đã có kinh nghiệm tốt khi sử dụng JMagick và một phiên bản tương thích của Image Magick trong môi trường sản xuất để thực hiện mở rộng ở tốc độ cao, tốc độ trễ thấp. Tốc độ tốt hơn đáng kể sau đó với một thư viện đồ họa Java mà chúng tôi đã thử trước đây.
Chỉ cần sử dụng câu trả lời của Burkhard nhưng thêm dòng này sau khi tạo đồ họa:
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
Bạn cũng có thể đặt giá trị thành BICUBIC, nó sẽ tạo ra hình ảnh chất lượng tốt hơn nhưng là một hoạt động đắt tiền hơn. Có những gợi ý kết xuất khác mà bạn có thể đặt nhưng tôi đã thấy rằng phép nội suy tạo ra hiệu ứng đáng chú ý nhất. Hãy ghi nhớ nếu bạn muốn phóng to nhiều, mã java rất có thể sẽ rất chậm. Tôi thấy hình ảnh lớn hơn bắt đầu tạo ra độ trễ khoảng 300% thu phóng ngay cả với tất cả các gợi ý kết xuất được đặt để tối ưu hóa cho tốc độ trên chất lượng.
Bạn có thể sử dụng Marvin (khung xử lý ảnh thuần Java) cho loại hoạt động này: http://marvinproject.sourceforge.net
Trình cắm tỷ lệ: http://marvinproject.sourceforge.net/en/plugins/scale.html
Nó chỉ ra rằng viết một bộ thu nhỏ hiệu suất không phải là nhỏ. Tôi đã làm điều đó một lần cho một dự án nguồn mở: ImageScaler .
Về nguyên tắc 'java.awt.Image # getScaledInstance (int, int, int)' cũng sẽ thực hiện công việc này, nhưng có một lỗi khó chịu với điều này - hãy tham khảo liên kết của tôi để biết chi tiết.
Tôi đã phát triển một giải pháp với các lớp có sẵn miễn phí (AnimatedGifEncoder, GifDecoder và LWZEncoder) có sẵn để xử lý GIF Animation.
Bạn có thể tải xuống jgifcode jar và chạy lớp GifImageUtil. Liên kết: http://www.jgifcode.com
bạn có thể sử dụng sản phẩm phổ biến sau: hình thu nhỏ
Nếu bạn không muốn nhập imgScalr như @Riyad Kalla trả lời ở trên mà tôi đã kiểm tra quá hoạt động tốt, bạn có thể thực hiện việc này từ Peter Walser trả lời @Peter Walser về một vấn đề khác:
/**
* 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;
}
}
Hãy thử phương pháp folowing này:
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);