blob: 821c9a50c13fdc54d7865cd1c80336628fa1954e [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package io.flutter.plugins.camera;
import android.media.Image;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
/** Saves a JPEG {@link Image} into the specified {@link File}. */
public class ImageSaver implements Runnable {
/** The JPEG image */
private final Image image;
/** The file we save the image into. */
private final File file;
/** Used to report the status of the save action. */
private final Callback callback;
/**
* Creates an instance of the ImageSaver runnable
*
* @param image - The image to save
* @param file - The file to save the image to
* @param callback - The callback that is run on completion, or when an error is encountered.
*/
ImageSaver(@NonNull Image image, @NonNull File file, @NonNull Callback callback) {
this.image = image;
this.file = file;
this.callback = callback;
}
@Override
public void run() {
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
FileOutputStream output = null;
try {
output = FileOutputStreamFactory.create(file);
output.write(bytes);
callback.onComplete(file.getAbsolutePath());
} catch (IOException e) {
callback.onError("IOError", "Failed saving image");
} finally {
image.close();
if (null != output) {
try {
output.close();
} catch (IOException e) {
callback.onError("cameraAccess", e.getMessage());
}
}
}
}
/**
* The interface for the callback that is passed to ImageSaver, for detecting completion or
* failure of the image saving task.
*/
public interface Callback {
/**
* Called when the image file has been saved successfully.
*
* @param absolutePath - The absolute path of the file that was saved.
*/
void onComplete(String absolutePath);
/**
* Called when an error is encountered while saving the image file.
*
* @param errorCode - The error code.
* @param errorMessage - The human readable error message.
*/
void onError(String errorCode, String errorMessage);
}
/** Factory class that assists in creating a {@link FileOutputStream} instance. */
static class FileOutputStreamFactory {
/**
* Creates a new instance of the {@link FileOutputStream} class.
*
* <p>This method is visible for testing purposes only and should never be used outside this *
* class.
*
* @param file - The file to create the output stream for
* @return new instance of the {@link FileOutputStream} class.
* @throws FileNotFoundException when the supplied file could not be found.
*/
@VisibleForTesting
public static FileOutputStream create(File file) throws FileNotFoundException {
return new FileOutputStream(file);
}
}
}