Skip to content

Commit

Permalink
First Release (Maybe)
Browse files Browse the repository at this point in the history
  • Loading branch information
mannu691 committed May 30, 2024
1 parent 9fa6a68 commit 05d4ba1
Show file tree
Hide file tree
Showing 14 changed files with 93 additions and 101 deletions.
Binary file added .github/readme-images/gemini.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/readme-images/googletranslate.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/readme-images/manhuaplus.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/readme-images/mlkit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ Newly Added :
* Japanase

## Translation Comparison
//TODO
| ManhuaPlus | Gemini | Google Translate | MLKit (On Device) |
| ------------- | ------------- | ------------- | ------------- |
| ![ManhuaPlus](./.github/readme-images/manhuaplus.png) | ![Gemini](./.github/readme-images/gemini.png) | ![GoogleTranslate](./.github/readme-images/googletranslate.png) | ![mlkit](./.github/readme-images/mlkit.png) |

## Available Translators
* MLkit : On Device Translations
Expand All @@ -31,6 +33,8 @@ Newly Added :
## Download
Get the app from our [releases page](https://github.com/mannu691/TachiyomiSY/releases/latest).

**Currently "Save as CBZ Archive" option is not supported**
**please turn it off in Settings > Downloads > Save as CBZ Archive**
## Issues, Feature Requests and Contributing

Please make sure to read the full guidelines. Your issue may be closed without warning if you do not.
Expand Down
17 changes: 13 additions & 4 deletions app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package eu.kanade.tachiyomi.data.download

import android.content.Context
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.lifecycleScope
import com.hippo.unifile.UniFile
import eu.kanade.domain.chapter.model.toSChapter
import eu.kanade.domain.manga.model.getComicInfo
Expand All @@ -16,6 +18,7 @@ import eu.kanade.tachiyomi.util.storage.CbzCrypto
import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.storage.DiskUtil.NOMEDIA_FILE
import eu.kanade.tachiyomi.util.storage.saveTo
import eu.kanade.translation.TranslationManager
import exh.source.isEhBasedSource
import exh.util.DataSaver
import exh.util.DataSaver.Companion.getImage
Expand All @@ -38,6 +41,8 @@ import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapMerge
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.retryWhen
import kotlinx.coroutines.flow.transformLatest
import kotlinx.coroutines.flow.update
Expand Down Expand Up @@ -88,6 +93,7 @@ class Downloader(
private val xml: XML = Injekt.get(),
private val getCategories: GetCategories = Injekt.get(),
private val getTracks: GetTracks = Injekt.get(),
private val translationManager: TranslationManager= Injekt.get(),
// SY -->
private val sourcePreferences: SourcePreferences = Injekt.get(),
// SY <--
Expand All @@ -97,7 +103,7 @@ class Downloader(
* Store for persisting downloads across restarts.
*/
private val store = DownloadStore(context)

private var translateOnDownload = false
/**
* Queue where active downloads are kept.
*/
Expand Down Expand Up @@ -128,6 +134,11 @@ class Downloader(
launchNow {
val chapters = async { store.restore() }
addAllToQueue(chapters.await())
launchNow {
downloadPreferences.translateOnDownload().changes().onEach {
translateOnDownload=it
}.launchIn(ProcessLifecycleOwner.get().lifecycleScope)
}
}
}

Expand Down Expand Up @@ -385,9 +396,6 @@ class Downloader(
return
}
//Translate and Render Images
//TODO ADD AUTO TRANSALTE
// if (downloadPreferences.translateOnDownload().get()) chapterTranslator.processChapter(tmpDir.name!!, tmpDir)


createComicInfoFile(
tmpDir,
Expand All @@ -407,6 +415,7 @@ class Downloader(
DiskUtil.createNoMediaFile(tmpDir, context)

download.status = Download.State.DOWNLOADED
if (translateOnDownload) translationManager.translateChapter(chapterID =download.chapter.id )
} catch (error: Throwable) {
if (error is CancellationException) throw error
// If the page list threw, it will resume here
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ internal class DownloadPageLoader(
}

private suspend fun getPagesFromArchive(file: UniFile): List<ReaderPage> {
//TODO LOAD TRANSLATION HERE ALSO
// SY -->
val loader = ZipPageLoader(file, context).also { zipPageLoader = it }
// SY <--
return loader.getPages()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ class WebtoonPageHolder(
* Binds the given [page] with this view holder, subscribing to its state.
*/
fun bind(page: ReaderPage) {

this.page = page
loadJob?.cancel()
loadJob = scope.launch { loadPageAndProcessStatus() }
Expand Down Expand Up @@ -145,6 +144,8 @@ class WebtoonPageHolder(
frame.recycle()
progressIndicator.setProgress(0)
progressContainer.isVisible = true
textTranslationsComposeView?.let{frame.removeView(textTranslationsComposeView)}
textTranslationsComposeView=null
}

/**
Expand Down Expand Up @@ -190,6 +191,7 @@ class WebtoonPageHolder(
private fun setQueued() {
progressContainer.isVisible = true
progressIndicator.show()
textTranslationsComposeView?.hide()
removeErrorLayout()
}

Expand All @@ -199,6 +201,7 @@ class WebtoonPageHolder(
private fun setLoading() {
progressContainer.isVisible = true
progressIndicator.show()
textTranslationsComposeView?.hide()
removeErrorLayout()
}

Expand All @@ -207,6 +210,7 @@ class WebtoonPageHolder(
*/
private fun setDownloading() {
progressContainer.isVisible = true
textTranslationsComposeView?.hide()
progressIndicator.show()
removeErrorLayout()
}
Expand Down Expand Up @@ -276,6 +280,7 @@ class WebtoonPageHolder(
*/
private fun setError() {
progressContainer.isVisible = false
textTranslationsComposeView?.hide()
initErrorLayout()
}

Expand All @@ -284,6 +289,7 @@ class WebtoonPageHolder(
*/
private fun onImageDecoded() {
progressContainer.isVisible = false
textTranslationsComposeView?.show()
removeErrorLayout()
}

Expand Down
97 changes: 33 additions & 64 deletions app/src/main/java/eu/kanade/translation/ChapterTranslator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,8 @@ import logcat.logcat
import tachiyomi.core.common.storage.extension
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min

/**TODOS
* Build a Translation Class for state of Job ✔
* Build a Translation Job Manager ✔
* Rework the Translation Process to output to translations.json ✔
* Read translations.json while loading chapter for reader
* Build ScanDialogView to display text translations
*/
class ChapterTranslator(
private val context: Context,
private var scanLanguage: ScanLanguage = ScanLanguage.CHINESE,
Expand All @@ -57,94 +51,68 @@ class ChapterTranslator(
val result = recognizer.recognize(image)
val blocks = result.textBlocks.filter { it.boundingBox != null && it.text.length > 1 }
val resultant = toTextTranslation(blocks, image.width, image.height)
file.name?.let { pages.put(it, resultant) }
if (resultant.isNotEmpty()) file.name?.let { pages.put(it, resultant) }
} catch (e: Exception) {
}
}

//Translate All Pages
textTranslator.translate(pages)
pages.forEach { page -> tempTest(page.value) }
Json.encodeToStream(pages, translation.dir.createFile("translations.json")!!.openOutputStream())
}

private fun tempTest(blocks: List<TextTranslation>){
private fun toTextTranslation(blocks: List<TextBlock>, width: Int, height: Int): ArrayList<TextTranslation> {
val resultant = ArrayList<TextTranslation>()
val width = blocks.first().imgHeight
val height = blocks.first().imgHeight
for (block in blocks) {
try {
var passed = true;
val bounds = block.textBlock!!.boundingBox!!
logcat { "Text : ${block.translated}" }
val bounds = block.boundingBox!!
val symbolBound = block.lines.first().elements.first().symbols.first().boundingBox!!
val bWidth = bounds.width().toFloat()
val bHeight = bounds.height().toFloat()
val bX = symbolBound.left.toFloat()
val bY = symbolBound.top.toFloat()

for (i in resultant.lastIndex downTo (resultant.lastIndex - 5).coerceAtLeast(0)) {
// logcat { "BLOCK : ${block.text} | ${bY} | ${bounds.bottom} | ${bX}" }

for (i in resultant.lastIndex downTo (resultant.lastIndex - 5).coerceAtLeast(0)) {
val b2 = resultant[i]
val b2b = b2.textBlock!!.boundingBox!!

if (b2b.bottom >= bounds.top && abs(b2b.left - bounds.left) < 20) {
logcat { "${b2.translated} ||| bottom : ${b2b.bottom} | top2 : ${bounds.left} | ${abs(b2b.left - bounds.left)}" }
logcat { "ADDED : ${block.translated}" }
val bottom = b2.height + b2.y
// logcat { "RES : ${b2.text} | ${bottom} | ${b2.x - bX} | ${(bY - bottom)}" }
if (bY - bottom < 20 && abs(b2.x - bX) < 20) {
// logcat { "ADDED : ${block.text.replace("\n", " ")}" }
passed = false
// b2.text += " " + block.text.replace("\n", " ")
// b2.height = (b2b.height() + bounds.height()) / height.toFloat()
// b2.width = max(bounds.width(), b2b.width()) / width.toFloat()
break;
b2.text += " " + block.text.replace("\n", " ")
b2.height += bHeight + 18
b2.width = max(bWidth, b2.width)
b2.x = min(bX, b2.x)
break
}
}
if (passed) {
resultant.add(
block,
)
}
} catch (e: Exception) {
logcat { "ERROR : ${e.stackTraceToString()}" }
}
}
}

private fun toTextTranslation(blocks: List<TextBlock>, width: Int, height: Int): ArrayList<TextTranslation> {
val resultant = ArrayList<TextTranslation>()
for (block in blocks) {
try {
var passed = true;
val bounds = block.boundingBox!!
// logcat { "Text : ${block.text}" }

// for (i in resultant.lastIndex downTo (resultant.lastIndex - 5).coerceAtLeast(0)) {
//
// val b2 = resultant[i]
// val b2b = b2.textBlock!!.boundingBox!!
// logcat { "bottom : ${b2b.bottom} | top2 : ${bounds.left} | ${abs(b2b.left - bounds.left)}" }
// if (b2b.bottom >= bounds.top && abs(b2b.left - bounds.left) < 20) {
//
// logcat { "ADDED : ${ block.text.replace("\n", " ")}" }
// passed = false
// b2.text += " " + block.text.replace("\n", " ")
// b2.height=(b2b.height()+bounds.height())/height.toFloat()
// b2.width= max(bounds.width(),b2b.width())/width.toFloat()
// break;
// }
// }
if (passed) {
val symbolBound = block.lines.first().elements.first().symbols.first().boundingBox!!
resultant.add(
TextTranslation(
text = block.text.replace("\n", " "),
x = (symbolBound.left / width.toFloat()),
y = symbolBound.top / height.toFloat(),
width = bounds.width() / width.toFloat(),
height = bounds.height() / height.toFloat(),
x = bX,
y = bY,
width = bounds.width().toFloat(),
height = bounds.height().toFloat(),
angle = block.lines.first().angle,
textBlock = block, imgHeight = height, imgWidth = width
),
)
}
} catch (e: Exception) {
logcat { "ERROR : ${e.stackTraceToString()}" }
}
}
resultant.forEach { tt ->
run {
tt.x /= width
tt.y /= height
tt.width /= width
tt.height /= height
}
}

return resultant
}
Expand Down Expand Up @@ -180,3 +148,4 @@ class ChapterTranslator(
}

}

11 changes: 2 additions & 9 deletions app/src/main/java/eu/kanade/translation/TextTranslation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,8 @@ data class TextTranslation(
var text: String,
var width: Float,
var height: Float,
val x: Float,
val y: Float,
var x: Float,
var y: Float,
val angle: Float,
var translated: String = "",
@Transient
val textBlock: TextBlock? = null,
@Transient
val imgWidth: Int = 0,

@Transient
val imgHeight: Int = 0,
)
Original file line number Diff line number Diff line change
Expand Up @@ -83,22 +83,23 @@ class TextTranslationsComposeView :
.fillMaxSize()
.onSizeChanged {
size = it
if(size==IntSize.Zero)hide()
if(size==IntSize.Zero)show()
},
) {
if (size == IntSize.Zero) return
val imgWidth = size.width
val imgHeight = size.height
translations.forEach { translation ->
//TODO give paddding when translatingt the text
val xPx = ((translation.x-0.02) * imgWidth).toFloat()
val yPx = ((translation.y-0.015) * imgHeight).toFloat()
val width = ((translation.width+0.04) * imgWidth).toFloat()
val height =((translation.height+0.03) * imgHeight).toFloat()
val height =((translation.height*1.2+0.03) * imgHeight).toFloat()
TextBlock(
translation = translation,
modifier = Modifier
.absoluteOffset(pxToDp(xPx), pxToDp(yPx))
.rotate(translation.angle)
.rotate(if(translation.angle<89)translation.angle else 0f)
.size(pxToDp(width), pxToDp(height)),
)
}
Expand All @@ -110,12 +111,13 @@ class TextTranslationsComposeView :
Box(modifier = modifier) {
AutoSizeText(
text = translation.translated,
color = Color.Red,
color = Color.Black,
softWrap = true, fontFamily = font,
lineSpacingRatio = 1.2f,
overflow = TextOverflow.Clip,
alignment = Alignment.Center,
modifier = Modifier
.background(Color.Blue.copy(alpha = 1f))
.background(Color.White)
.padding(1.dp)

)
Expand Down
Loading

0 comments on commit 05d4ba1

Please sign in to comment.