Android OpenGLES + Camera1 相机预览

这篇具有很好参考价值的文章主要介绍了Android OpenGLES + Camera1 相机预览。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

if (isCreate) {
return;
}
onCreatePre();
onClearColor();
onInitBlend();
onInitVertexBuffer();
onInitCoordinateBuffer();
onInitVbo();
onInitProgram();
onCreateAfter();
isCreate = true;
}

@Override
public void onChange(int width, int height) {
if (isChange) {
return;
}
onChangePre();
setWidth(width);
setHeight(height);
onViewport();
onInitFbo();
onChangeAfter();
isChange = true;
}

@Override
public void onDraw(int textureId) {
if (!onReadyToDraw()) {
return;
}
onDrawPre();
onClear();
onUseProgram();
onInitLocation();
onBindFbo();
onBindVbo();
onActiveTexture(textureId);
onEnableVertexAttributeArray();
onSetVertexData();
onSetCoordinateData();
onSetOtherData();
onDraw();
onDisableVertexAttributeArray();
onUnBind();
onDrawAfter();
}

@Override
public void onRelease() {
onDeleteProgram(program);
onDeleteShader(vertexShader);
onDeleteShader(fragShader);
onDeleteTexture(textureId);
onDeleteTexture(fboTextureId);
onDeleteFbo(fboId);
onDeleteVbo(vboId);
}

/**

  • 创建之前
    */
    public void onCreatePre() {

}

/**

  • 设置背景颜色
    */
    public void onClearColor() {
    GLES20.glClearColor(0, 0, 0, 1);
    }

/**

  • 是否启用混色
    */
    public boolean onEnableBlend() {
    return false;
    }

/**

  • 初始化混色
    */
    private void onInitBlend() {
    if (!onEnableBlend()) {
    return;
    }
    GLES20.glEnable(GLES20.GL_BLEND);
    GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
    }

/**

  • 初始化顶点坐标
    */
    public void onInitVertexBuffer() {
    vertexBuffer = OpenGLESUtils.getSquareVertexBuffer();
    }

/**

  • 初始化纹理坐标
    */
    public void onInitCoordinateBuffer() {
    if (isBindFbo) {
    coordinateBuffer = OpenGLESUtils.getSquareCoordinateReverseBuffer();
    } else {
    coordinateBuffer = OpenGLESUtils.getSquareCoordinateBuffer();
    }
    }

/**

  • 初始化Vbo
    */
    public void onInitVbo() {
    vboId = OpenGLESUtils.getVbo(vertexBuffer, coordinateBuffer);
    }

/**

  • 初始化Program
    */
    public void onInitProgram() {
    String vertexShaderCode = OpenGLESUtils.getShaderCode(context, vertexFilename);
    String fragShaderCode = OpenGLESUtils.getShaderCode(context, fragFilename);

vertexShader = OpenGLESUtils.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
fragShader = OpenGLESUtils.loadShader(GLES20.GL_FRAGMENT_SHADER, fragShaderCode);

program = OpenGLESUtils.linkProgram(vertexShader, fragShader);
}

/**

  • 创建之后
    */
    public void onCreateAfter() {

}

/**

  • 设置尺寸之前
    */
    public void onChangePre() {

}

/**

  • 设置窗口尺寸
    */
    public void onViewport() {
    GLES20.glViewport(0, 0, width, height);
    }

/**

  • 初始化Fbo
    */
    public void onInitFbo() {
    if (!isBindFbo) {
    return;
    }
    int[] fboData = OpenGLESUtils.getFbo(width, height);
    fboId = fboData[0];
    fboTextureId = fboData[1];
    }

/**

  • 设置尺寸之后
    */
    public void onChangeAfter() {

}

/**

  • 绘制之前的准备
    */
    public boolean onReadyToDraw() {
    return true;
    }

/**

  • 绘制之前
    */
    public void onDrawPre() {

}

/**

  • 清屏
    */
    public void onClear() {
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    }

/**

  • 使用Program
    */
    public void onUseProgram() {
    GLES20.glUseProgram(program);
    }

/**

  • 初始化着色器各个位置
    */
    public void onInitLocation() {
    aPosLocation = GLES20.glGetAttribLocation(program, “aPos”);
    aCoordinateLocation = GLES20.glGetAttribLocation(program, “aCoordinate”);
    uSamplerLocation = GLES20.glGetUniformLocation(program, “uSampler”);
    }

