Almost done tiles processing

This commit is contained in:
Alexey 2025-08-07 15:21:04 +03:00
commit 8bec8e4b16
3 changed files with 69 additions and 32 deletions

View file

@ -50,6 +50,8 @@ dependencies {
implementation("io.github.chochanaresh:filepicker:0.6.0") implementation("io.github.chochanaresh:filepicker:0.6.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.10.2")
implementation(libs.androidx.core.ktx) implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx) implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose) implementation(libs.androidx.activity.compose)

View file

@ -40,10 +40,14 @@ import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.mirenkov.ktheightmap.ui.theme.KtHeightMapTheme import com.mirenkov.ktheightmap.ui.theme.KtHeightMapTheme
import java.util.Base64
const val TAG = "KtHeightMap" const val TAG = "KtHeightMap"
const val TILE_SIZE: Float = 256F const val TILE_SIZE: Float = 256F
fun ByteArray.toBase64(): String =
String(Base64.getEncoder().encode(this))
class TileViewModelFactory(val application: Application): class TileViewModelFactory(val application: Application):
ViewModelProvider.Factory { ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T { override fun <T : ViewModel> create(modelClass: Class<T>): T {
@ -58,7 +62,6 @@ class MainActivity : ComponentActivity() {
enableEdgeToEdge() enableEdgeToEdge()
setContent { setContent {
val owner = LocalViewModelStoreOwner.current val owner = LocalViewModelStoreOwner.current
owner?.let { owner?.let {
val viewModel: TileViewModel = viewModel( val viewModel: TileViewModel = viewModel(
it, it,

View file

@ -1,65 +1,97 @@
package com.mirenkov.ktheightmap package com.mirenkov.ktheightmap
import android.graphics.BitmapFactory
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.safeDrawingPadding import androidx.compose.foundation.layout.safeDrawingPadding
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import com.mirenkov.ktheightmap.ui.theme.KtHeightMapTheme import com.mirenkov.ktheightmap.ui.theme.KtHeightMapTheme
import com.nareshchocha.filepickerlibrary.FilePickerResultContracts import com.nareshchocha.filepickerlibrary.FilePickerResultContracts
import com.nareshchocha.filepickerlibrary.models.PickerData import com.nareshchocha.filepickerlibrary.models.FilePickerResult
import com.nareshchocha.filepickerlibrary.models.PopUpConfig import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import java.io.FileInputStream import java.io.FileInputStream
import java.util.zip.ZipEntry import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream import java.util.zip.ZipInputStream
class SettingsActivity : ComponentActivity() { class SettingsActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) var filePath: String? = null
val launcher = registerForActivityResult(FilePickerResultContracts.PickDocumentFile()) { result -> fun filePickerResult(result: FilePickerResult): String? {
if (result.errorMessage != null) { if (result.errorMessage != null) {
Log.e("Picker", result.errorMessage ?: "") Log.e(TAG, result.errorMessage ?: "")
} else { return null
val filePath = result.selectedFilePath } else {
filePath?.let { val filePath = result.selectedFilePath
if (!it.endsWith(".zip")) filePath?.let {
return@let if (it.endsWith(".zip"))
ZipInputStream(FileInputStream(it)).use { zipInputStream -> return filePath
var entry = zipInputStream.nextEntry
while (entry != null) {
with(entry.name) {
if (count { it == '/' } == 4 && endsWith(".jpg"))
processEntry(entry)
}
entry = zipInputStream.nextEntry
}
}
}
} }
return null
} }
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val launcher = registerForActivityResult(FilePickerResultContracts.PickDocumentFile(),
{ result -> filePath = filePickerResult(result) }
)
enableEdgeToEdge() enableEdgeToEdge()
setContent { setContent {
val coroutineScope = rememberCoroutineScope()
KtHeightMapTheme { KtHeightMapTheme {
Column(Modifier.fillMaxSize() Column(Modifier.fillMaxSize()
.safeDrawingPadding()) { .safeDrawingPadding()) {
Button(onClick = { Button(onClick = {
launcher.launch(null) launcher.launch(null)
}) { Text(text = "Load database") } }) { Text(text = "Select database") }
Button(onClick = { coroutineScope.launch { processZip(filePath) } }) {
Text(text = "Load database")
}
} }
} }
} }
} }
} }
fun processEntry(entry: ZipEntry) { suspend fun processZip(filePath: String?) = coroutineScope {
Log.i(TAG, entry.name) filePath?.let {
ZipInputStream(FileInputStream(it)).use { zipInputStream ->
var entry = zipInputStream.nextEntry
while (true) {
if (entry.name.endsWith(".jpg")) {
Log.i(TAG, entry.name)
processEntry(zipInputStream, entry)
}
entry = zipInputStream.nextEntry
if (entry == null)
break
}
}
}
}
fun processEntry(zis: ZipInputStream, entry: ZipEntry) {
val ba = ByteArray(entry.size.toInt())
var offset = 0
var size = zis.read(ba, 0, ba.size)
while (size > 0) {
offset += size
size = zis.read(ba, offset, ba.size - offset)
}
val regex = Regex("(?<=z)(\\d+)|(?<=x)(\\d+)|(?<=y)(\\d+)")
val ( level, x, y ) = regex.findAll(entry.name).map { it.value.toInt() }.toList()
val base64 = ba.toBase64()
val tile = Tile(x, y, level, base64)
} }