在Android平台上,用扫描线填充指定的区域(当前仅支持凸形)后,我发现轮廓的边缘有一些未填充的间隙。
它看起来像这样:
它们主要集中在填充区域的右上角,并且在左上角有少量空白。实现代码如下:
class Fill02 : MainActivity.IFill {
private val pixel = ByteBuffer.allocate(3)
// Color to be filled
private val color = ByteArray(3)
private var xScanLeft = 0
private var xScanRight = 0
override fun fill(x: Int, y: Int, minX: Int, maxX: Int, minY: Int, maxY: Int, callback: MainActivity.IFillCallback) {
val surfaceWidth = maxX - minX
val surfaceHeight = maxY - minY
GLES20.glReadPixels(x, y, 1, 1, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, pixel)
pixel.position(0)
color[0] = pixel.get(0)
color[1] = pixel.get(1)
color[2] = pixel.get(2)
var xLeft = x
var xRight = x
while (isSameColor(xLeft - 1, y) && 0 < xLeft) {
xLeft--
}
while (isSameColor(xRight + 1, y) && xRight < surfaceWidth) {
xRight++
}
callback.fullCallback(xLeft.toFloat(), surfaceHeight - y.toFloat())
callback.fullCallback(xRight.toFloat(), surfaceHeight - y.toFloat())
var yUp = y
xScanLeft = xLeft
xScanRight = xRight
while (xScanLeft < xScanRight && yUp < maxY) {
scanLine(++yUp, minX, maxX, surfaceHeight, callback)
}
var yDown = y
xScanLeft = xLeft
xScanRight = xRight
while (xScanLeft < xScanRight && minY < yDown) {
scanLine(--yDown, minX, maxX, surfaceHeight, callback)
}
}
private fun scanLine(y: Int, minX: Int, maxX: Int, surfaceHeight: Int, callback: MainActivity.IFillCallback) {
if (isSameColor(xScanLeft, y)) {
while (minX < xScanLeft && isSameColor(xScanLeft - 1, y)) {
xScanLeft--
}
} else {
while (xScanLeft < xScanRight && !isSameColor(++xScanLeft, y)) {
}
}
if (isSameColor(xScanRight, y)) {
while (xScanRight < maxX && isSameColor(xScanRight + 1, y)) {
xScanRight++
}
} else {
while (xScanLeft < xScanRight && !isSameColor(--xScanRight, y)) {
}
}
callback.fullCallback((xScanLeft).toFloat(), (surfaceHeight - y).toFloat())
callback.fullCallback((xScanRight).toFloat(), (surfaceHeight - y).toFloat())
}
private fun isSameColor(x: Int, y: Int): Boolean {
GLES20.glReadPixels(x, y, 1, 1, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, pixel)
pixel.position(0)
return (color[0] == pixel.get(0) &&
color[1] == pixel.get(1) &&
color[2] == pixel.get(2))
}
}
callback.fullCallback
方法代码如下:
override fun fullCallback(x: Float, y: Float) {
buffer.put((x - mSurfaceSize.x) / mSurfaceSize.x)
buffer.put((mSurfaceSize.y - y) / mSurfaceSize.y)
}
override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
mSurfaceSize.set(width / 2.0f, height / 2.0f)
GLES20.glViewport(0, 0, width, height)
}
顶点着色器代码如下:
attribute vec2 vPosition;
uniform float vPointSize;
void main() {
gl_PointSize = vPointSize;
gl_Position = vec4(vPosition, 0.0, 1.0);
}
完整的源代码位于GitHub上。
请问是什么问题?
附件1:
修改代码后,图片已导出。
导出图片的代码如下:
private fun save() {
isSave = false
val w = mSurfaceSize.x.toInt() * 2
val h = mSurfaceSize.y.toInt() * 2
val screenshotSize = w * h
val pixels = IntBuffer.allocate(screenshotSize)
GLES20.glReadPixels(0, 0, w, h, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, pixels)
GlobalScope.launch {
val buffer = IntBuffer.allocate(screenshotSize)
for (i in 0 until h) {
for (j in 0 until w) {
buffer.put((h - i - 1) * w + j, pixels.get(i * w + j));
}
}
val config = Bitmap.Config.ARGB_8888
val bitmap = Bitmap.createBitmap(w, h, config)
bitmap.eraseColor(Color.argb(0, 255, 255, 255))
bitmap.copyPixelsFromBuffer(buffer)
val out = FileOutputStream(savePath)
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out)
}
}