/**

  • 绑定Fbo
    */
    public void onBindFbo() {
    if (!isBindFbo) {
    return;
    }
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboId);
    GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
    GLES20.GL_TEXTURE_2D, fboTextureId, 0);
    GLES20.glViewport(0, 0, width, height);
    }

/**

  • 绑定Vbo
    */
    public void onBindVbo() {
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
    }

/**

  • 激活并绑定纹理
    */
    public void onActiveTexture(int textureId) {
    this.textureId = textureId;
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
    GLES20.glUniform1i(uSamplerLocation, 0);
    }

/**

  • 启用顶点坐标
    */
    public void onEnableVertexAttributeArray() {
    GLES20.glEnableVertexAttribArray(aPosLocation);
    GLES20.glEnableVertexAttribArray(aCoordinateLocation);
    }

/**

  • 设置顶点坐标
    */
    public void onSetVertexData() {
    GLES20.glVertexAttribPointer(aPosLocation, vertexSize, GLES20.GL_FLOAT, false, vertexStride, 0);
    }

/**

  • 设置纹理坐标
    */
    public void onSetCoordinateData() {
    GLES20.glVertexAttribPointer(aCoordinateLocation, coordinateSize, GLES20.GL_FLOAT, false, coordinateStride, vertexBuffer.limit() * 4);
    }

/**

  • 设置其他数据
    */
    public void onSetOtherData() {

}

/**

  • 绘制
    */
    public void onDraw() {
    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, vertexCount);
    }

/**

  • 禁用顶点坐标
    */
    public void onDisableVertexAttributeArray() {
    GLES20.glDisableVertexAttribArray(aPosLocation);
    GLES20.glDisableVertexAttribArray(aCoordinateLocation);
    }

/**

  • 解除绑定
    */
    public void onUnBind() {
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
    }

/**

  • 绘制之后
    */
    public void onDrawAfter() {

}

/**

  • 删除Program
    */
    public void onDeleteProgram(int program) {
    GLES20.glDeleteProgram(program);
    }

/**

  • 删除Shader
    */
    public void onDeleteShader(int shader) {
    GLES20.glDeleteShader(shader);
    }

/**

  • 删除纹理
    */
    public void onDeleteTexture(int textureId) {
    GLES20.glDeleteTextures(1, new int[]{textureId}, 0);
    }

/**

  • 删除Fbo
    */
    public void onDeleteFbo(int fboId) {
    GLES20.glDeleteFramebuffers(1, new int[]{fboId}, 0);
    }

/**

  • 删除Vbo
    */
    public void onDeleteVbo(int vboId) {
    GLES20.glDeleteBuffers(1, new int[]{vboId}, 0);
    }

public Context getContext() {
return context;
}

public void setContext(Context context) {
this.context = context;
}

public FloatBuffer getVertexBuffer() {
return vertexBuffer;
}

public void setVertexBuffer(FloatBuffer vertexBuffer) {
this.vertexBuffer = vertexBuffer;
}

public FloatBuffer getCoordinateBuffer() {
return coordinateBuffer;
}

public void setCoordinateBuffer(FloatBuffer coordinateBuffer) {
this.coordinateBuffer = coordinateBuffer;
}

public int getVertexSize() {
return vertexSize;
}

public void setVertexSize(int vertexSize) {
this.vertexSize = vertexSize;
}

public int getCoordinateSize() {
return coordinateSize;
}

public void setCoordinateSize(int coordinateSize) {
this.coordinateSize = coordinateSize;
}

public int getVertexStride() {
return vertexStride;
}

public void setVertexStride(int vertexStride) {
this.vertexStride = vertexStride;
}

public int getCoordinateStride() {
return coordinateStride;
}

public void setCoordinateStride(int coordinateStride) {
this.coordinateStride = coordinateStride;
}

public int getVertexCount() {
return vertexCount;
}

public void setVertexCount(int vertexCount) {
this.vertexCount = vertexCount;
}

public int getCoordinateCount() {
return coordinateCount;
}

public void setCoordinateCount(int coordinateCount) {
this.coordinateCount = coordinateCount;
}

public int getProgram() {
return program;
}

public void setProgram(int program) {
this.program = program;
}

public int getFboTextureId() {
return fboTextureId;
}

