Implement simple pages copping

remotes/weblate/feature/pagecrop
Koitharu 6 years ago
parent e0d45961f8
commit 963d93ca7b

@ -1,7 +1,11 @@
package org.koitharu.kotatsu.domain
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Color
import android.graphics.Rect
import android.util.Size
import androidx.core.graphics.get
import okhttp3.OkHttpClient
import okhttp3.Request
import org.koin.core.KoinComponent
@ -11,6 +15,8 @@ import org.koitharu.kotatsu.core.model.MangaPage
import org.koitharu.kotatsu.core.prefs.ReaderMode
import org.koitharu.kotatsu.utils.ext.await
import org.koitharu.kotatsu.utils.ext.medianOrNull
import org.koitharu.kotatsu.utils.ext.use
import java.io.File
import java.io.InputStream
object MangaUtils : KoinComponent {
@ -54,4 +60,81 @@ object MangaUtils : KoinComponent {
check(imageHeight > 0 && imageWidth > 0)
return Size(imageWidth, imageHeight)
}
@JvmStatic
fun cropBitmap(input: Bitmap): Bitmap? {
return try {
val bounds = Rect(0, 0, input.width, input.height)
var isBoundsChanged = false
for (x in 1 until input.width / 2) {
var leftColor = 0
var rightColor = 0
for (y in 0 until input.height) {
leftColor += input[x, y]
rightColor += input[input.width - x - 1, y]
}
leftColor /= input.height
rightColor /= input.height
var consumed = false
if (leftColor == Color.WHITE) {
bounds.left++
consumed = true
}
if (rightColor == Color.WHITE) {
bounds.right--
consumed = true
}
if (consumed) {
isBoundsChanged = true
} else {
break
}
}
for (y in 1 until input.height / 2) {
var topColor = 0
var bottomColor = 0
for (x in 0 until input.width) {
topColor += input[x, y]
bottomColor += input[x, input.height - y - 1]
}
topColor /= input.width
bottomColor /= input.width
var consumed = false
if (topColor == Color.WHITE) {
bounds.top++
consumed = true
}
if (bottomColor == Color.WHITE) {
bounds.bottom--
consumed = true
}
if (consumed) {
isBoundsChanged = true
} else {
break
}
}
if (isBoundsChanged) {
Bitmap.createBitmap(input, bounds.left, bounds.top, bounds.width(), bounds.height())
} else {
null
}
} catch (e: Throwable) {
if (BuildConfig.DEBUG) {
e.printStackTrace()
}
null
}
}
@JvmStatic
fun cropBitmap(file: File) {
BitmapFactory.decodeFile(file.path).use { bmp ->
cropBitmap(bmp)?.use { cropped ->
file.outputStream().use { out ->
cropped.compress(Bitmap.CompressFormat.WEBP, 100, out)
}
}
}
}
}

@ -1,7 +1,9 @@
package org.koitharu.kotatsu.ui.reader
import android.net.Uri
import androidx.annotation.WorkerThread
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
import okhttp3.OkHttpClient
import okhttp3.Request
import org.koin.core.KoinComponent
@ -16,13 +18,14 @@ import kotlin.coroutines.CoroutineContext
class PageLoader : KoinComponent, CoroutineScope, DisposableHandle {
private val job = SupervisorJob()
private val tasks = HashMap<String, Job>()
private val mutex = Mutex()
private val okHttp by inject<OkHttpClient>()
private val cache by inject<PagesCache>()
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + job
@WorkerThread
@Suppress("BlockingMethodInNonBlockingContext")
suspend fun loadFile(url: String, force: Boolean): File {
if (!force) {
@ -55,6 +58,10 @@ class PageLoader : KoinComponent, CoroutineScope, DisposableHandle {
response.body!!.byteStream().copyTo(out)
}
}
}.also {
mutex.withLock(this) {
MangaUtils.cropBitmap(it)
}
}
}

@ -1,6 +1,7 @@
package org.koitharu.kotatsu.utils.ext
import android.content.res.Resources
import android.graphics.Bitmap
import kotlinx.coroutines.delay
import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.R
@ -43,4 +44,10 @@ fun Throwable.getDisplayMessage(resources: Resources) = when (this) {
} else {
resources.getString(R.string.error_occurred)
}
}
inline fun <R> Bitmap.use(block: (Bitmap) -> R): R = try {
block(this)
} finally {
recycle()
}
Loading…
Cancel
Save