com.TwentyCodes.android.IOIOTruck.CameraFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.TwentyCodes.android.IOIOTruck.CameraFragment.java

Source

/**
 * CameraFragment.java
 * @date Jan 29, 2012
 * @author ricky barrette
 * @author Twenty Codes, LLC
 * 
 * Copyright 2012 Richard Barrette 
 * 
 * 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 com.TwentyCodes.android.IOIOTruck;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

/**
 * This camera fragment will be used to maintain the camera, display a preview on the screen, display a vanishing point overlay on the preview
 * @author ricky barrette
 */
public class CameraFragment extends Fragment {

    /**
     * A interface used to receive steering updates generated by the camera
     * @author ricky barrette
     */
    public interface CameraListener {
        /**
         * Called when there is new information
         * @param error
         * @author ricky barrette
         */
        public void onCameraUpdate(int steeringModifier);
    }

    private boolean isDrawingView;
    private Camera mCamera;
    private Size mPreviewSize;
    private byte[] mImageData;
    private PreviewOverlay mPreviewOverlay;
    private SurfaceView mPreview;
    private CameraListener mListener;

    /**
     * Creates a new VanishingPointCameraFragment 
     * @author ricky barrette
     */
    public CameraFragment() {
        super();
    }

    /**
     * (non-Javadoc)
     * @see android.support.v4.app.Fragment#onViewCreated(android.view.View, android.os.Bundle)
     * @author ricky barrette
     */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.camera_fragment, container, false);

        /*
         * setup augmented preview overlay
         */
        FrameLayout fl = (FrameLayout) view.findViewById(R.id.camera_frame);
        mPreviewOverlay = new PreviewOverlay(this.getActivity());
        fl.addView(mPreviewOverlay);

        /*
         * setup camera preview      
         */
        mPreview = (SurfaceView) view.findViewById(R.id.cameraSurface);
        SurfaceHolder cameraHolder = mPreview.getHolder();
        cameraHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        cameraHolder.addCallback(new SurfaceHolder.Callback() {
            public void surfaceCreated(SurfaceHolder holder) {
                try {
                    mCamera.setPreviewDisplay(holder);
                    mCamera.startPreview();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            public void surfaceDestroyed(SurfaceHolder holder) {
            }

            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            }
        });

        return view;
    }

    /**
     * Called when the application is resuming
     * (non-Javadoc)
     * @see android.support.v4.app.Fragment#onResume()
     * @author ricky barrette 
     */
    @Override
    public void onResume() {
        super.onResume();

        /*
         * open camera
         */
        mCamera = Camera.open();
        mCamera.setDisplayOrientation(90);
        Camera.Parameters params = mCamera.getParameters();

        /*
         * find smallest preview size
         */
        List<Size> sizes = params.getSupportedPreviewSizes();
        Iterator<Size> iter = sizes.iterator();
        mPreviewSize = sizes.get(0);
        int minPixelCount = mPreviewSize.width * mPreviewSize.height;
        while (iter.hasNext()) {
            Size size = iter.next();
            int pixelCount = size.height * size.width;
            if (pixelCount < minPixelCount) {
                minPixelCount = pixelCount;
                mPreviewSize = size;
            }
        }
        params.setPreviewSize(mPreviewSize.width, mPreviewSize.height);

        mPreviewOverlay.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
        mImageData = new byte[mPreviewSize.width * mPreviewSize.height];
        mCamera.setPreviewCallback(new Camera.PreviewCallback() {

            @Override
            public void onPreviewFrame(byte[] data, Camera camera) {
                if (!isDrawingView) {
                    mImageData = data;
                    mPreviewOverlay.invalidate();
                    isDrawingView = true;
                }
            }
        });

        params.setRotation(90);
        mCamera.setParameters(params);

    }

    /**
     * Called when the application is pausing
     * (non-Javadoc)
     * @see android.support.v4.app.Fragment#onPause()
     * @author ricky barrette
     */
    public void onPause() {
        super.onPause();
        mCamera.stopPreview();
        mCamera.setPreviewCallback(null);
        mCamera.release();
    }

    /**
     * @return the mError
     */
    public void setListener(CameraListener listener) {
        mListener = listener;
    }

    /**
     * This View view will be displayed over the image preview.
     * It will be used to display a human readable overlay
     * @author ricky barrette
     */
    private class PreviewOverlay extends View {

        private int imageWidth, imageHeight, mHorizonOffset;
        private int[] localData, edgePixels;
        private long lastTime;
        private int mVerticalOffsetLeft;
        private int mVerticalOffsetRight;

        /**
         * Creates a new PreviewOverlay
         * @param context
         * @author ricky barrette
         */
        public PreviewOverlay(Context context) {
            super(context);
            lastTime = System.nanoTime();
        }

        public void setPreviewSize(int width, int height) {
            ViewGroup.LayoutParams layoutParams = this.getLayoutParams();
            layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
            layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
            this.setLayoutParams(layoutParams);

            imageWidth = width;
            imageHeight = height;

            localData = new int[width * height];
            edgePixels = new int[width * height];
        }

        /**
         * Called by system when view is invalidated
         * (non-Javadoc)
         * @see android.view.View#onDraw(android.graphics.Canvas)
         * @author ricky barrette
         */
        @Override
        public void onDraw(Canvas canvas) {
            super.onDraw(canvas);

            mHorizonOffset = (this.getHeight() / 4) * 3;
            mVerticalOffsetLeft = this.getWidth() / 4;
            mVerticalOffsetRight = (this.getWidth() / 4) * 3;

            if (mImageData == null)
                return;

            Paint paint = new Paint();
            paint.setColor(Color.RED);

            /*
             * draw the vertical & horizon lines that represent the robots path
             */
            canvas.drawLine(0, mHorizonOffset, this.getWidth(), mHorizonOffset, paint);
            canvas.drawLine(mVerticalOffsetLeft, mHorizonOffset, mVerticalOffsetLeft, this.getHeight(), paint);
            canvas.drawLine(mVerticalOffsetRight, mHorizonOffset, mVerticalOffsetRight, this.getHeight(), paint);

            /*
             * TODO Draw boxes around objects
             */

            /*
             * TODO some magical computer vision math
             * TODO draw path
             */
            paint.setStrokeWidth(2);
            paint.setColor(Color.GREEN);

            /*
             * here is some text information
             */
            paint.setColor(Color.RED);
            paint.setTextSize(30);

            /*
             * FPS
             */
            long thisTime = System.nanoTime();
            double fps = Math.floor(1e12 / (thisTime - lastTime)) / 1000;
            lastTime = thisTime;
            canvas.drawText(fps + " fps", 5, 30, paint);

            isDrawingView = false;

        }
    }
}