package com.fastebro.androidrgbtool.livepicker;
import android.content.Context;
import android.graphics.Color;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.view.TextureView;
import timber.log.Timber;
/**
* Created by danielealtomare on 31/03/16.
* Project: rgb-tool
*/
public class LivePickerTextureView extends TextureView implements TextureView.SurfaceTextureListener, Camera
.PreviewCallback {
private static final String TAG = LivePickerTextureView.class.getCanonicalName();
private static final int POINTER_RADIUS = 5;
private Camera camera;
private Camera.Size previewSize;
private int[] selectedColor;
private OnColorPointedListener onColorPointedListener;
public interface OnColorPointedListener {
void onColorPointed(int newColor);
}
public LivePickerTextureView(Context context, Camera camera) {
super(context);
this.camera = camera;
this.camera.getParameters().getPreviewFormat();
// Set a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
this.setSurfaceTextureListener(this);
this.previewSize = camera.getParameters().getPreviewSize();
this.selectedColor = new int[3];
}
public void setOnColorPointedListener(OnColorPointedListener onColorPointedListener) {
this.onColorPointedListener = onColorPointedListener;
}
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
if (onColorPointedListener != null) {
final int midX = previewSize.width / 2;
final int midY = previewSize.height / 2;
selectedColor[0] = 0;
selectedColor[1] = 0;
selectedColor[2] = 0;
// Compute the average selected color.
for (int i = 0; i <= POINTER_RADIUS; i++) {
for (int j = 0; j <= POINTER_RADIUS; j++) {
addColorFromYUV420(data, selectedColor, (i * POINTER_RADIUS + j + 1),
(midX - POINTER_RADIUS) + i, (midY - POINTER_RADIUS) + j,
previewSize.width, previewSize.height);
}
}
onColorPointedListener.onColorPointed(Color.rgb(selectedColor[0], selectedColor[1], selectedColor[2]));
}
}
// Credits go to http://stackoverflow.com/a/10125048
private void addColorFromYUV420(byte[] data, int[] averageColor, int count, 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;
// 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;
averageColor[0] += (red - averageColor[0]) / count;
averageColor[1] += (green - averageColor[1]) / count;
averageColor[2] += (blue - averageColor[2]) / count;
}
@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 {
camera.setPreviewTexture(surface);
camera.setPreviewCallback(this);
camera.startPreview();
} catch (Exception e) {
Timber.d("Camera preview start failure: %s", e.getMessage());
}
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Nothing to do in this case.
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
}