public void setFboTextureId(int fboTextureId) {
this.fboTextureId = fboTextureId;
}

public int getFboId() {
return fboId;
}

public void setFboId(int fboId) {
this.fboId = fboId;
}

public int getVboId() {
return vboId;
}

public void setVboId(int vboId) {
this.vboId = vboId;
}

public String getVertexFilename() {
return vertexFilename;
}

public void setVertexFilename(String vertexFilename) {
this.vertexFilename = vertexFilename;
}

public String getFragFilename() {
return fragFilename;
}

public void setFragFilename(String fragFilename) {
this.fragFilename = fragFilename;
}

public int getWidth() {
return width;
}

public void setWidth(int width) {
this.width = width;
}

public int getHeight() {
return height;
}

public void setHeight(int height) {
this.height = height;
}

public boolean isBindFbo() {
return isBindFbo;
}

public void setBindFbo(boolean bindFbo) {
isBindFbo = bindFbo;
}

public int getPosLocation() {
return aPosLocation;
}

public void setPosLocation(int aPosLocation) {
this.aPosLocation = aPosLocation;
}

public int getCoordinateLocation() {
return aCoordinateLocation;
}

public void setCoordinateLocation(int aCoordinateLocation) {
this.aCoordinateLocation = aCoordinateLocation;
}

public int getSamplerLocation() {
return uSamplerLocation;
}

public void setSamplerLocation(int uSamplerLocation) {
this.uSamplerLocation = uSamplerLocation;
}

public boolean isCreate() {
return isCreate;
}

public void setCreate(boolean create) {
isCreate = create;
}

public boolean isChange() {
return isChange;
}

public void setChange(boolean change) {
isChange = change;
}

public BaseRenderBean getRenderBean() {
return renderBean;
}

public void setRenderBean(BaseRenderBean renderBean) {
this.renderBean = renderBean;
}

public void updateRenderBean(BaseRenderBean renderBean) {
setRenderBean(renderBean);
}
}

代码有点长,但是里面尽可能地考虑到了渲染和扩展的需求

顶点着色器 vertex.frag

attribute vec4 aPos;
attribute vec2 aCoordinate;
varying vec2 vCoordinate;
void main(){
vCoordinate = aCoordinate;
gl_Position = aPos;
}

片元着色器 frag.frag

precision mediump float;
uniform sampler2D uSampler;
varying vec2 vCoordinate;
void main(){
gl_FragColor = texture2D(uSampler, vCoordinate);
}

注意到,里面有用到一个工具类OpenGLESUtils和实体类BaseRenderBean具体就不贴出来了,可以到Github上查看

四、BaseOesRender

注意到,BaseRender里面绑定的纹理是2D纹理,而如果想实现相机预览,则需要使用Oes纹理,所以需要创建一个BaseOesRender为相机做渲染

package com.yk.media.opengles.render.base;

import android.content.Context;
import android.graphics.SurfaceTexture;
import android.opengl.GLES11Ext;
import android.opengl.GLES20;

import com.yk.media.utils.OpenGLESUtils;

