blob: 9f9fcefebd1df8c4132e0e3cab5ad347076adc70 [file] [log] [blame]
/*
* Copyright 2019 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.core;
import android.graphics.PointF;
import android.util.Rational;
import android.util.Size;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.LifecycleOwner;
import java.util.Set;
/**
* A {@link MeteringPointFactory} that can create {@link MeteringPoint} by sensor oriented x, y ,
* width and height.
*
* <p>This factory is suitable for apps that already have coordinates translated into sensor
* coordinates. It is also useful for apps that want to focus on something detected in
* {@link ImageAnalysis}. Apps can pass the {@link ImageAnalysis} instance for useCaseForFov
* argument and CameraX will then adjust the final sensor coordinates by aspect ratio of
* ImageAnalysis.
*/
public class SensorOrientedMeteringPointFactory extends MeteringPointFactory {
/** the logical width of FoV in sensor orientation*/
private final float mWidth;
/** the logical height of FoV in sensor orientation */
private final float mHeight;
/**
* Creates the SensorOrientedMeteringPointFactory by width and height
*
* <p>The width/height is the logical width/height of the preview FoV in sensor orientation and
* X/Y is the logical XY inside the FOV. User can set the width and height to 1.0 which will
* make the XY the normalized coordinates [0..1].
*
* <p>By default, it will use active {@link Preview} as the FoV for final coordinates
* translation.
*
* @param width the logical width of FoV in sensor orientation
* @param height the logical height of FoV in sensor orientation
*/
public SensorOrientedMeteringPointFactory(float width, float height) {
mWidth = width;
mHeight = height;
mFovAspectRatio = null;
}
/**
* Creates the SensorOrientedMeteringPointFactory by width, height and useCaseForFov.
*
* <p>The width/height is the logical width/height of the preview FoV in sensor orientation and
* X/Y is the logical XY inside the FOV. User can set the width and height to 1.0 which will
* make the XY the normalized coordinates [0..1].
*
* <p>useCaseForFov is used to determine the FOV of this translation. This useCaseForFov needs
* to be bound via {@link CameraX#bindToLifecycle(LifecycleOwner, UseCase...)} first. Otherwise
* it will throw a {@link IllegalStateException}
*
* @param width the logical width of FOV in sensor orientation.
* @param height the logical height of FOV in sensor orientation.
* @param useCaseForFov the {@link UseCase} to be the FOV.
*/
public SensorOrientedMeteringPointFactory(float width, float height,
@NonNull UseCase useCaseForFov) {
mWidth = width;
mHeight = height;
mFovAspectRatio = getUseCaseAspectRatio(useCaseForFov);
}
@Nullable
private Rational getUseCaseAspectRatio(@Nullable UseCase useCase) {
if (useCase == null) {
return null;
}
Set<String> cameraIds = useCase.getAttachedCameraIds();
if (cameraIds.isEmpty()) {
throw new IllegalStateException("UseCase " + useCase + " is not bound.");
}
for (String id : cameraIds) {
Size resolution = useCase.getAttachedSurfaceResolution(id);
// Returns an aspect ratio of first found attachedSurfaceResolution.
return new Rational(resolution.getWidth(), resolution.getHeight());
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
@NonNull
protected PointF translatePoint(float x, float y) {
PointF pt = new PointF(x / mWidth, y / mHeight);
return pt;
}
}