added thumbnail generation

This commit is contained in:
Gauthier Roebroeck 2019-08-19 15:09:12 +08:00
parent f38660b45c
commit 5c153bf539
4 changed files with 38 additions and 1 deletions

View file

@ -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") {

View file

@ -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

View file

@ -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 {

View file

@ -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,