public class BaseOesRender extends BaseRender {
/**

  • oes纹理id
    */
    private int oesTextureId;

/**

  • 顶点变换矩阵位置
    */
    private int uMatrixLocation;

/**

  • 纹理变换矩阵位置
    */
    private int uOesMatrixLocation;

/**

  • oes尺寸
    */
    private int oesW = -1;
    private int oesH = -1;

/**

  • 顶点变换矩阵
    */
    private float[] mMVPMatrix = new float[16];

/**

  • 纹理变换矩阵
    */
    private float[] mOesMatrix = {
    1, 0, 0, 0,
    0, 1, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, 1
    };

/**

  • 是否准备好绘制
    */
    private boolean isReadyToDraw = false;

/**

  • SurfaceTexture
    */
    private SurfaceTexture surfaceTexture;

/**

  • SurfaceTexture回调
    */
    private OnSurfaceTextureListener onSurfaceTextureListener;

public BaseOesRender(Context context) {
super(context, “render/base/oes/vertex.frag”, “render/base/oes/frag.frag”);
setBindFbo(true);
oesTextureId = OpenGLESUtils.getOesTexture();
}

@Override
public void onInitCoordinateBuffer() {
setCoordinateBuffer(OpenGLESUtils.getSquareCoordinateBuffer());
}

@Override
public boolean onReadyToDraw() {
if (!isReadyToDraw) {
if (onSurfaceTextureListener != null) {
if (surfaceTexture != null) {
surfaceTexture.release();
surfaceTexture = null;
}
surfaceTexture = new SurfaceTexture(oesTextureId);
onSurfaceTextureListener.onSurfaceTexture(surfaceTexture);
isReadyToDraw = true;
} else if (surfaceTexture != null) {
surfaceTexture.attachToGLContext(oesTextureId);
isReadyToDraw = true;
} else {
return false;
}
}
return oesW != -1 && oesH != -1;
}

@Override
public void onDrawPre() {
super.onDrawPre();
mMVPMatrix = OpenGLESUtils.getMatrix(getWidth(), getHeight(), oesW, oesH);

surfaceTexture.updateTexImage();

float[] oesMatrix = new float[16];
surfaceTexture.getTransformMatrix(oesMatrix);
if (!OpenGLESUtils.isIdentityM(oesMatrix)) {
mOesMatrix = oesMatrix;
}
}

@Override
public void onInitLocation() {
super.onInitLocation();
uMatrixLocation = GLES20.glGetUniformLocation(getProgram(), “uMatrix”);
uOesMatrixLocation = GLES20.glGetUniformLocation(getProgram(), “uOesMatrix”);
}

@Override
public void onActiveTexture(int textureId) {
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId);
GLES20.glUniform1i(getSamplerLocation(), 0);
}

@Override
public void onSetOtherData() {
super.onSetOtherData();
GLES20.glUniformMatrix4fv(uMatrixLocation, 1, false, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(uOesMatrixLocation, 1, false, mOesMatrix, 0);
}

@Override
public void onRelease() {
super.onRelease();
onDeleteTexture(oesTextureId);
}

/**

  • 绘制
    */
    public void onDrawSelf() {
    super.onDraw(oesTextureId);
    }

/**

  • 设置oes尺寸
    */
    public void setOesSize(int width, int height) {
    oesW = width;
    oesH = height;
    }

/**

  • 设置SurfaceTexture
    */
    public void setSurfaceTexture(SurfaceTexture surfaceTexture) {
    this.surfaceTexture = surfaceTexture;
    isReadyToDraw = false;
    }

/**

  • 设置SurfaceTexture回调
    */
    public void setOnSurfaceTextureListener(OnSurfaceTextureListener onSurfaceTextureListener) {
    this.onSurfaceTextureListener = onSurfaceTextureListener;
    isReadyToDraw = false;
    }
    }

顶点着色器 vertex.frag

attribute vec4 aPos;
attribute vec4 aCoordinate;
uniform mat4 uMatrix;
uniform mat4 uOesMatrix;
varying vec2 vCoordinate;
void main(){
vCoordinate = (uOesMatrix * aCoordinate).xy;
gl_Position = uMatrix * aPos;
}

片元着色器 frag.frag

#extension GL_OES_EGL_image_external:require
precision mediump float;
uniform samplerExternalOES uSampler;
varying vec2 vCoordinate;
void main(){
gl_FragColor = texture2D(uSampler, vCoordinate);
}

BaseOesRender是继承BaseRender

加入了一些变量

  • oesWoesH

用于计算矩阵

  • mMVPMatrix

通过width、height、oesW、oesH计算的矩阵

  • mOesMatrix

通过SurfaceTexture获取的矩阵

  • isReadyToDraw

是否准备好渲染

重写了一些方法

  • onInitCoordinateBuffer

BaseOesRender需要绑定FBO,所有纹理坐标需要设置好,不然会出现倒立

  • onReadyToDraw

此处做一些SurfaceTexture绑定纹理和回调

  • onDrawPre

此处做矩阵相关的计算

  • onInitLocation

获取矩阵的Location

  • onActiveTexture

前面有说到,预览相机使用的是SurfaceTexture,所有需要修改绑定为Oes纹理

  • onSetOtherData

此处传入矩阵的数据

  • onRelease

此处做一些释放资源的工作

OnSurfaceTextureListener

public interface OnSurfaceTextureListener {
/**

  • SurfaceTexture回调
    */
    void onSurfaceTexture(SurfaceTexture surfaceTexture);
    }

onDrawSelf

