gpt4 book ai didi

android - 如何在surfaceview上绘制?

转载 作者:行者123 更新时间:2023-11-30 02:35:54 26 4
gpt4 key购买 nike

大家好,我试图制作一个 QRCode 阅读器,所以我使用了 dlzaaro66 提供的 QRCodeReaderView 库,它提供了 Zxing 库的简单实现。代码正在扫描二维码,但我想制作一个引用框,以指示在相机表面 View 上扫描代码的位置我尝试使用普通绘图技术。它没有给出任何错误,但它也没有绘图,你能帮我解决问题可能发生的地方吗?

这是我的 Activity 课。

import android.app.Activity;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.Toast;

import com.dlazaro66.qrcodereaderview.QRCodeReaderView;
import com.dlazaro66.qrcodereaderview.QRCodeReaderView.OnQRCodeReadListener;


public class MyActivity extends Activity implements OnQRCodeReadListener{

QRCodeReaderView decoder;
Switch start_stop;
Paint paint;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
decoder = (QRCodeReaderView) findViewById(R.id.view2);
decoder.setOnQRCodeReadListener(this);
start_stop=(Switch) findViewById(R.id.switch1);
start_stop.setChecked(true);

start_stop.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(b){
decoder.getCameraManager().startPreview();
}
else{
decoder.getCameraManager().stopPreview();
}
}
});
paint= new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(100);
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);

}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.my, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}

@Override
public void onQRCodeRead(String text, PointF[] points) {
start_stop.setChecked(false);
if(text.startsWith("http")){
Toast.makeText(getApplicationContext(),text,Toast.LENGTH_SHORT).show();
final Intent intent = new Intent(Intent.ACTION_VIEW).setData(Uri.parse(text));
startActivity(intent);
}
else{
Toast.makeText(getApplicationContext(),text,Toast.LENGTH_SHORT).show();
}
Canvas canvas=new Canvas();
for(int i=0;i<points.length-1;i++){
canvas.drawLine(points[i].x,points[i].y,points[i+1].x,points[i+1].y,paint);
}

}

@Override
public void cameraNotFound() {

}

@Override
public void QRCodeNotFoundOnCamImage() {

}

}

这是我从中获取方法和自定义表面 View 的库项目类

public class QRCodeReaderView extends SurfaceView implements SurfaceHolder.Callback,Camera.PreviewCallback {

public interface OnQRCodeReadListener {

public void onQRCodeRead(String text, PointF[] points);
public void cameraNotFound();
public void QRCodeNotFoundOnCamImage();
}

private OnQRCodeReadListener mOnQRCodeReadListener;

private static final String TAG = QRCodeReaderView.class.getName();

private QRCodeReader mQRCodeReader;
private int mPreviewWidth;
private int mPreviewHeight;
private SurfaceHolder mHolder;
private CameraManager mCameraManager;

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

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

public void setOnQRCodeReadListener(OnQRCodeReadListener onQRCodeReadListener) {
mOnQRCodeReadListener = onQRCodeReadListener;
}

public CameraManager getCameraManager() {
return mCameraManager;
}

@SuppressWarnings("deprecation")
private void init() {
if (checkCameraHardware(getContext())){
mCameraManager = new CameraManager(getContext());

mHolder = this.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // Need to set this flag despite it's deprecated
} else {
Log.e(TAG, "Error: Camera not found");
mOnQRCodeReadListener.cameraNotFound();
}
}



/****************************************************
* SurfaceHolder.Callback,Camera.PreviewCallback
****************************************************/

@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
// Indicate camera, our View dimensions
mCameraManager.openDriver(holder,this.getWidth(),this.getHeight());
} catch (IOException e) {
Log.w(TAG, "Can not openDriver: "+e.getMessage());
mCameraManager.closeDriver();
}

try {
mQRCodeReader = new QRCodeReader();
mCameraManager.startPreview();
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.getMessage());
mCameraManager.closeDriver();
}
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(TAG, "surfaceDestroyed");
mCameraManager.getCamera().setPreviewCallback(null);
mCameraManager.getCamera().stopPreview();
mCameraManager.getCamera().release();
mCameraManager.closeDriver();
}

