如何在 Android 中使用 CameraX 显示负片模式预览?
How can I display a negative mode preview with CameraX in Android?
正在学习CameraXAPI,CameraXBasic是office示例代码
CameraFragment.kt 在 CameraXBasic 项目中显示真实相机预览。
现在希望显示负片模式预览。我该如何使用 CameraX API?有示例代码吗?
CameraFragment.kt
private lateinit var viewFinder: TextureView
private fun bindCameraUseCases() {
// Get screen metrics used to setup camera for full screen resolution
val metrics = DisplayMetrics().also { viewFinder.display.getRealMetrics(it) }
val screenAspectRatio = Rational(metrics.widthPixels, metrics.heightPixels)
Log.d(TAG, "Screen metrics: ${metrics.widthPixels} x ${metrics.heightPixels}")
// Set up the view finder use case to display camera preview
val viewFinderConfig = PreviewConfig.Builder().apply {
setLensFacing(lensFacing)
// We request aspect ratio but no resolution to let CameraX optimize our use cases
setTargetAspectRatio(screenAspectRatio)
// Set initial target rotation, we will have to call this again if rotation changes
// during the lifecycle of this use case
setTargetRotation(viewFinder.display.rotation)
}.build()
// Use the auto-fit preview builder to automatically handle size and orientation changes
preview = AutoFitPreviewBuilder.build(viewFinderConfig, viewFinder)
....
CameraX.bindToLifecycle(
viewLifecycleOwner, preview, imageCapture, imageAnalyzer)
}
这是一个 android.media.effect.Effect
being applied to the SurfaceTexture
(the PreviewConfig
does not have any such properties). See EffectFactory.EFFECT_NEGATIVE:
/**
* Applies negative film effect on image.<br/>
* Parameters: scale (float): the degree of film grain.
**/
public final static String EFFECT_NEGATIVE = "android.media.effect.effects.NegativeEffect";
Here 也有解释(Kotlin 和 Java 文档的组织方式不同)。
但是,您可能需要使用自己的 SurfaceTexture
,因为否则很难获得 GLContext。这个例子几乎可以工作,但是 texture.attachToGLContext()
:
private EffectContext fxContext = null;
private EffectFactory fxFactory = null;
private Effect fx = null;
protected void applyNegativeEffect(SurfaceTexture texture, int width, int height) {
if(this.fxContext == null) {
// texture.attachToGLContext(texture.mSurfaceTexture);
this.fxContext = EffectContext.createWithCurrentGlContext();
}
if(this.fxFactory == null) {
this.fxFactory = this.fxContext.getFactory();
}
if(this.fx == null) {
this.fx = fxFactory.createEffect(EffectFactory.EFFECT_NEGATIVE);
this.fx.setParameter("scale", 1.0f);
// this.fx.apply(0, width, height, 0);
}
}
但是 SurfaceTexture
(其中 long mSurfaceTexture
需要公开)显示:
/**
* These fields are used by native code, do not access or modify.
**/
private long mSurfaceTexture;
在 GLSurfaceView
上设置着色器可能更容易完成:
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "varying vec2 vTextureCoord;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ "void main() {\n"
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " float colorR = (1.0 - color.r) / 1.0;\n"
+ " float colorG = (1.0 - color.g) / 1.0;\n"
+ " float colorB = (1.0 - color.b) / 1.0;\n"
+ " gl_FragColor = vec4(colorR, colorG, colorB, color.a);\n"
+ "}\n";
还有一个 camera2 example 用于 OpenGL ES 预览。
从 CameraX 抽象中获取 GLContext 是实际问题,因为需要使用自定义 OpenGL 预览构建 androidx.camera.core,以便应用着色器 - 或获取 input/ouput texId
.
更新:
If you require direct access to the SurfaceTexture
, such as to perform OpenGL rendering, see Manually create a SurfaceTexture. In these cases, pass in a SurfaceTexture
to a Preview
object using Preview.PreviewSurfaceProvider
.
查看问题 #146957342,Futures.immediateFuture(surface)
不再有效。
正在学习CameraXAPI,CameraXBasic是office示例代码
CameraFragment.kt 在 CameraXBasic 项目中显示真实相机预览。
现在希望显示负片模式预览。我该如何使用 CameraX API?有示例代码吗?
CameraFragment.kt
private lateinit var viewFinder: TextureView
private fun bindCameraUseCases() {
// Get screen metrics used to setup camera for full screen resolution
val metrics = DisplayMetrics().also { viewFinder.display.getRealMetrics(it) }
val screenAspectRatio = Rational(metrics.widthPixels, metrics.heightPixels)
Log.d(TAG, "Screen metrics: ${metrics.widthPixels} x ${metrics.heightPixels}")
// Set up the view finder use case to display camera preview
val viewFinderConfig = PreviewConfig.Builder().apply {
setLensFacing(lensFacing)
// We request aspect ratio but no resolution to let CameraX optimize our use cases
setTargetAspectRatio(screenAspectRatio)
// Set initial target rotation, we will have to call this again if rotation changes
// during the lifecycle of this use case
setTargetRotation(viewFinder.display.rotation)
}.build()
// Use the auto-fit preview builder to automatically handle size and orientation changes
preview = AutoFitPreviewBuilder.build(viewFinderConfig, viewFinder)
....
CameraX.bindToLifecycle(
viewLifecycleOwner, preview, imageCapture, imageAnalyzer)
}
这是一个 android.media.effect.Effect
being applied to the SurfaceTexture
(the PreviewConfig
does not have any such properties). See EffectFactory.EFFECT_NEGATIVE:
/**
* Applies negative film effect on image.<br/>
* Parameters: scale (float): the degree of film grain.
**/
public final static String EFFECT_NEGATIVE = "android.media.effect.effects.NegativeEffect";
Here 也有解释(Kotlin 和 Java 文档的组织方式不同)。
但是,您可能需要使用自己的 SurfaceTexture
,因为否则很难获得 GLContext。这个例子几乎可以工作,但是 texture.attachToGLContext()
:
private EffectContext fxContext = null;
private EffectFactory fxFactory = null;
private Effect fx = null;
protected void applyNegativeEffect(SurfaceTexture texture, int width, int height) {
if(this.fxContext == null) {
// texture.attachToGLContext(texture.mSurfaceTexture);
this.fxContext = EffectContext.createWithCurrentGlContext();
}
if(this.fxFactory == null) {
this.fxFactory = this.fxContext.getFactory();
}
if(this.fx == null) {
this.fx = fxFactory.createEffect(EffectFactory.EFFECT_NEGATIVE);
this.fx.setParameter("scale", 1.0f);
// this.fx.apply(0, width, height, 0);
}
}
但是 SurfaceTexture
(其中 long mSurfaceTexture
需要公开)显示:
/**
* These fields are used by native code, do not access or modify.
**/
private long mSurfaceTexture;
在 GLSurfaceView
上设置着色器可能更容易完成:
String shader = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "varying vec2 vTextureCoord;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ "void main() {\n"
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " float colorR = (1.0 - color.r) / 1.0;\n"
+ " float colorG = (1.0 - color.g) / 1.0;\n"
+ " float colorB = (1.0 - color.b) / 1.0;\n"
+ " gl_FragColor = vec4(colorR, colorG, colorB, color.a);\n"
+ "}\n";
还有一个 camera2 example 用于 OpenGL ES 预览。
从 CameraX 抽象中获取 GLContext 是实际问题,因为需要使用自定义 OpenGL 预览构建 androidx.camera.core,以便应用着色器 - 或获取 input/ouput texId
.
更新:
If you require direct access to the
SurfaceTexture
, such as to perform OpenGL rendering, see Manually create a SurfaceTexture. In these cases, pass in aSurfaceTexture
to aPreview
object usingPreview.PreviewSurfaceProvider
.
查看问题 #146957342,Futures.immediateFuture(surface)
不再有效。