繁体   English   中英

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

[英]Serializing and De-Serializing android.graphics.Bitmap in Java

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

无论如何,我已经确保需要写入文件的类是“可序列化的”,但由于 android.graphics.Bitmap 不可序列化这一事实而遇到了一些障碍。 以下代码实质上将 Bitmap 作为 PNG 输出到 ByteArray 中,并应将其作为“readObject”的一部分读回。 但是,当代码运行时——我可以验证读入的“imageByteArrayLength”变量与 output 的变量相同——但“位图图像”始终为 null。

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

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);
    }
}   

花了一段时间,但我找到了一个干净的解决方案来解决这个问题。 我制作了一个自定义 object (BitmapDataObject),它实现了 Serializable 并有一个 byte[] 来存储来自原始 Bitmap 的 PNG 数据。 使用它,数据被正确存储在 ObjectOutputStream / ObjectInputStream - 这有效地允许序列化和反序列化 Bitmap object 通过将其作为 PNG 存储在一个字节 [] 在自定义 ZA8CFDE6331BD59EB2AC966F9668 下面的代码解决了我的查询。

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);
}

这是一个可以包装位图的可序列化 object 示例。

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);

    }

    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);

    }
}

只需使用此代码制作 class BitmapDataObject。 使用 getter 和 setter 在 Bitmap 和 BitmapDataObject 类之间切换。

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;

public class BitmapDataObject implements Serializable {

    private Bitmap currentImage;

    public Bitmap getCurrentImage() {
        return currentImage;
    }

    public void setCurrentImage(Bitmap currentImage) {
        this.currentImage = 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);
    }

    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);
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM