第一次写博客,内心好激动的说
回归正题,做一个通过手机照相机取色的功能,不多说,直接上效果图*
实现过程
1.功能主要通过Camera里面的一个接口Camera.PreviewCallback预览回调里面的onPreviewFrame()方法实现。查询源码可知,@Deprecated
这个方法通过把相机的预览图转换成byte[]。拿到字节数据就可以干坏事了。
public interface PreviewCallback
{
/**
* Called as preview frames are displayed. This callback is invoked
* on the event thread {@link #open(int)} was called from.
*
* <p>If using the {@link android.graphics.ImageFormat#YV12} format,
* refer to the equations in {@link Camera.Parameters#setPreviewFormat}
* for the arrangement of the pixel data in the preview callback
* buffers.
*
* @param data the contents of the preview frame in the format defined
* by {@link android.graphics.ImageFormat}, which can be queried
* with {@link android.hardware.Camera.Parameters#getPreviewFormat()}.
* If {@link android.hardware.Camera.Parameters#setPreviewFormat(int)}
* is never called, the default will be the YCbCr_420_SP
* (NV21) format.
* @param camera the Camera service object.
*/
void onPreviewFrame(byte[] data, Camera camera);
};
2.拿到图片的字节数组,然后把得到的byte[]转换成图片。这里为了提高效率做了图片质量压缩` Bitmap bitmap;
public void runInPreviewFrame(byte[] data, Camera camera) {
// camera.setOneShotPreviewCallback(null);
//处理data
Camera.Size previewSize = camera.getParameters().getPreviewSize();//获取尺寸,格式转换的时候要用到
BitmapFactory.Options newOpts = new BitmapFactory.Options();
newOpts.inJustDecodeBounds = true;
YuvImage yuvimage = new YuvImage(
data,
ImageFormat.NV21,
previewSize.width,
previewSize.height,
null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvimage.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 50, baos);// 80--JPG图片的质量[0-100],100最高
byte[] rawImage = baos.toByteArray();
//将rawImage转换成bitmap
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
bitmap = BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length, options);
}`
3.通过计算手机屏幕的指定像素点。得到图片上对应像素点的颜色。` private void bitmapToColor() {
L.d(“尺寸:lastX:” + lastX + “—-lastY:” + lastY);
L.d(“尺寸:bitmap.getWidth():” + bitmap.getWidth() + “—–bitmap.getHeight():” + bitmap.getHeight());
if (Math.abs(lastX) > bitmap.getHeight() || Math.abs(lastY) > bitmap.getWidth())
return;
//因为手机尺寸与屏幕尺寸不一样是一样的,所以按比例获取像素点。
int y = lastY * bitmap.getWidth() / heightPixels;
int x = lastX * bitmap.getHeight() / widthPixels;
L.d("尺寸:y:" + y + "----x:" + x);
//拍照是默認橫屏的,與滑動的坐標系不一樣
int pixel = bitmap.getPixel(y, x);
//获取颜色
int redValue = Color.red(pixel);
int blueValue = Color.blue(pixel);
int greenValue = Color.green(pixel);
L.d("redValue:" + redValue);
L.d("blueValue:" + blueValue);
L.d("greenValue:" + greenValue);
img_color.setBackgroundColor(Color.argb(255, redValue, greenValue, blueValue));
BleManagerService.telinkBle.setRgb(new byte[]{(byte) redValue, (byte) greenValue, (byte) blueValue}, ConnectStatue.controlAddr, false);
}`
这里需要的注意的是,手机照相机拍照默认是横屏的,就算你竖着拿着,得到的图片的像素宽高也是横屏的宽高。这里需要做一次转换。需要旋转90度。你可以把图片旋转90度之后在做对比。不过我这里采用比较简单的方法,传入x轴的地方,我传入y轴数值。这样轻松解决旋转的问题。
int pixel = bitmap.getPixel(y, x);
之后通过Color自带的解析像素值的方法得到颜色值。
另外值得注意得是,在计算屏幕的尺寸的时候,默认是包含状态栏的,这里需要去掉。
好了,这里大功告成。一个简单的相机取色器就完成了。唯一需要注意的是如何让屏幕与图片像素点对应。
最后
第一次写博客。不太熟悉。以后慢慢加强。之后会把通过图片取色也写出来,实现的逻辑基本一样。