YuvToJpegConverter.java
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.camera.extensions.internal.sessionprocessor;
import android.graphics.ImageFormat;
import android.view.Surface;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.camera.core.ImageProcessingUtil;
import androidx.camera.core.ImageProxy;
import androidx.camera.core.Logger;
import androidx.camera.core.impl.ImageOutputConfig;
import androidx.core.util.Preconditions;
/**
* A image converter for YUV_420_888 to JPEG. The converted JPEG images were written to the given
* output surface after {@link #writeYuvImage(ImageProxy)} is invoked.
*/
@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
class YuvToJpegConverter {
private static final String TAG = "YuvToJpegConverter";
private final Surface mOutputJpegSurface;
@IntRange(from = 1, to = 100)
private volatile int mJpegQuality;
@ImageOutputConfig.RotationDegreesValue
private volatile int mRotationDegrees = 0;
YuvToJpegConverter(int jpegQuality, @NonNull Surface outputJpegSurface) {
mJpegQuality = jpegQuality;
mOutputJpegSurface = outputJpegSurface;
}
public void setRotationDegrees(@ImageOutputConfig.RotationDegreesValue int rotationDegrees) {
mRotationDegrees = rotationDegrees;
}
void setJpegQuality(int jpgQuality) {
mJpegQuality = jpgQuality;
}
static class ConversionFailedException extends Exception {
ConversionFailedException(String message) {
super(message);
}
ConversionFailedException(String message, Throwable cause) {
super(message, cause);
}
}
/**
* Writes an YUV_420_888 image and converts it into a JPEG image.
*/
void writeYuvImage(@NonNull ImageProxy imageProxy) throws ConversionFailedException {
Preconditions.checkState(imageProxy.getFormat() == ImageFormat.YUV_420_888,
"Input image is not expected YUV_420_888 image format");
try {
// TODO(b/258667618): remove extra copy by writing the jpeg data directly into the
// Surface's ByteBuffer.
boolean success = ImageProcessingUtil.convertYuvToJpegBytesIntoSurface(
imageProxy,
mJpegQuality,
mRotationDegrees,
mOutputJpegSurface);
if (!success) {
throw new ConversionFailedException("Failed to process YUV -> JPEG");
}
} catch (Exception e) {
Logger.e(TAG, "Failed to process YUV -> JPEG", e);
throw new ConversionFailedException("Failed to process YUV -> JPEG", e);
} finally {
imageProxy.close();
}
}
}