Skip to content

Commit

Permalink
Latent code for partitioning to reduce memory requirements
Browse files Browse the repository at this point in the history
(now partitioning in 2048x2048), but a typical one would be 128x128
Disabled because it produce artifacts on block edges. I have to figure out how to fix this.
  • Loading branch information
soywiz committed Dec 14, 2017
1 parent 9abd0f1 commit b9580ca
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 18 deletions.
1 change: 0 additions & 1 deletion build.gradle
@@ -1,4 +1,3 @@
import java.nio.file.CopyOption
import java.nio.file.Files
import java.nio.file.StandardCopyOption
import java.nio.file.attribute.PosixFilePermission
Expand Down
Binary file added docs/goku_small_bg.2x.partition.v1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
76 changes: 59 additions & 17 deletions src/main/kotlin/com/soywiz/kaifu2x/Kaifu2x.kt
Expand Up @@ -2,10 +2,7 @@ package com.soywiz.kaifu2x

import com.soywiz.kaifu2x.util.*
import com.soywiz.korim.bitmap.Bitmap32
import com.soywiz.korim.format.defaultImageFormats
import com.soywiz.korim.format.readBitmapNoNative
import com.soywiz.korim.format.registerStandard
import com.soywiz.korim.format.writeTo
import com.soywiz.korim.format.*
import com.soywiz.korio.Korio
import com.soywiz.korio.error.invalidArg
import com.soywiz.korio.error.invalidOp
Expand Down Expand Up @@ -121,6 +118,21 @@ object Kaifu2x {
}

suspend fun Model.waifu2xCoreRgba(name: String, image: Bitmap32, components: List<ColorComponent>, parallel: Boolean): Bitmap32 {
//val chunkSize = 128
//val chunkSize = 32
//val chunkSize = 400
//val artifactThresold = 2
//val artifactThresold = 4
//val artifactThresold = 8
//val artifactThresold = 16
//val artifactThresold = 32

val chunkSize = 2048
//val chunkSize = 128
val artifactThresold = 0
//val artifactThresold = 32
//val artifactThresold = 40

val model = this
val imYCbCr = image.rgbaToYCbCr()
val time = measureTimeMillis {
Expand All @@ -129,26 +141,56 @@ suspend fun Model.waifu2xCoreRgba(name: String, image: Bitmap32, components: Lis

System.err.println("Components: Requested:${components.map { it.toStringYCbCr() }} -> Required:${acomponents.map { it.toStringYCbCr() }}")

val startTime = System.currentTimeMillis()
model.waifu2xYCbCrInplace(imYCbCr, acomponents, parallel = parallel) { current, total ->
val currentTime = System.currentTimeMillis()
val ratio = current.toDouble() / total.toDouble()
val elapsedMs = (currentTime - startTime)
val estimatedMs = elapsedMs * (1.0 / ratio)
System.err.print(
"\rProgress($name): %.1f%% - Elapsed: %s - Remaining: %s ".format(
(ratio * 100).toFloat(),
toTimeString(elapsedMs.toInt()),
toTimeString((estimatedMs - elapsedMs).toInt())
)
)
for (y in 0 until imYCbCr.height step (chunkSize - artifactThresold * 2)) {
for (x in 0 until imYCbCr.width step (chunkSize - artifactThresold * 2)) {
val swidth = min(chunkSize, imYCbCr.width - x)
val sheight = min(chunkSize, imYCbCr.height - y)
println("CHUNK($x, $y, $swidth, $sheight) [${imYCbCr.width}, ${imYCbCr.height}]")
val chunk = imYCbCr.copySliceWithSize2(x, y, swidth, sheight)

System.gc()

val startTime = System.currentTimeMillis()
model.waifu2xYCbCrInplace(chunk, acomponents, parallel = parallel) { current, total ->
val currentTime = System.currentTimeMillis()
val ratio = current.toDouble() / total.toDouble()
val elapsedMs = (currentTime - startTime)
val estimatedMs = elapsedMs * (1.0 / ratio)
System.err.print(
"\r[%s] %.1f%% - ELA: %s - ETA: %s - MEM: %s ".format(
name,
(ratio * 100).toFloat(),
toTimeString(elapsedMs.toInt()),
toTimeString((estimatedMs - elapsedMs).toInt()),
getMemoryUsedString()
)
)
}
System.err.println()

val dx = if (x == 0) 0 else artifactThresold
val dy = if (y == 0) 0 else artifactThresold
if ((chunk.width - dx) > 0 && (chunk.height - dy) > 0) {
imYCbCr.put(chunk.copySliceWithSize2(dx, dy, chunk.width - dx, chunk.height - dy), x + dx, y + dy)
//imYCbCr.put(chunk.sliceWithBounds(dx, dy, chunk.width, chunk.height), x + dx, y + dy)
//imYCbCr.put(chunk.copySliceWithSize2(artifactThresold, artifactThresold, chunk.width - artifactThresold, chunk.height - artifactThresold), x + artifactThresold, y + artifactThresold)
}
}
}
}
System.err.println()
System.err.println("Took: " + time.toDouble() / 1000 + " seconds")
return imYCbCr.yCbCrToRgba()
}

fun getMemoryUsedString(): String {
return "%.2f MB".format(getMemoryUsed().toDouble() / (1024.0 * 1024.0))
}

fun getMemoryUsed(): Long {
return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()
}

//fun Model.waifu2xRgba(imRgba: Bitmap32, acomponents: List<ColorComponent>, parallel: Boolean = true, progressReport: (Int, Int) -> Unit = { cur, total -> }): Bitmap32 {
// val imYCbCr = imRgba.rgbaToYCbCr()
// val result = waifu2xYCbCrInplace(imYCbCr, acomponents, parallel, progressReport)
Expand Down
10 changes: 10 additions & 0 deletions src/main/kotlin/com/soywiz/kaifu2x/util/Bitmap32Ext.kt
@@ -1,10 +1,12 @@
package com.soywiz.kaifu2x.util

import com.soywiz.kmem.arraycopy
import com.soywiz.korim.bitmap.Bitmap32
import com.soywiz.korim.color.RGBA
import com.soywiz.korio.error.invalidOp
import com.soywiz.korio.util.clamp

// @TODO: Move to korim
fun Int.rgbaToYCbCr(): Int {
val R = RGBA.getR(this)
val G = RGBA.getG(this)
Expand Down Expand Up @@ -102,3 +104,11 @@ fun ColorComponent.toStringYCbCr() = when (this.index) {
3 -> "A"
else -> invalidOp
}

fun Bitmap32.copySliceWithSize2(x: Int, y: Int, width: Int, height: Int): Bitmap32 {
val out = Bitmap32(width, height)
for (yy in 0 until height) {
arraycopy(this.data, this.index(x, y + yy), out.data, out.index(0, yy), width)
}
return out
}

0 comments on commit b9580ca

Please sign in to comment.