package fr.tvbarthel.apps.cameracolorpicker.views;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.TextureView;

import fr.tvbarthel.apps.cameracolorpicker.utils.Views;

/**
 * A simple {@link android.view.TextureView} used to render camera preview.
 */
public class CameraColorPickerPreview extends TextureView implements TextureView.SurfaceTextureListener, Camera.PreviewCallback {

    private static final String TAG = CameraColorPickerPreview.class.getCanonicalName();

    /**
     * The size of the pointer (in DIP).
     */
    protected static final float POINTER_SIZE = 10;

    protected Camera mCamera;
    protected int mPointerSize;
    protected Camera.Size mPreviewSize;
    protected OnColorPickedListener mOnColorPickedListener;
    protected int mWidth;
    protected int mHeight;

    public CameraColorPickerPreview(Context context, Camera camera) {
        super(context);
        mCamera = camera;
        mCamera.getParameters().getPreviewFormat();

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        this.setSurfaceTextureListener(this);

        final DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
        mPointerSize = Views.dipToPx(displayMetrics, POINTER_SIZE);
        mPreviewSize = mCamera.getParameters().getPreviewSize();
    }


    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        // The Surface has been created, now tell the camera where to draw the preview.
        try {
            mCamera.setPreviewTexture(surface);
            mCamera.setPreviewCallback(this);
            mCamera.startPreview();

        } catch (Exception e) {
            Log.d(TAG, "Error starting camera preview: " + e.getMessage());
        }
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

    }


    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        return false;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        if (mOnColorPickedListener != null) {
            final int midX = mPreviewSize.width / 2;
            final int midY = mPreviewSize.height / 2;
            mOnColorPickedListener.onColorPicked(getColorFromYUV420(data, midX, midY, mPreviewSize.width, mPreviewSize.height));
        }

    }

    protected int getColorFromYUV420(byte[] data, int x, int y, int width, int height) {
        final int size = width * height;
        final int Y = data[y * width + x] & 0xff;
        final int xby2 = x / 2;
        final int yby2 = y / 2;

        final float V = (float) (data[size + 2 * xby2 + yby2 * width] & 0xff) - 128.0f;
        final float U = (float) (data[size + 2 * xby2 + 1 + yby2 * width] & 0xff) - 128.0f;

        // Do the YUV -> RGB conversion
        float Yf = 1.164f * ((float) Y) - 16.0f;
        int red = (int) (Yf + 1.596f * V);
        int green = (int) (Yf - 0.813f * V - 0.391f * U);
        int blue = (int) (Yf + 2.018f * U);

        // Clip rgb values to 0-255
        red = red < 0 ? 0 : red > 255 ? 255 : red;
        green = green < 0 ? 0 : green > 255 ? 255 : green;
        blue = blue < 0 ? 0 : blue > 255 ? 255 : blue;

        return Color.rgb(red, green, blue);
    }


    public void setOnColorPickedListener(OnColorPickedListener onColorPickedListener) {
        mOnColorPickedListener = onColorPickedListener;
    }

    public interface OnColorPickedListener {
        void onColorPicked(int color);
    }

}
@@ -81,40 +81,8 @@
 xt;%0A
-import android.graphics.Bitmap;%0A
 impo
@@ -279,65 +279,8 @@
 w;%0A%0A
-import fr.tvbarthel.apps.cameracolorpicker.utils.Views;%0A%0A
 /**%0A
@@ -627,11 +627,14 @@
 (in 
-DIP
+PIXELS
 ).%0A 
@@ -667,20 +667,18 @@
 c final 
-floa
+in
 t POINTE
@@ -683,17 +683,18 @@
 TER_
-SIZE = 10
+RADIUS = 5
 ;%0A%0A 
@@ -1350,76 +1350,8 @@
 ();%0A
-        mPointerSize = Views.dipToPx(displayMetrics, POINTER_SIZE);%0A
     
@@ -2444,121 +2444,518 @@
     
-mOnColorPickedListener.onColorPicked(getColorFromYUV420(data, midX
+final int%5B%5D colors = new int%5B3%5D;%0A            for (int i = 0; i %3C= POINTER_RADIUS; i++) %7B%0A                for (int j = 0; j %3C= POINTER_RADIUS; j++) %7B%0A                    addColorFromYUV420(data, colors, (i * POINTER_RADIUS + j + 1),%0A                            (midX - POINTER_RADIUS) + i
 , 
+(
 midY
-, mPreviewSize.width, mPreviewSize.height
+ - POINTER_RADIUS) + j,%0A                            mPreviewSize.width, mPreviewSize.height);%0A                %7D%0A            %7D%0A            mOnColorPickedListener.onColorPicked(Color.rgb(colors%5B0%5D, colors%5B1%5D, colors%5B2%5D
 ));%0A
@@ -2990,15 +2990,16 @@
 ted 
-int get
+void add
 Colo
@@ -3022,16 +3022,47 @@
 %5B%5D data,
+ int%5B%5D averageColor, int count,
  int x, 
@@ -3879,42 +3879,181 @@
     
-return Color.rgb(red, green, blue)
+averageColor%5B0%5D += (red - averageColor%5B0%5D) / count;%0A        averageColor%5B1%5D += (green - averageColor%5B1%5D) / count;%0A        averageColor%5B2%5D += (blue - averageColor%5B2%5D) / count
 ;%0A  

Use multiple pixel values for computing the picked color