package com.ford.openxc.nightvision;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.media.MediaPlayer;
import android.util.AttributeSet;
import android.view.SurfaceHolder;

import com.ford.openxc.webcam.WebcamPreview;

public class NightvisionView extends WebcamPreview {
    private final static String TAG = "NightvisionView";
    private final static int OBJECT_DETECT_BLOCK_SIZE_X = 8;
    private final static int OBJECT_DETECT_BLOCK_SIZE_Y = 8;

    private Bitmap mBitmapGray = null;
    private Bitmap mBitmapEdges = null;
    private Bitmap mBitmapObjectOverlay = null;

    private boolean objectInPrevFrame = false;
    private MediaPlayer mMediaPlayer;

    public native void toGrayscale(Bitmap bitmapcolor, Bitmap bitmapgray);
    public native void detectEdges(Bitmap bitmapgray, Bitmap bitmapedges);
    public native void showBitmap(Bitmap bitmapedges, Bitmap bitmapout);

    static {
        System.loadLibrary("nightvision");
    }

    public NightvisionView(Context context) {
        super(context);
        init();
    }

    public NightvisionView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mMediaPlayer = MediaPlayer.create(getContext(), R.raw.alert);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int winWidth,
            int winHeight) {
        super.surfaceChanged(holder, format, winWidth, winHeight);
        Rect window = getViewingWindow();
        mBitmapObjectOverlay = Bitmap.createBitmap(window.width(),
                window.height(), Bitmap.Config.ARGB_8888);
        mBitmapGray = Bitmap.createBitmap(window.width(), window.height(),
                Bitmap.Config.ALPHA_8);
        mBitmapEdges = Bitmap.createBitmap(window.width(), window.height(),
                Bitmap.Config.ALPHA_8);
    }

    protected void drawOnCanvas(Canvas canvas, Bitmap videoBitmap) {
        toGrayscale(videoBitmap, mBitmapGray);
        detectEdges(mBitmapGray, mBitmapEdges);
        showBitmap(mBitmapEdges, videoBitmap);

        Paint overlayPaint = new Paint();
        overlayPaint.setAlpha(0);

        boolean objectDetected = detectObjects(videoBitmap,
                mBitmapObjectOverlay);
        if (!objectInPrevFrame && objectDetected) {
            mMediaPlayer.start();
            objectInPrevFrame = true;
        } else if (objectInPrevFrame && !objectDetected) {
            objectInPrevFrame = false;
        }

        overlayPaint.setAlpha(130);
        canvas.drawBitmap(videoBitmap, null, getViewingWindow(), overlayPaint);
        canvas.drawBitmap(mBitmapObjectOverlay, null, getViewingWindow(),
                overlayPaint);
    }

    /** Simple Object Detection
     *
     * This object detection limits the detection to a bounded area of interest
     * that is the middle 50% of the screen. It then iterates through the
     * bounded area looking at a smaller area of OBJECT_DETECT_BLOCK_SIZE_X *
     * OBJECT_DETECT_BLOCK_SIZE_Y. If that area contains more than 40% white
     * pixels (edges) then the area is considered part of an object and it is
     * marked so in the mBitmapObjectOverlay.
     */
    public boolean detectObjects(Bitmap videoBitmap, Bitmap overlayBitmap) {
        overlayBitmap.eraseColor(Color.TRANSPARENT);

        boolean objectDetected = false;
        Rect window = getViewingWindow();
        int[] overlaySection = new int [OBJECT_DETECT_BLOCK_SIZE_X *
                OBJECT_DETECT_BLOCK_SIZE_Y];
        for(int y = (int) (window.height() * .25); y < window.height() * .75;
                    y += (OBJECT_DETECT_BLOCK_SIZE_Y / 2)) {
            for(int x = (int) (window.width() * .25); x < window.width() * .75;
                    x += (OBJECT_DETECT_BLOCK_SIZE_X / 2)) {
                int sum = 0;
                for(int i = 0; i < OBJECT_DETECT_BLOCK_SIZE_X; i++) {
                    for(int j=0 ; j < OBJECT_DETECT_BLOCK_SIZE_Y; j++) {
                        if(videoBitmap.getPixel((x + i), (y + j))
                                == Color.WHITE) {
                            sum++;
                            overlaySection[i + j *
                                    OBJECT_DETECT_BLOCK_SIZE_Y] = -256;
                        }
                    }
                }

                if (sum > (OBJECT_DETECT_BLOCK_SIZE_Y *
                            OBJECT_DETECT_BLOCK_SIZE_X * .4)) {
                    overlayBitmap.setPixels(overlaySection, 0,
                            OBJECT_DETECT_BLOCK_SIZE_X,
                            x, y,
                            OBJECT_DETECT_BLOCK_SIZE_X,
                            OBJECT_DETECT_BLOCK_SIZE_Y);
                    objectDetected = true;
                }
            }
        }
        return objectDetected;
    }
}

@@ -193,38 +193,8 @@
 nt;%0A
-import android.graphics.Rect;%0A
 impo
@@ -572,16 +572,175 @@
 Y = 8;%0A%0A
+    // TODO these are duplicated from the android-webcam library%0A    private final static int IMG_WIDTH = 640;%0A    private final static int IMG_HEIGHT = 480;%0A%0A
     priv
@@ -1741,50 +1741,8 @@
 t);%0A
-        Rect window = getViewingWindow();%0A
     
@@ -1792,56 +1792,46 @@
 map(
-window.width(),%0A                window.height(),
+IMG_WIDTH, IMG_HEIGHT,%0A               
  Bit
@@ -1899,39 +1899,29 @@
 map(
-window.width(), window.height()
+IMG_WIDTH, IMG_HEIGHT
 ,%0A  
@@ -2005,39 +2005,29 @@
 map(
-window.width(), window.height()
+IMG_WIDTH, IMG_HEIGHT
 ,%0A  
@@ -3575,50 +3575,8 @@
 se;%0A
-        Rect window = getViewingWindow();%0A
     
@@ -3716,51 +3716,41 @@
 t) (
-window.height() * .25); y %3C window.height()
+IMG_HEIGHT * .25); y %3C IMG_HEIGHT
  * .
@@ -3849,49 +3849,39 @@
 t) (
-window.width() * .25); x %3C window.width()
+IMG_WIDTH * .25); x %3C IMG_WIDTH
  * .

Use video image size for bitmaps, not adjusted window size.