[orx-jumpflood] Add cropping for NPOT inputs

This commit is contained in:
Edwin Jakobs
2022-06-27 07:50:48 +02:00
parent eb8d3ea7a3
commit 885b9e54a4
2 changed files with 93 additions and 10 deletions

View File

@@ -7,6 +7,11 @@ import org.openrndr.draw.colorBuffer
import org.openrndr.extra.parameters.Description import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.DoubleParameter import org.openrndr.extra.parameters.DoubleParameter
import org.openrndr.math.Vector2 import org.openrndr.math.Vector2
import org.openrndr.shape.IntRectangle
import kotlin.math.ceil
import kotlin.math.log2
import kotlin.math.max
import kotlin.math.pow
@Description("Directional field") @Description("Directional field")
class DirectionalField : Filter() { class DirectionalField : Filter() {
@@ -24,23 +29,62 @@ class DirectionalField : Filter() {
private val decodeFilter = PixelDirection() private val decodeFilter = PixelDirection()
private var fit: ColorBuffer? = null
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) { override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) {
val advisedWidth = 2.0.pow(ceil(log2(source[0].effectiveWidth.toDouble()))).toInt()
val advisedHeight = 2.0.pow(ceil(log2(source[0].effectiveHeight.toDouble()))).toInt()
val advisedSize = max(advisedWidth, advisedHeight)
fit?.let {
if (it.effectiveWidth != advisedSize || it.effectiveHeight != advisedSize) {
it.destroy()
fit = null
thresholded?.destroy()
thresholded = null
contoured?.destroy()
contoured = null
jumpFlooder?.destroy()
jumpFlooder = null
}
}
if (fit == null) {
fit = colorBuffer(advisedSize, advisedSize)
}
source[0].copyTo(fit!!,
sourceRectangle = IntRectangle(0, 0, source[0].effectiveWidth, source[0].effectiveHeight),
targetRectangle = IntRectangle(0, advisedSize-source[0].effectiveHeight, source[0].effectiveWidth, source[0].effectiveHeight)
)
if (thresholded == null) { if (thresholded == null) {
thresholded = colorBuffer(target[0].width, target[0].height, format = ColorFormat.R) thresholded = colorBuffer(advisedSize, advisedSize, format = ColorFormat.R)
} }
if (contoured == null) { if (contoured == null) {
contoured = colorBuffer(target[0].width, target[0].height, format = ColorFormat.R) contoured = colorBuffer(advisedSize, advisedSize, format = ColorFormat.R)
} }
if (jumpFlooder == null) { if (jumpFlooder == null) {
jumpFlooder = JumpFlooder(target[0].width, target[0].height) jumpFlooder = JumpFlooder(advisedSize, advisedSize)
} }
thresholdFilter.threshold = threshold thresholdFilter.threshold = threshold
thresholdFilter.apply(source[0], thresholded!!) thresholdFilter.apply(fit!!, thresholded!!)
contourFilter.apply(thresholded!!, contoured!!) contourFilter.apply(thresholded!!, contoured!!)
val result = jumpFlooder!!.jumpFlood(contoured!!) val result = jumpFlooder!!.jumpFlood(contoured!!)
decodeFilter.originalSize = Vector2(target[0].width * 1.0, target[0].height * 1.0) decodeFilter.originalSize = Vector2(advisedSize.toDouble(), advisedSize.toDouble())
decodeFilter.distanceScale = distanceScale decodeFilter.distanceScale = distanceScale
decodeFilter.apply(result, result) decodeFilter.apply(arrayOf(result, thresholded!!), arrayOf(result))
result.copyTo(target[0]) result.copyTo(target[0],
sourceRectangle = IntRectangle(0, advisedSize-source[0].effectiveHeight, source[0].effectiveWidth, source[0].effectiveHeight),
targetRectangle = IntRectangle(0, 0, source[0].effectiveWidth, source[0].effectiveHeight))
}
override fun destroy() {
thresholdFilter.destroy()
contourFilter.destroy()
fit?.destroy()
thresholded?.destroy()
contoured?.destroy()
jumpFlooder?.destroy()
} }
} }