public void onDrawSelf() {
super.onDraw(oesTextureId);
}

因为oesTextureId是内部创建的,故渲染的话,直接调用super.onDraw(oesTextureId),方便外部调用

五、OesRender

前面有说过,EGLTextureViewsetRenderer只能调用一次,故才会创建BaseRender,现在来创建Renderer调度者

public class OesRender implements Renderer {
private Context context;

/**

  • 输入(FBO保存数据)
    */
    private BaseOesRender inputRender;

/**

  • 输出(屏幕显示)
    */
    private BaseRender outputRender;

private int width;
private int height;

public OesRender(Context context) {
this.context = context;
inputRender = new BaseOesRender(context);
outputRender = new BaseRender(context);
}

@Override
public void onCreate() {
inputRender.onCreate();
outputRender.onCreate();
}

@Override
public void onChange(int width, int height) {
this.width = width;
this.height = height;
inputRender.onChange(width, height);
outputRender.onChange(width, height);
}

@Override
public void onDraw() {
inputRender.onDrawSelf();
outputRender.onDraw(inputRender.getFboTextureId());
}

public void setOesSize(int width, int height) {
inputRender.setOesSize(width, height);
}

public void setOnSurfaceTextureListener(OnSurfaceTextureListener onSurfaceTextureListener) {
inputRender.setOnSurfaceTextureListener(onSurfaceTextureListener);
}

public void setSurfaceTexture(SurfaceTexture surfaceTexture) {
inputRender.setSurfaceTexture(surfaceTexture);
}

public int getFboTextureId() {
return inputRender.getFboTextureId();
}
}

注意到,OesRender里面,有两个Render

  • BaseOesRender

渲染Oes纹理,并绑定了Fbo

  • BaseRender

做为输出显示

六、CameraView

完成了上面的工作,接下来就可以进入正题,如何在Android中,使用OpenGLES + Camera1实现相机预览?

既然我们已经完成了“容器”和Renderer的创建,那么下面的工作就比较轻松

还记得上一章的Android Camera1相机预览,不记得的同学可以点击链接进入查看,因为接下来需要用到上一章介绍的CameraManager

