mirror of
https://github.com/gotson/komga.git
synced 2025-12-06 08:32:25 +01:00
added thumbnail generation
This commit is contained in:
parent
f38660b45c
commit
5c153bf539
4 changed files with 38 additions and 1 deletions
|
|
@ -58,6 +58,8 @@ dependencies {
|
||||||
implementation("com.github.junrar:junrar:4.0.0")
|
implementation("com.github.junrar:junrar:4.0.0")
|
||||||
implementation("net.grey-panther:natural-comparator:1.1")
|
implementation("net.grey-panther:natural-comparator:1.1")
|
||||||
|
|
||||||
|
implementation("net.coobird:thumbnailator:0.4.8")
|
||||||
|
|
||||||
runtimeOnly("com.h2database:h2:1.4.199")
|
runtimeOnly("com.h2database:h2:1.4.199")
|
||||||
|
|
||||||
testImplementation("org.springframework.boot:spring-boot-starter-test") {
|
testImplementation("org.springframework.boot:spring-boot-starter-test") {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import javax.persistence.FetchType
|
||||||
import javax.persistence.GeneratedValue
|
import javax.persistence.GeneratedValue
|
||||||
import javax.persistence.Id
|
import javax.persistence.Id
|
||||||
import javax.persistence.JoinColumn
|
import javax.persistence.JoinColumn
|
||||||
|
import javax.persistence.Lob
|
||||||
import javax.persistence.OneToOne
|
import javax.persistence.OneToOne
|
||||||
import javax.persistence.Table
|
import javax.persistence.Table
|
||||||
|
|
||||||
|
|
@ -23,6 +24,10 @@ class BookMetadata(
|
||||||
@Column(name = "media_type")
|
@Column(name = "media_type")
|
||||||
val mediaType: String? = null,
|
val mediaType: String? = null,
|
||||||
|
|
||||||
|
@Column(name = "thumbnail")
|
||||||
|
@Lob
|
||||||
|
val thumbnail: ByteArray? = null,
|
||||||
|
|
||||||
pages: List<BookPage> = emptyList()
|
pages: List<BookPage> = emptyList()
|
||||||
) {
|
) {
|
||||||
@Id
|
@Id
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package org.gotson.komga.domain.service
|
package org.gotson.komga.domain.service
|
||||||
|
|
||||||
import mu.KotlinLogging
|
import mu.KotlinLogging
|
||||||
|
import net.coobird.thumbnailator.Thumbnails
|
||||||
import org.gotson.komga.domain.model.Book
|
import org.gotson.komga.domain.model.Book
|
||||||
import org.gotson.komga.domain.model.BookMetadata
|
import org.gotson.komga.domain.model.BookMetadata
|
||||||
import org.gotson.komga.domain.model.Status
|
import org.gotson.komga.domain.model.Status
|
||||||
|
|
@ -9,6 +10,7 @@ import org.gotson.komga.infrastructure.archive.ContentDetector
|
||||||
import org.gotson.komga.infrastructure.archive.RarExtractor
|
import org.gotson.komga.infrastructure.archive.RarExtractor
|
||||||
import org.gotson.komga.infrastructure.archive.ZipExtractor
|
import org.gotson.komga.infrastructure.archive.ZipExtractor
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
|
||||||
private val logger = KotlinLogging.logger {}
|
private val logger = KotlinLogging.logger {}
|
||||||
|
|
@ -25,6 +27,9 @@ class BookParser(
|
||||||
"application/x-rar-compressed" to rarExtractor
|
"application/x-rar-compressed" to rarExtractor
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val thumbnailSize = 300
|
||||||
|
private val thumbnailFormat = "png"
|
||||||
|
|
||||||
fun parse(book: Book): BookMetadata {
|
fun parse(book: Book): BookMetadata {
|
||||||
logger.info { "Trying to parse book: ${book.url}" }
|
logger.info { "Trying to parse book: ${book.url}" }
|
||||||
|
|
||||||
|
|
@ -36,7 +41,20 @@ class BookParser(
|
||||||
val pages = supportedMediaTypes.getValue(mediaType).getPagesList(book.path())
|
val pages = supportedMediaTypes.getValue(mediaType).getPagesList(book.path())
|
||||||
logger.info { "Book has ${pages.size} pages" }
|
logger.info { "Book has ${pages.size} pages" }
|
||||||
|
|
||||||
return BookMetadata(mediaType = mediaType, status = Status.READY, pages = pages)
|
val thumbnail = try {
|
||||||
|
ByteArrayOutputStream().let {
|
||||||
|
Thumbnails.of(supportedMediaTypes.getValue(mediaType).getPageStream(book.path(), pages.first().fileName))
|
||||||
|
.size(thumbnailSize, thumbnailSize)
|
||||||
|
.outputFormat(thumbnailFormat)
|
||||||
|
.toOutputStream(it)
|
||||||
|
it.toByteArray()
|
||||||
|
}
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
logger.warn(ex) { "Could not generate thumbnail for book: ${book.url}" }
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
return BookMetadata(mediaType = mediaType, status = Status.READY, pages = pages, thumbnail = thumbnail)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPageStream(book: Book, number: Int): InputStream {
|
fun getPageStream(book: Book, number: Int): InputStream {
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,18 @@ class SerieController(
|
||||||
return bookRepository.findByIdOrNull(bookId)?.toDto() ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
return bookRepository.findByIdOrNull(bookId)?.toDto() ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping(value = ["{serieId}/books/{bookId}/thumbnail"], produces = [MediaType.IMAGE_PNG_VALUE])
|
||||||
|
fun getBookThumbnail(
|
||||||
|
@PathVariable serieId: Long,
|
||||||
|
@PathVariable bookId: Long
|
||||||
|
): ByteArray {
|
||||||
|
if (!serieRepository.existsById(serieId)) throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||||
|
|
||||||
|
return bookRepository.findByIdOrNull(bookId)?.let {
|
||||||
|
it.metadata.thumbnail ?: throw ResponseStatusException(HttpStatus.NO_CONTENT)
|
||||||
|
} ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping(value = ["{serieId}/books/{bookId}/content"], produces = [MediaType.APPLICATION_OCTET_STREAM_VALUE])
|
@GetMapping(value = ["{serieId}/books/{bookId}/content"], produces = [MediaType.APPLICATION_OCTET_STREAM_VALUE])
|
||||||
fun getBookContent(
|
fun getBookContent(
|
||||||
@PathVariable serieId: Long,
|
@PathVariable serieId: Long,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue