【问题标题】:Can I generate 1:1 pixel data within an Android application?我可以在 Android 应用程序中生成 1:1 像素数据吗?
【发布时间】:2022-06-10 19:29:10
【问题描述】:

我希望检查 Android 显示屏是否显示正确的色调曲线。如果我生成一个由 50% 灰色包围的黑白交替线的补丁,并且两个灰度级匹配,则色调曲线的第一站是正确的。然后,我可以生成一个带有交替的黑色和 50% 灰色线的补丁,并被 25% 的灰色包围,依此类推。

我可以找到当前的显示尺寸。我可以制作适合的 RGB 栅格数据。如果需要,我可以使用 2x2 像素复制来制作图像,例如视网膜显示器。但是我看不到如何在不冒险调整大小的情况下将栅格数据显示出来。

我所描述的特定图像可能是使用哑光纹理或其他技巧生成的。我还有其他更复杂的视觉测试图像,我目前在另一个程序中生成为光栅数据。所以,我真的在寻找可以获取自定义 RGB 数据矩形并将其粘贴到屏幕上的东西。

也许这个工具就在 Android Studio 中,正盯着我看。但是我看不到。

(次日)

我找到了 Bitmap 类。这可能是我想要的。

(几天后)

没有。我仍然不在那里。我可以生成一个 ImageView。我想生成一个具有交替黑白线的位图数据区域。

我的实验在 Kotlin 中。

我发现以像素为单位获取 ImageView 尺寸的问题。布局有效地以另一种方式工作:您说定义布局,库为您计算尺寸和调整大小参数。 resize 并且在布局视图之前通常无法计算大小。例如看...

Why does setting view dimensions asynchronously not work in Kotlin?

有一个使用 viewTreeObserver() 的 Java 解决方案。我可以使用它在 Toast 中获取以像素为单位的尺寸,但我无法将值从观察者中获取到上下文中。

确切的像素大小不是这里的问题。我可以将 ImageView 设为显示高度和宽度的 50%,并将像素数计算为屏幕尺寸的一小部分。这对于灰色边框和条纹块的总体布局来说已经足够准确了。我可以使用 来布置画布,然后强制视图以 1:1 的比例适应它。

感觉这些工具不应该以这种方式工作。有没有我想念的完全不同的方法?

后记:

有办法做到这一点...

   override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityToneBinding.inflate(layoutInflater)
    setContentView(binding.root)

    stripeColour = lastColour
    step = resources.displayMetrics.density

    // Initialize the ImageView
    stripeView = findViewById(R.id.stripeView)

    stripeView.doOnLayout {
        val myBitmap = Bitmap.createBitmap(
            it.measuredWidth,
            it.measuredHeight,
            Bitmap.Config.ARGB_8888
        )
        val myCanvas = Canvas(myBitmap)
        val xMax = it.measuredWidth.toFloat()
        val yMax = it.measuredHeight.toFloat()
        val myPaint = Paint()
        myPaint.isAntiAlias = false
        myPaint.color = Color.rgb(0, 0, 0)
        var y = 0.0f
        while (y < yMax) {
            myCanvas.drawRect(0.0f, y, xMax, y+step, myPaint)
            y += 2.0f*step
        }
        stripeView.setImageBitmap(myBitmap)
    }

黑色条纹是不透明的,我可以通过更改背景来更新其他条纹。条纹都有很好的锐利边缘,没有我在边缘得到的插值。这是针对我的特定问题的一个相当具体的解决方案,但它似乎工作正常。

如果您想自己尝试,请注意:我现在看到一些我不理解的东西。似乎明暗条纹平均比应有的亮,尤其是深色。当我测量大色块时,显示器的色调曲线似乎很符合 sRGB 标准,但明暗条纹的总和并不应该是这样。所以,这不是我希望的色调曲线的测试。

【问题讨论】:

  • 您应该向代码展示您是如何绘制图像的。通常您创建一个位图并可能将其放在画布上,请参阅:developer.android.com/guide/topics/graphics/drawables
  • 我会展示我的代码,但还没有。我可以在外部程序中制作 PNG 文件,但我想用不同的随机变化来生成它们,这样人们就不会太习惯于某个特定的文件。但是,我确实对 ImageView 类进行了挖掘,并找到了 Bitmap,所以我再去一次。谢谢。

标签: android image raster


【解决方案1】:

一旦我找到了“位图”和“画布”这两个术语,我就找到了合适的工具,但很难看出如何将它们串在一起以制作出有效的东西。这是一个对我有帮助的简单练习...

https://developer.android.com/codelabs/advanced-android-kotlin-training-canvas#10

忽略设置 SYSTEM_UI_FLAG_FULLSCREEN 的位。这不再受支持。还有其他方法可以做同样的事情,但这个例子没有它也能很好地工作。

【讨论】:

    【解决方案2】:

    如果您想以像素分辨率渲染某些东西,请在 doOnLayout() 调用中进行渲染。然后,您可以获得视图的高度和宽度。 ImageView 布局的宽度和高度为 0dp (match_constraints)。我还没有完全到那里:我的双高条纹图案仍在被插值。

    class MainActivity : Activity() {
    // Here are all the objects(instances)
    // of classes that we need to do some drawing
    lateinit var myImageView: ImageView
    var background = Color.rgb(180, 180, 180)
    var darkStripe = Color.rgb(0, 0, 0)
    var lightStripe = Color.rgb(255, 255, 255)
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    
        // Initialize the ImageView
        myImageView = findViewById(R.id.imageView)
        myImageView.doOnLayout {
            val myBitmap = Bitmap.createBitmap(
                it.measuredWidth,
                it.measuredHeight,
                Bitmap.Config.ARGB_8888
            )
            val w = (it.measuredWidth/4).toFloat()
            val h = (it.measuredHeight/4).toFloat()
    
            val myCanvas = Canvas(myBitmap)
            myCanvas.drawColor(background)
    
            // Toast.makeText(applicationContext, w.toString(), Toast.LENGTH_SHORT).show()
            val tex = createBitmap(
                intArrayOf(lightStripe, lightStripe, darkStripe, darkStripe),
                0, 1, 1, 4, Bitmap.Config.ARGB_8888
            )
            val shader: Shader = BitmapShader(tex, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT)
            val myPaint = Paint()
            myPaint.setAntiAlias(false)
            myPaint.shader = shader
            myCanvas.drawRect(w, h,w*3.0f,h*3.0f, myPaint)
    
            myImageView.setImageBitmap(myBitmap)
        }
    }
    

    }

    这是一个修改后的版本,它在没有硬编码 3.0 值的情况下给出了我的清晰条纹......

        step = resources.displayMetrics.density
    
        // Initialize the ImageView
        stripeView = findViewById(R.id.stripeView)
    
        stripeView.doOnLayout {
            val myBitmap = Bitmap.createBitmap(
                it.measuredWidth,
                it.measuredHeight,
                Bitmap.Config.ARGB_8888
            )
            val myCanvas = Canvas(myBitmap)
            val xMax = it.measuredWidth.toFloat()
            val yMax = it.measuredHeight.toFloat()
            val myPaint = Paint()
            myPaint.isAntiAlias = false
            myPaint.color = Color.rgb(0, 0, 0)
            var y = 0.0f
            while (y < yMax) {
                myCanvas.drawRect(0.0f, y, xMax, y+step, myPaint)
                y += 2.0f*step
            }
            stripeView.setImageBitmap(myBitmap)
        }
    

    我将黑色条纹绘制为不透明的矩形。背景颜色给出了其他条纹。这意味着我可以更新条纹颜色而无需重绘。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-03
      • 2011-09-28
      • 2019-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多