diff options
Diffstat (limited to 'src/com/google/snappy/PreviewOverlay.java')
-rw-r--r-- | src/com/google/snappy/PreviewOverlay.java | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/src/com/google/snappy/PreviewOverlay.java b/src/com/google/snappy/PreviewOverlay.java new file mode 100644 index 0000000..803d824 --- /dev/null +++ b/src/com/google/snappy/PreviewOverlay.java @@ -0,0 +1,216 @@ +package com.google.snappy; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PointF; +import android.graphics.RectF; +import android.util.AttributeSet; +import android.view.View; + +/** + * Created by andyhuibers on 9/18/14. + */ + +public class PreviewOverlay extends View { + private static final String TAG = "SNAPPY_FACE"; + + private boolean mShow3AInfo; + private boolean mShowGyroGrid; + private int mColor; + private int mColor2; + private Paint mPaint; + private Paint mPaint2; + + // Rendered data: + private NormalizedFace[] mFaces; + private float mExposure; + private float mLens; + private int mAfState; + private float mFovLargeDegrees; + private float mFovSmallDegrees; + float[] mAngles = new float[2]; + + public PreviewOverlay(Context context, AttributeSet attrs) { + super(context, attrs); + Resources res = getResources(); + mColor = res.getColor(R.color.face_color); + mPaint = new Paint(); + mPaint.setColor(mColor); + mPaint.setAntiAlias(true); + mPaint.setStyle(Paint.Style.STROKE); + mPaint.setStrokeWidth(res.getDimension(R.dimen.face_circle_stroke)); + + mColor2 = res.getColor(R.color.hud_color); + mPaint2 = new Paint(); + mPaint2.setAntiAlias(true); + mPaint2.setStyle(Paint.Style.STROKE); + mPaint2.setStrokeWidth(res.getDimension(R.dimen.hud_stroke)); + } + + public void setFrameData(NormalizedFace[] faces, float normExposure, float normLens, int afState) { + mFaces = faces; + mExposure = normExposure; + mLens = normLens; + mAfState = afState; + this.setVisibility(VISIBLE); + invalidate(); + } + + public void show3AInfo(boolean show) { + mShow3AInfo = show; + this.setVisibility(VISIBLE); + invalidate(); + } + + public void setGyroAngles(float[] angles) { + mAngles = angles; + } + + public void setFieldOfView(float fovLargeDegrees, float fovSmallDegrees) { + mFovLargeDegrees = fovLargeDegrees; + mFovSmallDegrees = fovSmallDegrees; + } + + public void showGyroGrid(boolean show) { + mShowGyroGrid = show; + this.setVisibility(VISIBLE); + invalidate(); + } + + private static double SHORT_LOG_EXPOSURE = Math.log10(1000000000 / 10000); // 1/10000 second + private static double LONG_LOG_EXPOSURE = Math.log10(1000000000 / 10); // 1/10 second + float[] yGridValues = new float[] { + (float) ((Math.log10(1000000000 / 30) - SHORT_LOG_EXPOSURE) / (LONG_LOG_EXPOSURE - SHORT_LOG_EXPOSURE)), + (float) ((Math.log10(1000000000 / 100) - SHORT_LOG_EXPOSURE) / (LONG_LOG_EXPOSURE - SHORT_LOG_EXPOSURE)), + (float) ((Math.log10(1000000000 / 1000) - SHORT_LOG_EXPOSURE) / (LONG_LOG_EXPOSURE - SHORT_LOG_EXPOSURE))}; + + /** Focus states + CONTROL_AF_STATE_INACTIVE 0 + CONTROL_AF_STATE_PASSIVE_SCAN 1 + CONTROL_AF_STATE_PASSIVE_FOCUSED 2 + CONTROL_AF_STATE_ACTIVE_SCAN 3 + CONTROL_AF_STATE_FOCUSED_LOCKED 4 + CONTROL_AF_STATE_NOT_FOCUSED_LOCKED 5 + CONTROL_AF_STATE_PASSIVE_UNFOCUSED 6 + */ + + @Override + protected void onDraw(Canvas canvas) { + if (mFaces == null) { + return; + } + float previewW = this.getWidth(); + float previewH = this.getHeight(); + + // 3A visualizatoins + if (mShow3AInfo) { + + // Draw 3A ball on a rail + if (false) { + mPaint2.setStyle(Paint.Style.FILL_AND_STROKE); + mPaint2.setColor(0x33FFFFFF); + canvas.drawRect(0.04f * previewW, 0.03f * previewH, 0.96f * previewW, 0.05f * previewH, mPaint2); + + mPaint2.setStyle(Paint.Style.FILL_AND_STROKE); + float x1 = (0.92f * mLens + 0.04f) * previewW; + float y1 = (0.04f) * previewH; + mPaint2.setColor(0xFF000000); + canvas.drawCircle(x1, y1, 20, mPaint2); + mPaint2.setColor(0xFFDDDDDD); + canvas.drawCircle(x1, y1, 18, mPaint2); + } + + // Draw AF center thing + mPaint2.setStyle(Paint.Style.FILL_AND_STROKE); + float x2 = 0.5f * previewW; + float y2 = 0.5f * previewH; + mPaint2.setColor(0x990000FF); + String text = "NOT IN CAF"; + if (mAfState == 1) { // passive scan RED + mPaint2.setColor(0x99FF0000); + text = "CAF SCAN"; + } + if (mAfState == 2) { // passive good + mPaint2.setColor(0x9999FF99); + text = "CAF FOCUSED"; + } + if (mAfState == 6) { // passive bad + mPaint2.setColor(0x99FFFFFF); + text = "CAF UNFOCUSED"; + } + canvas.drawCircle(x2, y2, mLens * 0.25f * previewW, mPaint2); + mPaint.setColor(0xFFFFFFFF); + mPaint.setTextSize(36f); + canvas.drawText(text, x2, y2 - mLens * 0.25f * previewW - 7f, mPaint); + } + + // Draw Faces + for (NormalizedFace face : mFaces) { + RectF r1 = face.bounds; + float newY = r1.centerX() * previewH; + float newX = (1 - r1.centerY()) * previewW; + float dY = r1.width() * previewH; + float dX = r1.height() * previewW; + float dP = (dX + dY) * 0.045f; + RectF newR1 = new RectF(newX - dX * 0.5f, newY - dY * 0.5f, newX + dX * 0.5f, newY + dY * 0.5f); + canvas.drawRoundRect(newR1, dP, dP, mPaint); + + PointF[] p = new PointF[3]; + p[0] = face.leftEye; + p[1] = face.rightEye; + p[2] = face.mouth; + + for (int j = 0; j < 3; j++) { + if (p[j] == null) { + continue; + } + newY = p[j].x * previewH; + newX = (1 - p[j].y) * previewW; + canvas.drawCircle(newX, newY, dP, mPaint); + } + } + + // Draw Gyro grid. + if (mShowGyroGrid) { + float x1, x2, y1, y2; + + // + // screen/sensor + // | + // screen/2 = FL tan(FOV/2) | + // | lens + // |<––––––––––––– FL –––––––––––>()–––––––––> scene @ infinity + // | + // | + // | + // + + float focalLengthH = 0.5f * previewH / (float) Math.tan(Math.toRadians(mFovLargeDegrees) * 0.5); + float focalLengthW = 0.5f * previewW / (float) Math.tan(Math.toRadians(mFovSmallDegrees) * 0.5); + final double ANGLE_STEP = (float) Math.toRadians(10f); + + // Draw horizontal lines, with 10 degree spacing. + double phase1 = mAngles[0] % ANGLE_STEP; + for (double i = -5 * ANGLE_STEP + phase1; i < 5 * ANGLE_STEP; i += ANGLE_STEP) { + x1 = 0; + x2 = previewW; + y1 = y2 = previewH / 2 + focalLengthH * (float) Math.tan(i); + canvas.drawLine(x1, y1, x2, y2, mPaint); + } + // Draw vertical lines, with 10 degree spacing. + double phase2 = mAngles[1] % ANGLE_STEP; + for (double i = -5 * ANGLE_STEP + phase2; i < 5 * ANGLE_STEP; i += ANGLE_STEP) { + x1 = x2 = previewW / 2 + focalLengthW * (float) Math.tan(i); + y1 = 0; + y2 = previewH; + canvas.drawLine(x1, y1, x2, y2, mPaint); + } + } + + super.onDraw(canvas); + } +} + + |