Add toFile utility in CameraUtils and in PictureResult

v2
Mattia Iavarone 6 years ago
parent 147f175ba8
commit fcf41c8d2c
  1. 2
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraListener.java
  2. 21
      cameraview/src/main/java/com/otaliastudios/cameraview/PictureResult.java
  3. 63
      cameraview/src/main/utils/com/otaliastudios/cameraview/CameraUtils.java
  4. 25
      cameraview/src/main/utils/com/otaliastudios/cameraview/FileCallback.java
  5. 2
      demo/src/main/java/com/otaliastudios/cameraview/demo/PicturePreviewActivity.java
  6. 14
      docs/_posts/2018-12-20-getting-started.md
  7. 2
      docs/_posts/2018-12-20-v1-migration-guide.md

@ -48,7 +48,7 @@ public abstract class CameraListener {
* Notifies that a picture previously captured with {@link CameraView#takePicture()}
* or {@link CameraView#takePictureSnapshot()} is ready to be shown or saved to file.
*
* If planning to show a bitmap, you can use {@link PictureResult#asBitmap(int, int, BitmapCallback)}
* If planning to show a bitmap, you can use {@link PictureResult#toBitmap(int, int, BitmapCallback)}
* to decode the byte array taking care about orientation and threading.
*
* @param result captured picture

@ -1,6 +1,9 @@
package com.otaliastudios.cameraview;
import android.location.Location;
import java.io.File;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -93,7 +96,7 @@ public class PictureResult {
* @param maxHeight the max. height of final bitmap
* @param callback a callback to be notified of image decoding
*/
public void asBitmap(int maxWidth, int maxHeight, @NonNull BitmapCallback callback) {
public void toBitmap(int maxWidth, int maxHeight, @NonNull BitmapCallback callback) {
CameraUtils.decodeBitmap(getData(), maxWidth, maxHeight, rotation, callback);
}
@ -104,9 +107,19 @@ public class PictureResult {
*
* @param callback a callback to be notified of image decoding
*/
public void asBitmap(@NonNull BitmapCallback callback) {
asBitmap(-1, -1, callback);
public void toBitmap(@NonNull BitmapCallback callback) {
toBitmap(-1, -1, callback);
}
// TODO toFile
/**
* Shorthand for {@link CameraUtils#writeToFile(byte[], File, FileCallback)}.
* This writes this picture to file on a background thread and posts the result in the UI
* thread using the given callback.
*
* @param file the file to write into
* @param callback a callback
*/
public void toFile(@NonNull File file, @NonNull FileCallback callback) {
CameraUtils.writeToFile(getData(), file, callback);
}
}

@ -12,9 +12,14 @@ import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import androidx.exifinterface.media.ExifInterface;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Static utilities for dealing with camera I/O, orientations, etc.
@ -57,6 +62,59 @@ public class CameraUtils {
}
/**
* Simply writes the given data to the given file. It is done synchronously. If you are
* running on the UI thread, please use {@link #writeToFile(byte[], File, FileCallback)}
* and pass a file callback.
*
* If any error is encountered, this returns null.
*
* @param data the data to be written
* @param file the file to write into
* @return the source file, or null if error
*/
@SuppressWarnings("WeakerAccess")
@Nullable
@WorkerThread
public static File writeToFile(@NonNull final byte[] data, @NonNull File file) {
if (file.exists() && !file.delete()) return null;
try (OutputStream stream = new BufferedOutputStream(new FileOutputStream(file))) {
stream.write(data);
stream.flush();
return file;
} catch (IOException e) {
return null;
}
}
/**
* Writes the given data to the given file in a background thread, returning on the
* original thread (typically the UI thread) once writing is done.
* If some error is encountered, the {@link FileCallback} will return null instead of the
* original file.
*
* @param data the data to be written
* @param file the file to write into
* @param callback a callback
*/
@SuppressWarnings("WeakerAccess")
public static void writeToFile(@NonNull final byte[] data, @NonNull final File file, @NonNull final FileCallback callback) {
final Handler ui = new Handler();
WorkerHandler.run(new Runnable() {
@Override
public void run() {
final File result = writeToFile(data, file);
ui.post(new Runnable() {
@Override
public void run() {
callback.onFileReady(result);
}
});
}
});
}
/**
* Decodes an input byte array and outputs a Bitmap that is ready to be displayed.
* The difference with {@link android.graphics.BitmapFactory#decodeByteArray(byte[], int, int)}
@ -65,9 +123,10 @@ public class CameraUtils {
* @param source a JPEG byte array
*/
@SuppressWarnings("WeakerAccess")
@Nullable
@WorkerThread
public static void decodeBitmap(@NonNull final byte[] source) {
decodeBitmap(source, Integer.MAX_VALUE, Integer.MAX_VALUE);
public static Bitmap decodeBitmap(@NonNull final byte[] source) {
return decodeBitmap(source, Integer.MAX_VALUE, Integer.MAX_VALUE);
}
/**

@ -0,0 +1,25 @@
package com.otaliastudios.cameraview;
import android.graphics.Bitmap;
import java.io.File;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
/**
* Receives callbacks about a file saving operation.
*/
public interface FileCallback {
/**
* Notifies that the data was succesfully written to file.
* This is run on the UI thread.
* Returns a null object if an exception was encountered, for example
* if you don't have permissions to write to file.
*
* @param file the written file, or null
*/
@UiThread
void onFileReady(@Nullable File file);
}

@ -39,7 +39,7 @@ public class PicturePreviewActivity extends Activity {
captureLatency.setTitleAndMessage("Approx. latency", delay + " milliseconds");
captureResolution.setTitleAndMessage("Resolution", result.getSize() + " (" + ratio + ")");
exifRotation.setTitleAndMessage("EXIF rotation", result.getRotation() + "");
result.asBitmap(1000, 1000, new BitmapCallback() {
result.toBitmap(1000, 1000, new BitmapCallback() {
@Override
public void onBitmapReady(Bitmap bitmap) {
imageView.setImageBitmap(bitmap);

@ -73,12 +73,16 @@ camera.addCameraListener(new CameraListener() {
@Override
public void onPictureTaken(PictureResult result) {
// Picture was taken!
// If planning to save a file, just get the jpeg array.
byte[] jpeg = result.getJpeg();
// If planning to show a Bitmap, we will take care of
// EXIF rotation and background threading for you...
result.asBitmap(maxWidth, maxHeight, callback);
result.toBitmap(maxWidth, maxHeight, callback);
// If planning to save a file on a background thread,
// just use toFile. Ensure you have permissions.
result.toFile(file, callback);
// Access the raw data if needed.
byte[] data = result.getData();
}
});
camera.takePicture();
@ -124,7 +128,7 @@ For runtime permissions and Manifest setup, please read the [permissions page]()
If you are not using support libraries and you can't resolve the LifecycleOwner interface,
make sure you override `onResume`, `onPause` and `onDestroy` in your activity (`onDestroyView`
in your fragment), and call `CameraView.open()`, `close()` and `destroy()`.
in your fragment), and call `open()`, `close()` and `destroy()`.
```java
@Override

@ -156,7 +156,7 @@ The listener interface brings two breaking signature changes:
- `onPictureTaken()` now returns a `PictureResult`. Use `result.getJpeg()` to access the jpeg stream.
The result class includes rich information about the picture (or picture snapshot) that was taken,
plus handy utilities (`result.asBitmap()`...)
plus handy utilities (`result.toBitmap()`, `result.toFile()`...)
- `onVideoTaken()` now returns a `VideoResult`. Use `result.getFile()` to access the video file.
The result class includes rich information about the video (or video snapshot) that was taken.

Loading…
Cancel
Save