2012-04-19 16 views
10

Hola Tengo una instancia de BufferedImage en la memoria y quiero convertirla en byte [] para codificar como serie base64 sin operación de E/S para la consideración del rendimiento. Yo estaba usando la siguiente API:Convertir imagen Buffered en byte [] sin I/O

ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
ImageIO.write(image,"png",baos); 
return baos.toByteArray(); 

Sin embargo, esta API todavía escribe implícitamente la imagen en el directorio OS temperatura, lo que dará lugar a un fallo en el caso de que el directorio OS temp subyacente es completa y el archivo temporal no puede ser creado. Seguimiento de la pila:

Caused by: java.io.IOException: No space left on device 
    at java.io.RandomAccessFile.write(RandomAccessFile.java:493) 
    at javax.imageio.stream.FileCacheImageOutputStream.write(FileCacheImageOutputStream.java:134) 
    at javax.imageio.stream.ImageOutputStreamImpl.write(ImageOutputStreamImpl.java:66) 
    at com.sun.imageio.plugins.png.PNGImageWriter.write_magic(PNGImageWriter.java:376) 
    at com.sun.imageio.plugins.png.PNGImageWriter.write(PNGImageWriter.java:1115) 
    at javax.imageio.ImageWriter.write(ImageWriter.java:628) 
    at javax.imageio.ImageIO.write(ImageIO.java:1480) 
    at javax.imageio.ImageIO.write(ImageIO.java:1554) 

¿Hay una (como la conversión en memoria o eficiente de E/S) de manera eficiente para hacer la conversión sin E/S? Por favor avise.

+3

soy .. .se sorprendió de que esto sucediera. –

+0

Esto es casi seguro un error en la JVM. ¿Has probado la última versión? –

+0

@PeterLawrey: ¿por qué consideras esto un error? Hay toda una clase ['FileCacheImageOutputStream'] (http://docs.oracle.com/javase/7/docs/api/javax/imageio/stream/FileCacheImageOutputStream.html). Sin embargo, no estaba al tanto de este mecanismo en 'ImageIO' en absoluto. –

Respuesta

11

Desactivar la caché ImageIO a través de la ImageIO.setUseCache() método:

ImageIO.setUseCache(false); 

Es activado por defecto de acuerdo con el javadoc:

establece un indicador que indica si un archivo de caché basada en disco se debe utilizar al crear ImageInputStreams e ImageOutputStreams.

Al leer un InputStream> estándar, puede ser necesario guardar información previamente leída en un caché ya que el flujo subyacente no permite volver a leer los datos. De manera similar, al escribir en un OutputStream estándar, se puede usar un caché para permitir que se modifique un valor previamente escrito antes de enjuagarlo hasta el destino final.

La memoria caché puede residir en la memoria principal o en el disco. Establecer este indicador en falso no permite el uso de disco para futuras transmisiones, lo que puede ser una ventaja cuando se trabaja con imágenes pequeñas, ya que se elimina la sobrecarga de crear y destruir archivos.

Al inicio, el valor se establece en verdadero.

3

ImageIO por defecto escribe su caché en el disco incluso cuando solo utiliza secuencias. Pruebe a desactivar la caché con:

ImageIO.setUseCache(false); 
1

((DataBufferByte)img.getRaster().getDataBuffer()).getData() vuelve automáticamente una matriz de bytes si la imagen estaba en un formato de bytes. No hay necesidad de ningún IO en absoluto.

2

Ambas menciones de ImageIO.setUseCache(false) es correcta. Sin embargo, si usted no quiere inhabilitar el almacenamiento en caché de disco para ImageIO a nivel mundial, es una alternativa para envolver de manera explícita la corriente en un MemoryCacheImageOutputStream (que hace el almacenamiento en caché en memoria en lugar de almacenamiento en caché de disco):

ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
ImageOutputStream stream = new MemoryCacheImageOutputStream(baos); 
ImageIO.write(image, "png", stream); 
stream.close(); 
return baos.toByteArray(); 
+0

Parece que ya no es cierto, al menos en 1.8. 'com.sun.imageio.spi.OutputStreamImageOutputStreamSpi # createOutputStreamInstance' no comprueba el tipo de la secuencia pero sí marca el parámetro' useCache'. De todos modos, sería muy bueno tener una forma de desactivar el almacenamiento en caché localmente. – sedovav

+0

@sedovav La solución anterior proporciona de hecho una forma de desactivar "localmente" la memoria caché de disco. Cuando se crea el MemoryCacheImageOutputStream directamente así, nunca se golpea el Spi, por lo que lo que haga es irrelevante. PD: tenga en cuenta que ImageOutputSream no es una subclase de OutputStream, a pesar de su nombre. Y hay una sobrecarga separada de ImageIO.write para esto. – haraldK

+1

De hecho. ¡Muchas gracias! – sedovav