// Called when camera take a frame
@Override
public void onPreviewFrame(byte[] data, Camera camera) {

PlanarYUVLuminanceSource source = mCameraManager.buildLuminanceSource(data, mPreviewWidth, mPreviewHeight);

HybridBinarizer hybBin = new HybridBinarizer(source);
BinaryBitmap bitmap = new BinaryBitmap(hybBin);

try {
Result result = mQRCodeReader.decode(bitmap);

// Notify We're found a QRCode
if (mOnQRCodeReadListener != null) {
// Transform resultPoints to View coordinates
PointF[] transformedPoints = transformToViewCoordinates(result.getResultPoints());
mOnQRCodeReadListener.onQRCodeRead(result.getText(), transformedPoints);
}

} catch (ChecksumException e) {
Log.d(TAG, "ChecksumException");
e.printStackTrace();
} catch (NotFoundException e) {
// Notify QR not found
if (mOnQRCodeReadListener != null) {
mOnQRCodeReadListener.QRCodeNotFoundOnCamImage();
}
} catch (FormatException e) {
Log.d(TAG, "FormatException");
e.printStackTrace();
} finally {
mQRCodeReader.reset();
}
}



@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.d(TAG, "surfaceChanged");

if (mHolder.getSurface() == null){
Log.e(TAG, "Error: preview surface does not exist");
return;
}

//preview_width = width;
//preview_height = height;

mPreviewWidth = mCameraManager.getPreviewSize().x;
mPreviewHeight = mCameraManager.getPreviewSize().y;


mCameraManager.stopPreview();
mCameraManager.getCamera().setPreviewCallback(this);
mCameraManager.getCamera().setDisplayOrientation(90); // Portrait mode

mCameraManager.startPreview();
}

/**
* Transform result to surfaceView coordinates
*
* This method is needed because coordinates are given in landscape camera coordinates.
* Now is working but transform operations aren't very explained
*
* TODO re-write this method explaining each single value
*
* @return a new PointF array with transformed points
*/
private PointF[] transformToViewCoordinates(ResultPoint[] resultPoints) {

PointF[] transformedPoints = new PointF[resultPoints.length];
int index = 0;
if (resultPoints != null){
float previewX = mCameraManager.getPreviewSize().x;
float previewY = mCameraManager.getPreviewSize().y;
float scaleX = this.getWidth()/previewY;
float scaleY = this.getHeight()/previewX;

for (ResultPoint point :resultPoints){
PointF tmppoint = new PointF((previewY- point.getY())*scaleX, point.getX()*scaleY);
transformedPoints[index] = tmppoint;
index++;
}
}
return transformedPoints;

}


/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
return true;
}
else if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)){
// this device has a front camera
return true;
}
else if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)){
// this device has any camera
return true;
}
else {
// no camera on this device
return false;
}
}

}

最佳答案

Surface 是生产者-消费者缓冲区队列安排的一部分。您的应用程序位于生产者端,对于 SurfaceView,系统合成器 (SurfaceFlinger) 位于消费者端。

一个表面一次只能有一个生产者。您已经将相机预览设置为制作者,因此无法同时连接 Canvas 来执行绘图。您没有看到失败,因为您正在使用 new Canvas 在真空中创建一个 Canvas -- 它没有连接到任何东西。 (通常您会使用 Surface#lockCanvas() 来获取与 Surface 关联的 Canvas。)

表面是一个完全独立的层,默认情况下合成在其他所有内容的后面,这意味着您可以使用自定义 View 在其之上绘制。不过,我认为您不需要额外的 View 对象——我相信您可以使用 SurfaceView 本身的“ View ”部分来实现,它应该具有透明背景。请参阅“custom drawing”文档。

如果您想要花哨一点,可以将相机预览提供给 OpenGL ES,但这可能超出了您的需要。 (一些示例 here。)此外,如果您想了解有关 Android 图形架构的更多信息,请参阅 this document。 .

关于android - 如何在surfaceview上绘制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26564984/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com