public class CameraView extends EGLTextureView implements OnCameraListener {
private final CameraManager cameraManager = new CameraManager();

private Activity activity;

public OesRender render;

public CameraView(Context context) {
this(context, null);
}

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

private void init(Context context) {
setEGLContextClientVersion(2);
render = new OesRender(context);
setRenderer(render);
setRenderMode(EGLTextureView.RENDERMODE_WHEN_DIRTY);

activity = (Activity) context;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

Android OpenGLES + Camera1 相机预览,程序员,android,数码相机

Android OpenGLES + Camera1 相机预览,程序员,android,数码相机

Android OpenGLES + Camera1 相机预览,程序员,android,数码相机

Android OpenGLES + Camera1 相机预览,程序员,android,数码相机

Android OpenGLES + Camera1 相机预览,程序员,android,数码相机

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

Android OpenGLES + Camera1 相机预览,程序员,android,数码相机

最后

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

上面分享的百度、腾讯、网易、字节跳动、阿里等公司2021年的高频面试题,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,上面只是以图片的形式给大家展示一部分。

【Android思维脑图(技能树)】

知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。

Android OpenGLES + Camera1 相机预览,程序员,android,数码相机

【Android高级架构视频学习资源】

**Android部分精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!文章来源地址https://www.toymoban.com/news/detail-848831.html

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

.(img-8pVlIYcc-1711756366555)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

Android OpenGLES + Camera1 相机预览,程序员,android,数码相机

最后

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

上面分享的百度、腾讯、网易、字节跳动、阿里等公司2021年的高频面试题,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,上面只是以图片的形式给大家展示一部分。

【Android思维脑图(技能树)】

知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。

[外链图片转存中…(img-afVEsosx-1711756366556)]

【Android高级架构视频学习资源】

**Android部分精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

到了这里,关于Android OpenGLES + Camera1 相机预览的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android 使用Camera2 API 和 GLSurfaceView实现相机预览

    GLSurfaceView 和 SurfaceView 是 Android 中用于显示图像的两个视图类,它们在实现方式和使用场景上有一些区别。 实现方式:GLSurfaceView 基于 OpenGL ES 技术实现,可以通过 OpenGL ES 渲染图像。而 SurfaceView 则是通过基于线程的绘制方式,可以在独立的线程中进行绘制操作。 性能:由于

    2024年02月09日
    浏览(47)
  • Android之camera1和2的简单使用

    前言 Android Framework提供Camera API来实现拍照与录制视频的功能,目前Android有三类API, Camera 此类是用于控制设备相机的旧版 API,现已弃用,在Android5.0以下使用 Camera2 此软件包是用于控制设备相机的主要 API,Android5.0以上使用 CameraX 基于Camera 2 API封装,简化了开发流程,并增加

    2024年02月09日
    浏览(45)
  • android camera系列(Camera1、Camera2、CameraX)的使用以及输出的图像格式

    1.1.1、布局 1.1.2、实现预览 Camera.open() 打开摄像头 setPreviewDisplay 设置预览展示的控件 startPreview 开始预览 发现预览是横着的,需要使用 setDisplayOrientation 调整预览图像的方向 1.1.3、获取摄像头的原始数据 setPreviewCallback 设置预览数据的回调 2560*1440 默认返回图像的分辨率 Image

    2024年02月21日
    浏览(53)
  • OpenGLES:glReadPixels()获取相机GLSurfaceView预览数据并保存

    Android 现行的 Camera API2 机制可以通过 onImageAvailable(ImageReader reader) 回调从底层获取到 Jpeg、Yuv 和 Raw 三种格式的 Image ,然后通过保存 Image 实现拍照功能,但是却并没有 Api 能直接在上层直接拿到预览Surface上的实显数据。 Android Camera 预览的实现是上层下发 Surface 到 CameraHAL ,由

    2024年02月03日
    浏览(37)
  • Android相机开发实战,Android程序员必看

    由于需求不同,所以选择的方案固然也不同,至于第二种调用系统相机,这里就不过多讲解了,使用Intent对象设置一个Action动作即可,跳转时使用startActivityForResult,然后在onActivityResult处理相关数据便可,关键代码: intent.setAction(“android.media.action.STILL_IMAGE_CAMERA”); 至于使用

    2024年04月15日
    浏览(48)
  • 在基于 Android 相机预览的 CV 应用程序中使用 OpenCL

    组装和配置 Android OpenCL SDK。 示例的 JNI 部分依赖于标准 Khornos OpenCL 标头,以及 OpenCL 和 libOpenCL.so 的C++包装器。标准 OpenCL 标头可以从 OpenCV 存储库中的第三方目录或 Linux 发行版包中复制。C++包装器在Github上的官方Khronos存储库中可用。按以下方式将头文件复制到专用目录:

    2024年01月21日
    浏览(49)
  • 安卓camera1设置自动连续对焦

    camera 1实现的控制摄像头拍照功能. adb控制自动拍照,发现近点时拍照很模糊,需要自动连续对焦. mCamera.autoFocus(null) 这个接口只能实现单次对焦.不适用. 作者:帅得不敢出门

    2024年02月14日
    浏览(54)
  • Android Camera预览画面变形问题

    csdn 安卓camera1在预览时,预览画面看起来被拉伸了. 如图,圆形的盖子,变成椭圆形了. 默认流程,如下为大致的打开摄像头并进行预览显示的代码 网上大部分的解决方法(实测不一定有效) 原理是遍历摄像头分辨率,找到与当前屏幕契合的分辨率,并设置为预览大小. 如下

    2024年02月13日
    浏览(75)
  • Android Camera2-预览、拍照、录像流程

    一、Camera2实现预览、拍照、录像三大基础功能的流程框架图 Camera2关键几个类: CameraManager 管理手机上的所有摄像头设备。管理手机上的所有摄像头设备,它的作用主要是获取摄像头列表和打开(openCamera)指定的摄像头。 它其实是一个系统服务,通过getSystemService(Context.CAM

    2024年02月16日
    浏览(54)
  • Android Camera2(1)-Camera2在textureView中的预览和拍照

    解释上诉示意图,假如想要同时拍摄两张不同尺寸的图片,并且在拍摄过程中闪光灯必须亮起来。整个拍摄流程如下: 创建一个用于从 Pipeline 获取图片的 CaptureRequest。 修改 CaptureRequest 的闪光灯配置,让闪光灯在拍照过程中亮起来。 创建两个不同尺寸的 Surface 用于接收图片

    2024年02月05日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包