2015-08-26 67 views
0

我有一個大的PNG圖像(600x600),我的應用程序使圖像不透明並寫出文件。問題是ImageIO的性能很糟糕。還有其他的選擇嗎?我需要圖像是不透明的。下面是我在做什麼:使用帶有alpha的PNG改進Java ImageIO讀取/寫入

BufferedImage buf = ImageIO.read(localUrl); 
    float[] scales = {1f, 1f, 1f, 1f}; // R, G, B, A 
    float[] offsets = {0f, 0f, 0f, 1f}; // R, G, B, A 
    RescaleOp rescaler = new RescaleOp(scales, offsets, null); 
    BufferedImage opaque = rescaler.filter(buf, null); 
    File outputfile = new File(localUrl.getPath()); 
    ImageIO.write(opaque, "png", outputfile); 
+0

不知道這是否會對您有所幫助。我有一個開源的Java圖像庫[這裏](https://github.com/dragon66/icafe),它可以讀取寫PNG w/o alpha。默認情況下,不使用Alpha通道編寫,您可以選擇速度的壓縮級別。 – dragon66

+0

你有沒有關於保存基於alpha和基於alpha的圖像的指標? – MadProgrammer

+2

因此,我在1600x1440的圖像上使用您的代碼進行了快速測試,加載時間爲0.280秒,重新採樣爲0.183秒,寫入時間爲0.784秒......我不確定我會打電話給那些可怕的... (和我的電腦負載〜75%的CPU使用率之前我跑了測試,所以是的,很多事情) – MadProgrammer

回答

3

使用RescaleOp也不是完全必要在這裏,如果你只是想擺脫的透明度。一個更簡單的解決辦法是在背景繪製的圖像,像這樣:

Color bgColor = Color.WHITE; 

BufferedImage foreground = ImageIO.read(localUrl); 
int width = foreground.getWidth(); 
int height = foreground.getHeight(); 
BufferedImage background = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 
Graphics2D g = background.createGraphics(); 
g.setColor(bgColor); 
g.fillRect(0, 0, width, height); 
g.drawImage(foreground, 0, 0, null); 
g.dispose(); 
File outputfile = new File(localUrl.getPath()); 
ImageIO.write(background, "png", outputfile); 

這似乎是做事情的一個簡單的方法,並會可能需要較少的處理能力,但我懷疑會有巨大的差異。如果您對速度不滿意,可以從硬盤讀取/寫入映像,但您無法做到加快速度。

0

隨着PNGJ

private static void removeAlpha(File file1,File file2) { 
    PngReaderByte reader = new PngReaderByte(file1); 
    ImageInfo info = reader.imgInfo; 
    PngWriter writer = new PngWriter(file2,info); 
    writer.setFilterPreserve(true); 
    writer.setCompLevel(6); 
    writer.copyChunksFrom(reader.getChunksList(), ChunkCopyBehaviour.COPY_ALL_SAFE); 
    if(info.bitDepth != 8 ||info.channels!=4) throw new RuntimeException("expected 8bits RGBA "); 
    while(reader.hasMoreRows()) { 
     ImageLineByte line = reader.readRowByte(); 
     byte [] buf = line.getScanlineByte(); 
     for(int i=0,j=3;i<info.cols;i++,j+=4) 
      buf[j]=(byte)255; 
     writer.writeRow(line); 
    } 
    reader.end(); 
    writer.end(); 
} 

我不知道這是否會提升更流暢。請記住,(與Parker Hoyes的答案相反),這只是簡單地殺死alpha通道,但它不會與某種背景顏色混合(因此「原始」顏色將出現在先前透明的現在不透明的區域中)。