2013-08-29 42 views
7
  1. Cách nhanh nhất để đọc hình ảnh từ một tệp vào BufferedImage trong Java/Grails là gì?
  2. Cách nhanh nhất để ghi hình ảnh từ BufferedImage vào một tệp trong Java/Grails là gì?

biến thể của tôi (đọc):Cách nhanh nhất để đọc/ghi hình ảnh từ một tệp vào BufferedImage?

byte [] imageByteArray = new File(basePath+imageSource).readBytes() 
InputStream inStream = new ByteArrayInputStream(imageByteArray) 
BufferedImage bufferedImage = ImageIO.read(inStream) 

tôi biến thể (ghi):

BufferedImage bufferedImage = // some image 
def fullPath = // image page + file name 
byte [] currentImage 

try{ 

    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    ImageIO.write(bufferedImage, "jpg", baos); 
    baos.flush(); 
    currentImage = baos.toByteArray(); 
    baos.close(); 

    }catch(IOException e){ 
     System.out.println(e.getMessage()); 
    }  
    }  


def newFile = new FileOutputStream(fullPath) 
newFile.write(currentImage) 
newFile.close() 

Trả lời

6

Giải pháp đọc của bạn về cơ bản là đọc các byte hai lần, một lần từ tệp và một lần từ ByteArrayInputStream. Đừng làm điều đó

Với Java 7 để đọc

BufferedImage bufferedImage = ImageIO.read(Files.newInputStream(Paths.get(basePath + imageSource))); 

Với Java 7 để viết

ImageIO.write(bufferedImage, "jpg", Files.newOutputStream(Paths.get(fullPath))); 

Các cuộc gọi đến Files.newInputStream sẽ trả về một ChannelInputStream mà (AFAIK) không được đệm. Bạn sẽ muốn quấn nó

new BufferedInputStream(Files.newInputStream(...)); 

Vì vậy, có ít cuộc gọi IO đến đĩa hơn, tùy thuộc vào cách bạn sử dụng nó.

+0

Tôi đọc rằng Bộ công cụ Java rất nhanh để đọc không đúng? Bạn có thể sửa đổi câu trả lời của bạn nếu điều này là đúng? –

+0

@ stephan1001 Tôi xin lỗi, tôi không quen với các gói liên quan đến giao diện người dùng. –

+0

Gói đầy đủ của Tệp và Đường dẫn là gì? –

0

Bạn đang gần như tốt cho văn bản. Chỉ cần không sử dụng ByteArrayOutputStream trung gian. Đó là một nút cổ chai khổng lồ trong mã của bạn. Thay vào đó gói FileOutputStream trong BufferedOutputStream và làm tương tự.

Tương tự như vậy đối với việc đọc của bạn. Loại bỏ Itermediate ByteArrayInputStream.

5

Tôi muộn để đảng, nhưng dù sao ...

Trên thực tế, sử dụng:

ImageIO.read(new File(basePath + imageSource)); 

ImageIO.write(bufferedImage, "jpeg", new File(fullPath)); 

... có thể chứng minh nhanh hơn (thử nó, sử dụng một hồ sơ, để đảm bảo).

Điều này là do những biến thể sử dụng RandomAccessFile -backed ImageInputStream/ImageOutputStream hiện thực đằng sau hậu trường, trong khi InputStream/OutputStream phiên bản dựa trên sẽ theo mặc định sử dụng một đĩa hậu thuẫn seekable suối thực hiện. Việc sao lưu đĩa liên quan đến việc viết toàn bộ nội dung của luồng vào một tệp tạm thời và có thể đọc lại từ nó (điều này là vì hình ảnh I/O thường được hưởng lợi từ truy cập dữ liệu phi tuyến tính).

Nếu bạn muốn tránh thêm I/O với các phiên bản dòng dựa, với chi phí của việc sử dụng bộ nhớ nhiều hơn, người ta có thể gọi là mơ hồ có tên ImageIO.setUseCache(false), để vô hiệu hóa đĩa bộ nhớ đệm của đầu vào seekable suối. Điều này rõ ràng không phải là một ý tưởng tốt nếu bạn đang đối phó với những hình ảnh rất lớn.

+0

Vì vậy, phiên bản này ImageIO.read (tệp mới (basePath + imageSource)); nhanh hơn so với ImageIO.read (BufferedInputStream mới (Files.newInputStream (Paths.get (basePath + imageSource)))); điều này có đúng không? –

+1

@ stephan1001 Theo lý thuyết, có (giả sử thiết lập mặc định cho 'useCahce'' false'). Nhưng như tôi đã nói, hãy đo lường để chắc chắn. :-) – haraldK

+1

Chỉ cần cho heck của nó, tôi đã viết một chương trình mẫu, mà đọc một kích thước trung bình JPEG 100 lần bằng cách sử dụng phiên bản tập tin, phiên bản dòng và phiên bản dòng mà không có bộ nhớ cache đĩa. Thời gian là thời gian trung bình. thời gian sử dụng tệp: 36.76ms thời gian sử dụng luồng: 40.32ms thời gian sử dụng luồng (useCache == false): 37.63ms JDK 1.6.0_26-b03-383 trên OS X, 2.66GHz i7 + SSD. Milage của bạn có thể thay đổi ... – haraldK

Các vấn đề liên quan