在Java中序列化和反序列化android.graphics.Bitmap

我已经开始了我的第一个android应用程序的工作,并有一个应用程序的基础上处理多层图像。 我能够导出一个平面版本的项目文件作为PNG,但我希望能够保存分层的图像以供日后编辑(包括应用于某些图层,如基于文本的图层的任何选项)。

无论如何,我已经确保需要写入文件的类是“可序列化的”,但是由于android.graphics.Bitmap不可序列化的缘故,已经遇到了一些障碍。 下面的代码实际上是将位图作为一个PNG输出到一个ByteArray中,并且应该将其作为“readObject”的一部分进行读取。 但是,当代码运行时 – 我可以validation读入的“imageByteArrayLength”variables与输出的相同,但“位图图像”始终为空。

任何帮助将不胜感激。 谢谢阅读。

private String title; private int width; private int height; private Bitmap sourceImage; private Canvas sourceCanvas; private Bitmap currentImage; private Canvas currentCanvas; private Paint currentPaint; private void writeObject(ObjectOutputStream out) throws IOException{ out.writeObject(title); out.writeInt(width); out.writeInt(height); ByteArrayOutputStream stream = new ByteArrayOutputStream(); currentImage.compress(Bitmap.CompressFormat.PNG, 100, stream); byte[] imageByteArray = stream.toByteArray(); int length = imageByteArray.length; out.writeInt(length); out.write(imageByteArray); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{ this.title = (String)in.readObject(); this.width = in.readInt(); this.height = in.readInt(); int imageByteArrayLength = in.readInt(); byte[] imageByteArray = new byte[imageByteArrayLength]; in.read(imageByteArray, 0, imageByteArrayLength); BitmapFactory.Options opt = new BitmapFactory.Options(); opt.inPreferredConfig = Bitmap.Config.ARGB_8888; Bitmap image = BitmapFactory.decodeByteArray(imageByteArray, 0, imageByteArrayLength, opt); sourceImage = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); currentImage = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); sourceCanvas = new Canvas(sourceImage); currentCanvas = new Canvas(currentImage); currentPaint = new Paint(Paint.ANTI_ALIAS_FLAG); if ( image != null ) { sourceCanvas.drawBitmap(image, 0, 0, currentPaint); } } 

这花了一段时间,但我find了一个干净的解决scheme,这个问题。 我生成了一个实现Serializable的自定义对象(BitmapDataObject),并有一个byte []来存储原始位图的PNG数据。 使用这个,数据被正确地存储在ObjectOutputStream / ObjectInputStream中 – 这有效地允许将一个Bitmap对象序列化和反序列化,方法是将其作为一个PNG存储在一个自定义对象的byte []中。 下面的代码解决了我的查询。

 private String title; private int sourceWidth, currentWidth; private int sourceHeight, currentHeight; private Bitmap sourceImage; private Canvas sourceCanvas; private Bitmap currentImage; private Canvas currentCanvas; private Paint currentPaint; protected class BitmapDataObject implements Serializable { private static final long serialVersionUID = 111696345129311948L; public byte[] imageByteArray; } /** Included for serialization - write this layer to the output stream. */ private void writeObject(ObjectOutputStream out) throws IOException{ out.writeObject(title); out.writeInt(currentWidth); out.writeInt(currentHeight); ByteArrayOutputStream stream = new ByteArrayOutputStream(); currentImage.compress(Bitmap.CompressFormat.PNG, 100, stream); BitmapDataObject bitmapDataObject = new BitmapDataObject(); bitmapDataObject.imageByteArray = stream.toByteArray(); out.writeObject(bitmapDataObject); } /** Included for serialization - read this object from the supplied input stream. */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{ title = (String)in.readObject(); sourceWidth = currentWidth = in.readInt(); sourceHeight = currentHeight = in.readInt(); BitmapDataObject bitmapDataObject = (BitmapDataObject)in.readObject(); Bitmap image = BitmapFactory.decodeByteArray(bitmapDataObject.imageByteArray, 0, bitmapDataObject.imageByteArray.length); sourceImage = Bitmap.createBitmap(sourceWidth, sourceHeight, Bitmap.Config.ARGB_8888); currentImage = Bitmap.createBitmap(sourceWidth, sourceHeight, Bitmap.Config.ARGB_8888); sourceCanvas = new Canvas(sourceImage); currentCanvas = new Canvas(currentImage); currentPaint = new Paint(Paint.ANTI_ALIAS_FLAG); thumbnailPaint = new Paint(Paint.ANTI_ALIAS_FLAG); thumbnailPaint.setARGB(255, 200, 200, 200); thumbnailPaint.setStyle(Paint.Style.FILL); } 

这是一个可以封装位图的可序列化对象的例子。

 public class BitmapDataObject implements Serializable { private Bitmap currentImage; public BitmapDataObject(Bitmap bitmap) { currentImage = bitmap; } private void writeObject(java.io.ObjectOutputStream out) throws IOException { ByteArrayOutputStream stream = new ByteArrayOutputStream(); currentImage.compress(Bitmap.CompressFormat.PNG, 100, stream); byte[] byteArray = stream.toByteArray(); out.writeInt(byteArray.length); out.write(byteArray); currentImage = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length); } private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { int bufferLength = in.readInt(); byte[] byteArray = new byte[bufferLength]; int pos = 0; do { int read = in.read(byteArray, pos, bufferLength - pos); if (read != -1) { pos += read; } else { break; } } while (pos < bufferLength); currentImage = BitmapFactory.decodeByteArray(byteArray, 0, bufferLength); } }