@ -9,6 +9,8 @@ import android.view.ViewGroup;
abstract class Preview {
private final static CameraLogger LOG = CameraLogger . create ( Preview . class . getSimpleName ( ) ) ;
// This is used to notify CameraImpl to recompute its camera Preview size.
// After that, CameraView will need a new layout pass to adapt to the Preview size.
interface SurfaceCallback {
@ -45,6 +47,7 @@ abstract class Preview {
// This is called by the CameraImpl.
// These must be alredy rotated, if needed, to be consistent with surface/view sizes.
void setDesiredSize ( int width , int height ) {
LOG . i ( "setDesiredSize:" , "desiredW=" , width , "desiredH=" , height ) ;
this . mDesiredWidth = width ;
this . mDesiredHeight = height ;
crop ( ) ;
@ -60,6 +63,7 @@ abstract class Preview {
protected final void onSurfaceAvailable ( int width , int height ) {
LOG . i ( "onSurfaceAvailable:" , "w=" , width , "h=" , height ) ;
mSurfaceWidth = width ;
mSurfaceHeight = height ;
crop ( ) ;
@ -70,6 +74,7 @@ abstract class Preview {
// As far as I can see, these are the view/surface dimensions.
// This is called by subclasses.
protected final void onSurfaceSizeChanged ( int width , int height ) {
LOG . i ( "onSurfaceSizeChanged:" , "w=" , width , "h=" , height ) ;
if ( width ! = mSurfaceWidth | | height ! = mSurfaceHeight ) {
mSurfaceWidth = width ;
mSurfaceHeight = height ;
@ -87,30 +92,33 @@ abstract class Preview {
/ * *
* As far as I can see , this extends either width or height of the surface ,
* to match the desired aspect ratio .
* This means that the external part of the surface will be cropped by the outer view .
* Here we must crop the visible part by applying a > 1 scale to one of our
* dimensions . This way our internal aspect ratio ( mSurfaceWidth / mSurfaceHeight )
* will match the preview size aspect ratio ( mDesiredWidth / mDesiredHeight ) .
*
* There might still be some absolute difference ( e . g . same ratio but bigger / smaller ) .
* However that should be already managed by the framework .
* /
private final void crop ( ) {
getView ( ) . post ( new Runnable ( ) {
@Override
public void run ( ) {
if ( mDesiredWidth ! = 0 & & mDesiredHeight ! = 0 ) {
AspectRatio aspectRatio = AspectRatio . of ( mDesiredWidth , mDesiredHeight ) ;
float targetHeight = ( float ) mSurfaceWidth / aspectRatio . toFloat ( ) ;
float scale = 1 ;
if ( mSurfaceHeight > 0 ) {
scale = targetHeight / ( float ) mSurfaceHeight ;
}
if ( scale > 1 ) {
getView ( ) . setScaleX ( 1f ) ;
getView ( ) . setScaleY ( scale ) ;
if ( mDesiredHeight = = 0 | | mDesiredWidth = = 0 ) return ;
if ( mSurfaceHeight = = 0 | | mSurfaceWidth = = 0 ) return ;
float scaleX = 1f , scaleY = 1f ;
AspectRatio current = AspectRatio . of ( mSurfaceWidth , mSurfaceHeight ) ;
AspectRatio target = AspectRatio . of ( mDesiredWidth , mDesiredHeight ) ;
if ( current . toFloat ( ) > = target . toFloat ( ) ) {
// We are too short. Must increase height.
scaleY = current . toFloat ( ) / target . toFloat ( ) ;
} else {
getView ( ) . setScaleX ( 1f / scale ) ;
getView ( ) . setScaleY ( 1f ) ;
}
// We must increase width.
scaleX = target . toFloat ( ) / current . toFloat ( ) ;
}
getView ( ) . setScaleX ( scaleX ) ;
getView ( ) . setScaleY ( scaleY ) ;
LOG . i ( "crop:" , "applied scaleX=" , scaleX ) ;
LOG . i ( "crop:" , "applied scaleY=" , scaleY ) ;
}
} ) ;
}