View File

@@ -4,9 +4,15 @@ import org.openrndr.draw.ColorBuffer
import org.openrndr.draw.ColorFormat import org.openrndr.draw.ColorFormat
import org.openrndr.draw.Filter import org.openrndr.draw.Filter
import org.openrndr.draw.colorBuffer import org.openrndr.draw.colorBuffer
import org.openrndr.extra.parameters.BooleanParameter
import org.openrndr.extra.parameters.Description import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.DoubleParameter import org.openrndr.extra.parameters.DoubleParameter
import org.openrndr.math.Vector2 import org.openrndr.math.Vector2
import org.openrndr.shape.IntRectangle
import kotlin.math.ceil
import kotlin.math.log2
import kotlin.math.max
import kotlin.math.pow
@Description("Distance field") @Description("Distance field")
class DistanceField : Filter() { class DistanceField : Filter() {
@@ -24,9 +30,38 @@ class DistanceField : Filter() {
private val decodeFilter = PixelDistance() private val decodeFilter = PixelDistance()
private var fit: ColorBuffer? = null
@BooleanParameter("signed distance")
var signedDistance = true var signedDistance = true
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) { override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) {
val advisedWidth = 2.0.pow(ceil(log2(source[0].effectiveWidth.toDouble()))).toInt()
val advisedHeight = 2.0.pow(ceil(log2(source[0].effectiveHeight.toDouble()))).toInt()
val advisedSize = max(advisedWidth, advisedHeight)
fit?.let {
if (it.effectiveWidth != advisedSize || it.effectiveHeight != advisedSize) {
it.destroy()
fit = null
thresholded?.destroy()
thresholded = null
contoured?.destroy()
contoured = null
jumpFlooder?.destroy()
jumpFlooder = null
}
}
if (fit == null) {
fit = colorBuffer(advisedSize, advisedSize)
}
source[0].copyTo(fit!!,
sourceRectangle = IntRectangle(0, 0, source[0].effectiveWidth, source[0].effectiveHeight),
targetRectangle = IntRectangle(0, advisedSize-source[0].effectiveHeight, source[0].effectiveWidth, source[0].effectiveHeight)
)
if (thresholded == null) { if (thresholded == null) {
thresholded = colorBuffer(target[0].width, target[0].height, format = ColorFormat.R) thresholded = colorBuffer(target[0].width, target[0].height, format = ColorFormat.R)
} }
@@ -37,14 +72,18 @@ class DistanceField : Filter() {
jumpFlooder = JumpFlooder(target[0].width, target[0].height) jumpFlooder = JumpFlooder(target[0].width, target[0].height)
} }
thresholdFilter.threshold = threshold thresholdFilter.threshold = threshold
thresholdFilter.apply(source[0], thresholded!!) thresholdFilter.apply(fit!!, thresholded!!)
contourFilter.apply(thresholded!!, contoured!!) contourFilter.apply(thresholded!!, contoured!!)
val result = jumpFlooder!!.jumpFlood(contoured!!) val result = jumpFlooder!!.jumpFlood(contoured!!)
decodeFilter.signedDistance = signedDistance decodeFilter.signedDistance = signedDistance
decodeFilter.originalSize = Vector2(target[0].width * 1.0, target[0].height * 1.0) decodeFilter.originalSize = Vector2(advisedSize.toDouble(), advisedSize.toDouble())
decodeFilter.distanceScale = distanceScale decodeFilter.distanceScale = distanceScale
decodeFilter.signedBit = false decodeFilter.signedBit = false
decodeFilter.apply(arrayOf(result, thresholded!!), arrayOf(result)) decodeFilter.apply(arrayOf(result, thresholded!!), arrayOf(result))
result.copyTo(target[0]) result.copyTo(target[0],
sourceRectangle = IntRectangle(0, advisedSize-source[0].effectiveHeight, source[0].effectiveWidth, source[0].effectiveHeight),
targetRectangle = IntRectangle(0, 0, source[0].effectiveWidth, source[0].effectiveHeight)
)
} }
} }