diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1f634de..6eed119 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,5 +37,13 @@ jobs: - name: Build with Gradle run: "./gradlew build -Dgithub.build.id=$GITHUB_RUN_ID -Dbuild.number=$GITHUB_RUN_NUMBER -Dgit.branch=$GITHUB_REF -Dcommit.hash=$GITHUB_SHA -Dcompiled.at=${{ steps.current-time.outputs.time }}" + - name: Publish to PerfectDreams' repository + if: github.ref == 'refs/heads/master' + env: + USERNAME: ${{ secrets.PERFECTDREAMS_REPO_USERNAME }} + PASSWORD: ${{ secrets.PERFECTDREAMS_REPO_PASSWORD }} + run: "./gradlew publish -DUSERNAME=$USERNAME -DPASSWORD=$PASSWORD" + - name: Publish to Docker + if: github.ref == 'refs/heads/master' run: "./gradlew :image-generation-server:jib -Dgithub.build.id=$GITHUB_RUN_ID -Dbuild.number=$GITHUB_RUN_NUMBER -Dgit.branch=$GITHUB_REF -Dcommit.hash=$GITHUB_SHA -Dcompiled.at=${{ steps.current-time.outputs.time }}" \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 929bbb6..2dcf4af 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,31 @@ +plugins { + `maven-publish` +} + +group = "net.perfectdreams.gabrielaimageserver" +version = Versions.GABRIELA_IMAGE_SERVER + allprojects { repositories { mavenCentral() - jcenter() + } +} + +subprojects { + apply() + version = "0.0.10-SNAPSHOT" + + publishing { + repositories { + maven { + name = "PerfectDreams" + url = uri("https://repo.perfectdreams.net/") + + credentials { + username = System.getProperty("USERNAME") ?: System.getenv("USERNAME") + password = System.getProperty("PASSWORD") ?: System.getenv("PASSWORD") + } + } + } } } \ No newline at end of file diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 0000000..b22ed73 --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,7 @@ +plugins { + `kotlin-dsl` +} + +repositories { + mavenCentral() +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt new file mode 100644 index 0000000..5147910 --- /dev/null +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -0,0 +1,8 @@ +object Versions { + const val GABRIELA_IMAGE_SERVER = "2.0.0-SNAPSHOT" + const val KOTLIN = "1.5.31" + const val JIB = "3.1.4" + const val KOTLINX_SERIALIZATION = "1.3.0" + const val PROMETHEUS = "0.12.0" + const val KTOR = "1.6.3" +} \ No newline at end of file diff --git a/client/build.gradle.kts b/client/build.gradle.kts new file mode 100644 index 0000000..9611476 --- /dev/null +++ b/client/build.gradle.kts @@ -0,0 +1,41 @@ +plugins { + kotlin("multiplatform") version Versions.KOTLIN + kotlin("plugin.serialization") version Versions.KOTLIN + `maven-publish` +} + +group = "net.perfectdreams.gabrielaimageserver" +version = Versions.GABRIELA_IMAGE_SERVER + +repositories { + mavenCentral() +} + +kotlin { + jvm { + compilations.all { + kotlinOptions.jvmTarget = "11" + } + + withJava() + } + + sourceSets { + commonMain { + dependencies { + api(project(":common")) + + api("io.ktor:ktor-client-core:${Versions.KTOR}") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:${Versions.KOTLINX_SERIALIZATION}") + } + } + } +} + +publishing { + publications { + register("PerfectDreams", MavenPublication::class.java) { + from(components["java"]) + } + } +} \ No newline at end of file diff --git a/client/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/client/GabrielaImageServerClient.kt b/client/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/client/GabrielaImageServerClient.kt new file mode 100644 index 0000000..3118e07 --- /dev/null +++ b/client/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/client/GabrielaImageServerClient.kt @@ -0,0 +1,20 @@ +package net.perfectdreams.gabrielaimageserver.client + +import io.ktor.client.* +import net.perfectdreams.gabrielaimageserver.client.services.ImagesService +import net.perfectdreams.gabrielaimageserver.client.services.VideosService + +/** + * Client for [GabrielaImageServer](https://github.com/LorittaBot/GabrielaImageGen) + * + * While the requests themselves are very simple, this is useful to wrap errors and exceptions. + * + * @param baseUrl the URL of the image server, example: https://gabriela.loritta.website + * @param http the http client that will be used for requests + */ +class GabrielaImageServerClient(baseUrl: String, val http: HttpClient) { + val baseUrl = baseUrl.removeSuffix("/") // Remove trailing slash + + val images = ImagesService(this) + val videos = VideosService(this) +} \ No newline at end of file diff --git a/client/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/client/services/ImagesService.kt b/client/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/client/services/ImagesService.kt new file mode 100644 index 0000000..93c3ea2 --- /dev/null +++ b/client/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/client/services/ImagesService.kt @@ -0,0 +1,58 @@ +package net.perfectdreams.gabrielaimageserver.client.services + +import net.perfectdreams.gabrielaimageserver.client.GabrielaImageServerClient +import net.perfectdreams.gabrielaimageserver.data.CortesFlowRequest +import net.perfectdreams.gabrielaimageserver.data.ManiaTitleCardRequest +import net.perfectdreams.gabrielaimageserver.data.PetPetRequest +import net.perfectdreams.gabrielaimageserver.data.SAMLogoRequest +import net.perfectdreams.gabrielaimageserver.data.ShipRequest +import net.perfectdreams.gabrielaimageserver.data.SingleImageRequest +import net.perfectdreams.gabrielaimageserver.data.TerminatorAnimeRequest +import net.perfectdreams.gabrielaimageserver.data.TobyTextBoxRequest +import net.perfectdreams.gabrielaimageserver.data.TwoImagesRequest + +class ImagesService(client: GabrielaImageServerClient) : Service(client) { + suspend fun ship(request: ShipRequest) = execute("/images/ship", request) + suspend fun petPet(request: PetPetRequest) = execute("/images/pet-pet", request) + suspend fun maniaTitleCard(request: ManiaTitleCardRequest) = execute("/images/mania-title-card", request) + suspend fun tobyTextBox(request: TobyTextBoxRequest) = execute("/images/toby-text-box", request) + + suspend fun invertColors(request: SingleImageRequest) = execute("/images/invert-colors", request) + suspend fun toBeContinued(request: SingleImageRequest) = execute("/images/to-be-continued", request) + suspend fun cepoDeMadeira(request: SingleImageRequest) = execute("/images/cepo-de-madeira", request) + suspend fun knucklesThrow(request: SingleImageRequest) = execute("/images/knuckles-throw", request) + suspend fun nichijouYuukoPaper(request: SingleImageRequest) = execute("/images/nichijou-yuuko-paper", request) + suspend fun getOverHere(request: SingleImageRequest) = execute("/images/get-over-here", request) + suspend fun drake(request: TwoImagesRequest) = execute("/images/drake", request) + suspend fun bolsoDrake(request: TwoImagesRequest) = execute("/images/bolso-drake", request) + suspend fun loriDrake(request: TwoImagesRequest) = execute("/images/lori-drake", request) + suspend fun trump(request: TwoImagesRequest) = execute("/images/trump", request) + suspend fun samLogo(request: SAMLogoRequest) = execute("/images/sam", request) + suspend fun terminatorAnime(request: TerminatorAnimeRequest) = execute("/images/terminator-anime", request) + suspend fun cortesFlow(path: String, request: CortesFlowRequest) = execute("/images/cortes-flow/$path", request) + + // ===[ SCALED IMAGES (with one single image) GENERATORS ]=== + suspend fun pepeDream(request: SingleImageRequest) = execute("/images/pepe-dream", request) + suspend fun loriScared(request: SingleImageRequest) = execute("/images/lori-scared", request) + suspend fun studiopolisTv(request: SingleImageRequest) = execute("/images/studiopolis-tv", request) + + // ===[ SKEWED IMAGES (with one single image) GENERATORS ]=== + suspend fun art(request: SingleImageRequest) = execute("/images/art", request) + suspend fun bobBurningPaper(request: SingleImageRequest) = execute("/images/bob-burning-paper", request) + suspend fun bolsoFrame(request: SingleImageRequest) = execute("/images/bolso-frame", request) + suspend fun bolsonaro(request: SingleImageRequest) = execute("/images/bolsonaro", request) + suspend fun bolsonaro2(request: SingleImageRequest) = execute("/images/bolsonaro2", request) + suspend fun briggsCover(request: SingleImageRequest) = execute("/images/briggs-cover", request) + suspend fun canellaDvd(request: SingleImageRequest) = execute("/images/canella-dvd", request) + suspend fun chicoAta(request: SingleImageRequest) = execute("/images/chico-ata", request) + suspend fun ednaldoBandeira(request: SingleImageRequest) = execute("/images/ednaldo-bandeira", request) + suspend fun ednaldoTv(request: SingleImageRequest) = execute("/images/ednaldo-tv", request) + suspend fun gessyAta(request: SingleImageRequest) = execute("/images/gessy-ata", request) + suspend fun loriAta(request: SingleImageRequest) = execute("/images/lori-ata", request) + suspend fun loriSign(request: SingleImageRequest) = execute("/images/lori-sign", request) + suspend fun monicaAta(request: SingleImageRequest) = execute("/images/monica-ata", request) + suspend fun passingPaper(request: SingleImageRequest) = execute("/images/passing-paper", request) + suspend fun romeroBritto(request: SingleImageRequest) = execute("/images/romero-britto", request) + suspend fun wolverineFrame(request: SingleImageRequest) = execute("/images/wolverine-frame", request) + suspend fun ripTv(request: SingleImageRequest) = execute("/images/rip-tv", request) +} \ No newline at end of file diff --git a/client/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/client/services/Service.kt b/client/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/client/services/Service.kt new file mode 100644 index 0000000..2f99abe --- /dev/null +++ b/client/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/client/services/Service.kt @@ -0,0 +1,53 @@ +package net.perfectdreams.gabrielaimageserver.client.services + +import io.ktor.client.call.* +import io.ktor.client.request.* +import io.ktor.client.statement.* +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.encodeToJsonElement +import kotlinx.serialization.json.jsonObject +import net.perfectdreams.gabrielaimageserver.client.GabrielaImageServerClient +import net.perfectdreams.gabrielaimageserver.data.ContentLengthTooLargeExceptionResponse +import net.perfectdreams.gabrielaimageserver.data.ErrorResponse +import net.perfectdreams.gabrielaimageserver.data.ImageNotFoundExceptionResponse +import net.perfectdreams.gabrielaimageserver.data.ImageTooLargeExceptionResponse +import net.perfectdreams.gabrielaimageserver.data.InternalServerErrorExceptionResponse +import net.perfectdreams.gabrielaimageserver.data.StreamExceedsLimitExceptionResponse +import net.perfectdreams.gabrielaimageserver.data.UntrustedURLExceptionResponse +import net.perfectdreams.gabrielaimageserver.exceptions.ContentLengthTooLargeException +import net.perfectdreams.gabrielaimageserver.exceptions.ImageNotFoundException +import net.perfectdreams.gabrielaimageserver.exceptions.ImageTooLargeException +import net.perfectdreams.gabrielaimageserver.exceptions.InternalServerErrorException +import net.perfectdreams.gabrielaimageserver.exceptions.StreamExceedsLimitException +import net.perfectdreams.gabrielaimageserver.exceptions.UntrustedURLException + +open class Service(private val client: GabrielaImageServerClient) { + private val apiVersion = "v2" + + suspend inline fun execute(endpoint: String, body: T) = execute(endpoint, Json.encodeToJsonElement(body).jsonObject) + + suspend fun execute(endpoint: String, body: JsonObject): ByteArray { + val response = client.http.post("${client.baseUrl}/api/$apiVersion$endpoint") { + this.body = body.toString() + } + + // If the status code is not between 400..499, then it means that it was (probably) a invalid input or something + if (response.status.value !in 200..299) { + // If it wasn't successful, let's try parsing the response! + val errorResponse = Json.decodeFromString(response.readText()) + + when (errorResponse) { + is ContentLengthTooLargeExceptionResponse -> throw ContentLengthTooLargeException() + is ImageNotFoundExceptionResponse -> throw ImageNotFoundException() + is ImageTooLargeExceptionResponse -> throw ImageTooLargeException() + is InternalServerErrorExceptionResponse -> throw InternalServerErrorException() + is StreamExceedsLimitExceptionResponse -> throw StreamExceedsLimitException() + is UntrustedURLExceptionResponse -> throw UntrustedURLException(errorResponse.url) + } + } + + return response.receive() + } +} \ No newline at end of file diff --git a/client/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/client/services/VideosService.kt b/client/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/client/services/VideosService.kt new file mode 100644 index 0000000..3fe38a3 --- /dev/null +++ b/client/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/client/services/VideosService.kt @@ -0,0 +1,13 @@ +package net.perfectdreams.gabrielaimageserver.client.services + +import net.perfectdreams.gabrielaimageserver.client.GabrielaImageServerClient +import net.perfectdreams.gabrielaimageserver.data.CocieloChavesRequest +import net.perfectdreams.gabrielaimageserver.data.FansExplainingRequest +import net.perfectdreams.gabrielaimageserver.data.SingleImageRequest + +class VideosService(client: GabrielaImageServerClient) : Service(client) { + suspend fun attackOnHeart(request: SingleImageRequest) = execute("/videos/attack-on-heart", request) + suspend fun carlyAaah(request: SingleImageRequest) = execute("/videos/carly-aaah", request) + suspend fun fansExplaining(request: FansExplainingRequest) = execute("/videos/fans-explaining", request) + suspend fun cocieloChaves(request: CocieloChavesRequest) = execute("/videos/cocielo-chaves", request) +} \ No newline at end of file diff --git a/gabriela-image-api/build.gradle.kts b/common/build.gradle.kts similarity index 68% rename from gabriela-image-api/build.gradle.kts rename to common/build.gradle.kts index e5393e9..2fda074 100644 --- a/gabriela-image-api/build.gradle.kts +++ b/common/build.gradle.kts @@ -1,7 +1,7 @@ -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile - plugins { - kotlin("multiplatform") version "1.4.20-M2" + kotlin("multiplatform") version "1.5.31" + kotlin("plugin.serialization") version "1.5.31" + `maven-publish` } group = "net.perfectdreams.imagegen" @@ -18,26 +18,17 @@ kotlin { } withJava() } - js { - browser { - binaries.executable() - testTask { - useKarma { - useChromeHeadless() - } - } - } - } sourceSets { - jvm().compilations["main"].defaultSourceSet { + commonMain { dependencies { + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.0") } } - js().compilations["main"].defaultSourceSet { + jvm().compilations["main"].defaultSourceSet { dependencies { - implementation(npm("buffer", "5.6.1")) + } } @@ -51,4 +42,12 @@ kotlin { } } } +} + +publishing { + publications { + register("PerfectDreams", MavenPublication::class.java) { + from(components["java"]) + } + } } \ No newline at end of file diff --git a/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/CocieloChavesRequest.kt b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/CocieloChavesRequest.kt new file mode 100644 index 0000000..d52e3b1 --- /dev/null +++ b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/CocieloChavesRequest.kt @@ -0,0 +1,12 @@ +package net.perfectdreams.gabrielaimageserver.data + +import kotlinx.serialization.Serializable + +@Serializable +data class CocieloChavesRequest( + val image1: SourceImageData, + val image2: SourceImageData, + val image3: SourceImageData, + val image4: SourceImageData, + val image5: SourceImageData, +) \ No newline at end of file diff --git a/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/CortesFlowRequest.kt b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/CortesFlowRequest.kt new file mode 100644 index 0000000..6097aa4 --- /dev/null +++ b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/CortesFlowRequest.kt @@ -0,0 +1,8 @@ +package net.perfectdreams.gabrielaimageserver.data + +import kotlinx.serialization.Serializable + +@Serializable +data class CortesFlowRequest( + val text: String +) \ No newline at end of file diff --git a/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/ErrorResponse.kt b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/ErrorResponse.kt new file mode 100644 index 0000000..a2452dc --- /dev/null +++ b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/ErrorResponse.kt @@ -0,0 +1,26 @@ +package net.perfectdreams.gabrielaimageserver.data + +import kotlinx.serialization.Serializable + +@Serializable +sealed class ErrorResponse { + abstract val reason: String? +} + +@Serializable +data class ContentLengthTooLargeExceptionResponse(override val reason: String?) : ErrorResponse() + +@Serializable +data class ImageTooLargeExceptionResponse(override val reason: String?) : ErrorResponse() + +@Serializable +data class StreamExceedsLimitExceptionResponse(override val reason: String?) : ErrorResponse() + +@Serializable +data class UntrustedURLExceptionResponse(override val reason: String?, val url: String) : ErrorResponse() + +@Serializable +data class ImageNotFoundExceptionResponse(override val reason: String?) : ErrorResponse() + +@Serializable +data class InternalServerErrorExceptionResponse(override val reason: String?) : ErrorResponse() \ No newline at end of file diff --git a/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/FansExplainingRequest.kt b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/FansExplainingRequest.kt new file mode 100644 index 0000000..f9818a7 --- /dev/null +++ b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/FansExplainingRequest.kt @@ -0,0 +1,21 @@ +package net.perfectdreams.gabrielaimageserver.data + +import kotlinx.serialization.Serializable + +@Serializable +data class FansExplainingRequest( + val section1Line1: String, + val section1Line2: String, + + val section2Line1: String, + val section2Line2: String, + + val section3Line1: String, + val section3Line2: String, + + val section4Line1: String, + val section4Line2: String, + + val section5Line1: String, + val section5Line2: String +) \ No newline at end of file diff --git a/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/ManiaTitleCardRequest.kt b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/ManiaTitleCardRequest.kt new file mode 100644 index 0000000..68a5e67 --- /dev/null +++ b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/ManiaTitleCardRequest.kt @@ -0,0 +1,9 @@ +package net.perfectdreams.gabrielaimageserver.data + +import kotlinx.serialization.Serializable + +@Serializable +data class ManiaTitleCardRequest( + val line1: String, + val line2: String? +) \ No newline at end of file diff --git a/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/MemeMakerRequest.kt b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/MemeMakerRequest.kt new file mode 100644 index 0000000..2c144ad --- /dev/null +++ b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/MemeMakerRequest.kt @@ -0,0 +1,10 @@ +package net.perfectdreams.gabrielaimageserver.data + +import kotlinx.serialization.Serializable + +@Serializable +data class MemeMakerRequest( + val image: SourceImageData, + val line1: String, + val line2: String? = null +) \ No newline at end of file diff --git a/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/PetPetRequest.kt b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/PetPetRequest.kt new file mode 100644 index 0000000..3cd2e02 --- /dev/null +++ b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/PetPetRequest.kt @@ -0,0 +1,10 @@ +package net.perfectdreams.gabrielaimageserver.data + +import kotlinx.serialization.Serializable + +@Serializable +data class PetPetRequest( + val image: SourceImageData, + val squish: Double = 0.875, + val delayBetweenFrames: Int = 7 +) \ No newline at end of file diff --git a/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/SAMLogoRequest.kt b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/SAMLogoRequest.kt new file mode 100644 index 0000000..014ab18 --- /dev/null +++ b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/SAMLogoRequest.kt @@ -0,0 +1,15 @@ +package net.perfectdreams.gabrielaimageserver.data + +import kotlinx.serialization.Serializable + +@Serializable +data class SAMLogoRequest( + val image: SourceImageData, + val type: LogoType +) { + enum class LogoType { + SAM_1, + SAM_2, + SAM_3 + } +} \ No newline at end of file diff --git a/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/ShipRequest.kt b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/ShipRequest.kt new file mode 100644 index 0000000..5a174f9 --- /dev/null +++ b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/ShipRequest.kt @@ -0,0 +1,10 @@ +package net.perfectdreams.gabrielaimageserver.data + +import kotlinx.serialization.Serializable + +@Serializable +data class ShipRequest( + val image1: SourceImageData, + val image2: SourceImageData, + val percentage: Int +) \ No newline at end of file diff --git a/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/SingleImageRequest.kt b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/SingleImageRequest.kt new file mode 100644 index 0000000..2e0eedc --- /dev/null +++ b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/SingleImageRequest.kt @@ -0,0 +1,8 @@ +package net.perfectdreams.gabrielaimageserver.data + +import kotlinx.serialization.Serializable + +@Serializable +data class SingleImageRequest( + val image: SourceImageData +) \ No newline at end of file diff --git a/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/SourceImageData.kt b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/SourceImageData.kt new file mode 100644 index 0000000..124de59 --- /dev/null +++ b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/SourceImageData.kt @@ -0,0 +1,12 @@ +package net.perfectdreams.gabrielaimageserver.data + +import kotlinx.serialization.Serializable + +@Serializable +sealed class SourceImageData + +@Serializable +data class URLImageData(val url: String) : SourceImageData() + +@Serializable +data class Base64ImageData(val data: String) : SourceImageData() \ No newline at end of file diff --git a/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/TerminatorAnimeRequest.kt b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/TerminatorAnimeRequest.kt new file mode 100644 index 0000000..391ed7b --- /dev/null +++ b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/TerminatorAnimeRequest.kt @@ -0,0 +1,9 @@ +package net.perfectdreams.gabrielaimageserver.data + +import kotlinx.serialization.Serializable + +@Serializable +data class TerminatorAnimeRequest( + val terminatorText: String, + val nonoMorikuboText: String +) \ No newline at end of file diff --git a/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/TobyTextBoxRequest.kt b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/TobyTextBoxRequest.kt new file mode 100644 index 0000000..98d14eb --- /dev/null +++ b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/TobyTextBoxRequest.kt @@ -0,0 +1,23 @@ +package net.perfectdreams.gabrielaimageserver.data + +import kotlinx.serialization.Serializable + +@Serializable +data class TobyTextBoxRequest( + val text: String, + val type: TextBoxType, + val portrait: String? = null, + val image: SourceImageData? = null, + val colorPortraitType: ColorPortraitType? = null, +) { + enum class TextBoxType { + ORIGINAL, + DARK_WORLD + } + + enum class ColorPortraitType { + COLORED, + BLACK_AND_WHITE, + SHADES_OF_GRAY + } +} \ No newline at end of file diff --git a/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/TwoImagesRequest.kt b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/TwoImagesRequest.kt new file mode 100644 index 0000000..21a7720 --- /dev/null +++ b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/data/TwoImagesRequest.kt @@ -0,0 +1,9 @@ +package net.perfectdreams.gabrielaimageserver.data + +import kotlinx.serialization.Serializable + +@Serializable +data class TwoImagesRequest( + val image1: SourceImageData, + val image2: SourceImageData +) \ No newline at end of file diff --git a/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/exceptions/ContentLengthTooLargeException.kt b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/exceptions/ContentLengthTooLargeException.kt new file mode 100644 index 0000000..1d92732 --- /dev/null +++ b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/exceptions/ContentLengthTooLargeException.kt @@ -0,0 +1,3 @@ +package net.perfectdreams.gabrielaimageserver.exceptions + +class ContentLengthTooLargeException : IllegalArgumentException() \ No newline at end of file diff --git a/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/exceptions/ImageNotFoundException.kt b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/exceptions/ImageNotFoundException.kt new file mode 100644 index 0000000..b679415 --- /dev/null +++ b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/exceptions/ImageNotFoundException.kt @@ -0,0 +1,3 @@ +package net.perfectdreams.gabrielaimageserver.exceptions + +class ImageNotFoundException : IllegalArgumentException() \ No newline at end of file diff --git a/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/exceptions/ImageTooLargeException.kt b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/exceptions/ImageTooLargeException.kt new file mode 100644 index 0000000..941ede1 --- /dev/null +++ b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/exceptions/ImageTooLargeException.kt @@ -0,0 +1,3 @@ +package net.perfectdreams.gabrielaimageserver.exceptions + +class ImageTooLargeException : IllegalArgumentException() \ No newline at end of file diff --git a/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/exceptions/InternalServerErrorException.kt b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/exceptions/InternalServerErrorException.kt new file mode 100644 index 0000000..8cd67fe --- /dev/null +++ b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/exceptions/InternalServerErrorException.kt @@ -0,0 +1,3 @@ +package net.perfectdreams.gabrielaimageserver.exceptions + +class InternalServerErrorException : RuntimeException() \ No newline at end of file diff --git a/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/exceptions/StreamExceedsLimitException.kt b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/exceptions/StreamExceedsLimitException.kt new file mode 100644 index 0000000..0cdeb98 --- /dev/null +++ b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/exceptions/StreamExceedsLimitException.kt @@ -0,0 +1,3 @@ +package net.perfectdreams.gabrielaimageserver.exceptions + +class StreamExceedsLimitException : RuntimeException() \ No newline at end of file diff --git a/image-generation-server/src/main/kotlin/net/perfectdreams/imageserver/utils/UntrustedURLException.kt b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/exceptions/UntrustedURLException.kt similarity index 62% rename from image-generation-server/src/main/kotlin/net/perfectdreams/imageserver/utils/UntrustedURLException.kt rename to common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/exceptions/UntrustedURLException.kt index fb740ff..d5dcf06 100644 --- a/image-generation-server/src/main/kotlin/net/perfectdreams/imageserver/utils/UntrustedURLException.kt +++ b/common/src/commonMain/kotlin/net/perfectdreams/gabrielaimageserver/exceptions/UntrustedURLException.kt @@ -1,3 +1,3 @@ -package net.perfectdreams.imageserver.utils +package net.perfectdreams.gabrielaimageserver.exceptions class UntrustedURLException(val url: String) : IllegalArgumentException("$url is not trusted!") \ No newline at end of file diff --git a/gabriela-image-api/src/commonMain/kotlin/net/perfectdreams/imagegen/generators/SingleSourceImageGenerator.kt b/gabriela-image-api/src/commonMain/kotlin/net/perfectdreams/imagegen/generators/SingleSourceImageGenerator.kt deleted file mode 100644 index 49b431c..0000000 --- a/gabriela-image-api/src/commonMain/kotlin/net/perfectdreams/imagegen/generators/SingleSourceImageGenerator.kt +++ /dev/null @@ -1,7 +0,0 @@ -package net.perfectdreams.imagegen.generators - -import net.perfectdreams.imagegen.graphics.Image - -interface SingleSourceImageGenerator { - fun generate(source: Image): Image -} \ No newline at end of file diff --git a/gabriela-image-api/src/commonMain/kotlin/net/perfectdreams/imagegen/generators/TwoSourceImagesGenerator.kt b/gabriela-image-api/src/commonMain/kotlin/net/perfectdreams/imagegen/generators/TwoSourceImagesGenerator.kt deleted file mode 100644 index a9aec06..0000000 --- a/gabriela-image-api/src/commonMain/kotlin/net/perfectdreams/imagegen/generators/TwoSourceImagesGenerator.kt +++ /dev/null @@ -1,7 +0,0 @@ -package net.perfectdreams.imagegen.generators - -import net.perfectdreams.imagegen.graphics.Image - -interface TwoSourceImagesGenerator { - fun generate(source1: Image, source2: Image): Image -} \ No newline at end of file diff --git a/gabriela-image-api/src/commonMain/kotlin/net/perfectdreams/imagegen/graphics/Graphics.kt b/gabriela-image-api/src/commonMain/kotlin/net/perfectdreams/imagegen/graphics/Graphics.kt deleted file mode 100644 index 886fbbd..0000000 --- a/gabriela-image-api/src/commonMain/kotlin/net/perfectdreams/imagegen/graphics/Graphics.kt +++ /dev/null @@ -1,5 +0,0 @@ -package net.perfectdreams.imagegen.graphics - -interface Graphics { - fun drawImage(image: Image, x: Int, y: Int) -} \ No newline at end of file diff --git a/gabriela-image-api/src/commonMain/kotlin/net/perfectdreams/imagegen/graphics/Image.kt b/gabriela-image-api/src/commonMain/kotlin/net/perfectdreams/imagegen/graphics/Image.kt deleted file mode 100644 index 0ef4df2..0000000 --- a/gabriela-image-api/src/commonMain/kotlin/net/perfectdreams/imagegen/graphics/Image.kt +++ /dev/null @@ -1,37 +0,0 @@ -package net.perfectdreams.imagegen.graphics - -interface Image { - enum class ScaleType { - SMOOTH - } - - enum class ImageType { - ARGB - } - - enum class FormatType { - PNG, - JPEG - } - - val width: Int - val height: Int - - fun getScaledInstance(width: Int, height: Int, scaleType: ScaleType): Image - fun getSkewedInstance( - x0: Float, y0: Float, // UL - x1: Float, y1: Float, // UR - x2: Float, y2: Float, // LR - x3: Float, y3: Float): Image // LL - - fun createGraphics(): Graphics - - fun toByteArray(type: FormatType): ByteArray - - fun clone(): Image { - val image = createImage(width, height) - val graphics = image.createGraphics() - graphics.drawImage(this, 0, 0) - return image - } -} \ No newline at end of file diff --git a/gabriela-image-api/src/commonMain/kotlin/net/perfectdreams/imagegen/graphics/createImage.kt b/gabriela-image-api/src/commonMain/kotlin/net/perfectdreams/imagegen/graphics/createImage.kt deleted file mode 100644 index e3fa725..0000000 --- a/gabriela-image-api/src/commonMain/kotlin/net/perfectdreams/imagegen/graphics/createImage.kt +++ /dev/null @@ -1,3 +0,0 @@ -package net.perfectdreams.imagegen.graphics - -expect fun createImage(width: Int, height: Int, imageType: Image.ImageType = Image.ImageType.ARGB): Image \ No newline at end of file diff --git a/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/gabrielaimagegen/imagegen/utils/Test.kt b/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/gabrielaimagegen/imagegen/utils/Test.kt deleted file mode 100644 index c6e383f..0000000 --- a/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/gabrielaimagegen/imagegen/utils/Test.kt +++ /dev/null @@ -1,69 +0,0 @@ -package net.perfectdreams.gabrielaimagegen.imagegen.utils - -import kotlinx.browser.document -import net.perfectdreams.imagegen.graphics.* -import net.perfectdreams.imagegen.utils.extensions.get2dContext -import org.w3c.dom.Element -import org.w3c.dom.HTMLCanvasElement -import org.w3c.dom.HTMLInputElement -import org.w3c.dom.Image -import org.w3c.dom.events.Event -import org.w3c.files.Blob -import org.w3c.files.FileReader -import org.w3c.files.get - -fun main() { - println("Hello!") - - /* val body = document.body!! - val selecter = document.querySelector("#myfile") - as HTMLInputElement - - val test = document.querySelector("#my-canvas") as HTMLCanvasElement - val ednaldoBandeiraGenerator = EdnaldoTVGenerator(JSImage(test)) - - (body.querySelector("#submitimage") as HTMLInputElement) - .onClick { - println("clicked") - - val reader = FileReader() - - reader.onload = { - println("Loaded") - - val image = Image() - image.src = reader.result - - image.onload = { - val sourceCanvas = createCanvas(image.width, image.height) - sourceCanvas.get2dContext().drawImage( - image, - 0.0, - 0.0 - ) - - val jsImage = JSImage(sourceCanvas) - - val result = ednaldoBandeiraGenerator.generate(jsImage) - - body.appendChild((result as JSImage).canvas) - - result as JSImage - val stuff = result.canvas.toDataURL("image/png") - - val image = Image() - image.src = stuff - body.appendChild(image) - - "".asDynamic() - } - - "a".asDynamic() - } - reader.readAsDataURL(selecter.files!![0] as Blob) - } */ -} - -fun Element.onClick(callback: (Event) -> (Unit)) { - this.addEventListener("click", callback) -} \ No newline at end of file diff --git a/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/imagegen/graphics/Buffer.kt b/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/imagegen/graphics/Buffer.kt deleted file mode 100644 index 2025ff7..0000000 --- a/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/imagegen/graphics/Buffer.kt +++ /dev/null @@ -1,44 +0,0 @@ -package net.perfectdreams.imagegen.graphics - -@JsName("Buffer") -external class Buffer { - companion object { - fun from(data: String, encoding: String): Buffer - fun alloc(size: Int): Buffer - fun allocUnsafe(size: Int): Buffer - } - - val length: Int - fun values(): dynamic - fun writeInt8(value: Int): Int - fun writeInt8(value: Int, offset: Int): Int -} - -fun Buffer.toByteArray(): ByteArray { - val imageByteArray = ByteArray(this.length) - - console.log(this.values()) - var idx = 0 - val values = this.values() - - while (true) { - val result = values.next() - if (result.done == true) - break - - imageByteArray[idx] = result.value - idx++ - } - - return imageByteArray -} - -fun ByteArray.toBuffer(): Buffer { - val buffer = Buffer.alloc(this.size) - - var currentOffset = 0 - for (byte in this) - currentOffset = buffer.writeInt8(byte.toInt(), currentOffset) - - return buffer -} \ No newline at end of file diff --git a/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/imagegen/graphics/CanvasUtils.kt b/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/imagegen/graphics/CanvasUtils.kt deleted file mode 100644 index 701cc94..0000000 --- a/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/imagegen/graphics/CanvasUtils.kt +++ /dev/null @@ -1,12 +0,0 @@ -package net.perfectdreams.imagegen.graphics - -import kotlinx.browser.document -import org.w3c.dom.HTMLCanvasElement - -fun createCanvas(width: Int, height: Int): HTMLCanvasElement { - return document.createElement("CANVAS") - .apply { - setAttribute("width", width.toString()) - setAttribute("height", height.toString()) - } as HTMLCanvasElement -} \ No newline at end of file diff --git a/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/imagegen/graphics/HackySkew.kt b/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/imagegen/graphics/HackySkew.kt deleted file mode 100644 index dadc6ee..0000000 --- a/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/imagegen/graphics/HackySkew.kt +++ /dev/null @@ -1,455 +0,0 @@ -package net.perfectdreams.imagegen.graphics - -import org.khronos.webgl.get -import org.w3c.dom.CanvasRenderingContext2D -import org.w3c.dom.HTMLCanvasElement -import kotlin.math.floor -import kotlin.math.max -import kotlin.math.min - -/** - * Used to skew an image. Adapted from 2 image processing classes developed - * by Jerry Huxtable (http://www.jhlabs.com) and released under - * the Apache License, Version 2.0. - * - * Ported to Kotlin/JS by MrPowerGamerBR - */ -class HackySkew(private val canvas: HTMLCanvasElement) { - data class Rectangle( - var x: Int, - var y: Int, - var width: Int, - var height: Int - ) - - protected var edgeAction = ZERO - protected var interpolation = BILINEAR - - protected lateinit var transformedSpace: Rectangle - protected lateinit var originalSpace: Rectangle - - private var x0: Float = 0.toFloat() - private var y0: Float = 0.toFloat() - private var x1: Float = 0.toFloat() - private var y1: Float = 0.toFloat() - private var x2: Float = 0.toFloat() - private var y2: Float = 0.toFloat() - private var x3: Float = 0.toFloat() - private var y3: Float = 0.toFloat() - private var dx1: Float = 0.toFloat() - private var dy1: Float = 0.toFloat() - private var dx2: Float = 0.toFloat() - private var dy2: Float = 0.toFloat() - private var dx3: Float = 0.toFloat() - private var dy3: Float = 0.toFloat() - private var A: Float = 0.toFloat() - private var B: Float = 0.toFloat() - private var C: Float = 0.toFloat() - private var D: Float = 0.toFloat() - private var E: Float = 0.toFloat() - private var F: Float = 0.toFloat() - private var G: Float = 0.toFloat() - private var H: Float = 0.toFloat() - private var I: Float = 0.toFloat() - - fun setCorners(x0: Float, y0: Float, - x1: Float, y1: Float, - x2: Float, y2: Float, - x3: Float, y3: Float): HTMLCanvasElement { - this.x0 = x0 - this.y0 = y0 - this.x1 = x1 - this.y1 = y1 - this.x2 = x2 - this.y2 = y2 - this.x3 = x3 - this.y3 = y3 - - dx1 = x1 - x2 - dy1 = y1 - y2 - dx2 = x3 - x2 - dy2 = y3 - y2 - dx3 = x0 - x1 + x2 - x3 - dy3 = y0 - y1 + y2 - y3 - - println("dx1: $dx1") - println("dy1: $dy1") - println("dx2: $dx2") - println("dy2: $dy2") - println("dx3: $dx3") - println("dy3: $dy3") - - val a11: Float - val a12: Float - val a13: Float - val a21: Float - val a22: Float - val a23: Float - val a31: Float - val a32: Float - - if (dx3 == 0f && dy3 == 0f) { - a11 = x1 - x0 - a21 = x2 - x1 - a31 = x0 - a12 = y1 - y0 - a22 = y2 - y1 - a32 = y0 - a23 = 0f - a13 = a23 - } else { - a13 = (dx3 * dy2 - dx2 * dy3) / (dx1 * dy2 - dy1 * dx2) - a23 = (dx1 * dy3 - dy1 * dx3) / (dx1 * dy2 - dy1 * dx2) - a11 = x1 - x0 + a13 * x1 - a21 = x3 - x0 + a23 * x3 - a31 = x0 - a12 = y1 - y0 + a13 * y1 - a22 = y3 - y0 + a23 * y3 - a32 = y0 - } - - A = a22 - a32 * a23 - B = a31 * a23 - a21 - C = a21 * a32 - a31 * a22 - D = a32 * a13 - a12 - E = a11 - a31 * a13 - F = a31 * a12 - a11 * a32 - G = a12 * a23 - a22 * a13 - H = a21 * a13 - a11 * a23 - I = a11 * a22 - a21 * a12 - - println("A: $A") - println("B: $B") - println("C: $C") - println("D: $D") - println("E: $E") - println("F: $F") - println("G: $G") - println("H: $H") - println("I: $I") - - return filter(canvas, createCanvas(canvas.width, canvas.height)) - } - - protected fun transformSpace(rect: Rectangle) { - rect.x = min(min(x0, x1), min(x2, x3)).toInt() - rect.y = min(min(y0, y1), min(y2, y3)).toInt() - rect.width = max(max(x0, x1), max(x2, x3)).toInt() - rect.x - rect.height = max(max(y0, y1), max(y2, y3)).toInt() - rect.y - } - - private fun filter(src: HTMLCanvasElement, dst: HTMLCanvasElement): HTMLCanvasElement { - val width = src.width - val height = src.height - console.log("width is $width, height is $height. Interpolation type is ${interpolation} Edge Action is ${edgeAction}") - - originalSpace = Rectangle(0, 0, width, height) - transformedSpace = Rectangle(0, 0, width, height) - console.log("teh og: $originalSpace") - transformSpace(transformedSpace) - console.log("after transform: $transformedSpace") - - console.log("gettin them pixels uwu") - val inPixels = getRGB(src, 0, 0, width, height) - console.log("there are ${inPixels.size} pixels, very owo") - - if (interpolation == NEAREST_NEIGHBOUR) - return filterPixelsNN(dst, width, height, inPixels, transformedSpace) - - val srcWidth1 = width - 1 - val srcHeight1 = height - 1 - val outWidth = transformedSpace.width - val outHeight = transformedSpace.height - val outX: Int - val outY: Int - //int index = 0; - val outPixels = IntArray(outWidth) - - outX = transformedSpace.x - outY = transformedSpace.y - val out = FloatArray(2) - - for (y in 0 until outHeight) { - for (x in 0 until outWidth) { - transformInverse(outX + x, outY + y, out) - val srcX = floor(out[0].toDouble()).toInt() - val srcY = floor(out[1].toDouble()).toInt() - val xWeight = out[0] - srcX - val yWeight = out[1] - srcY - val nw: Int - val ne: Int - val sw: Int - val se: Int - - if (srcX >= 0 && srcX < srcWidth1 && srcY >= 0 && srcY < srcHeight1) { - // Easy case, all corners are in the image - val i = width * srcY + srcX - nw = inPixels[i] - ne = inPixels[i + 1] - sw = inPixels[i + width] - se = inPixels[i + width + 1] - } else { - // Some of the corners are off the image - nw = getPixel(inPixels, srcX, srcY, width, height) - ne = getPixel(inPixels, srcX + 1, srcY, width, height) - sw = getPixel(inPixels, srcX, srcY + 1, width, height) - se = getPixel(inPixels, srcX + 1, srcY + 1, width, height) - } - outPixels[x] = bilinearInterpolate(xWeight, yWeight, nw, ne, sw, se) - } - setRGB(dst, outX, outY + y, transformedSpace.width, 1, outPixels) - } - return dst - } - - private fun getPixel(pixels: IntArray, x: Int, y: Int, width: Int, height: Int): Int { - if (x < 0 || x >= width || y < 0 || y >= height) { - when (edgeAction) { - ZERO -> return 0 - WRAP -> return pixels[mod(y, height) * width + mod(x, width)] - CLAMP -> return pixels[clamp(y, 0, height - 1) * width + clamp(x, 0, width - 1)] - else -> return 0 - } - } - return pixels[y * width + x] - } - - - protected fun filterPixelsNN(dst: HTMLCanvasElement, width: Int, - height: Int, inPixels: IntArray, transformedSpace: Rectangle - ): HTMLCanvasElement { - val outWidth = transformedSpace.width - val outHeight = transformedSpace.height - val outX: Int - val outY: Int - var srcX: Int - var srcY: Int - val outPixels = IntArray(outWidth) - - outX = transformedSpace.x - outY = transformedSpace.y - val rgb = IntArray(4) - val out = FloatArray(2) - - for (y in 0 until outHeight) { - for (x in 0 until outWidth) { - transformInverse(outX + x, outY + y, out) - srcX = out[0].toInt() - srcY = out[1].toInt() - // int casting rounds towards zero, so we check out[0] < 0, not srcX < 0 - if (out[0] < 0 || srcX >= width || out[1] < 0 || srcY >= height) { - val p: Int - when (edgeAction) { - ZERO -> p = 0 - WRAP -> p = inPixels[mod(srcY, height) * width + mod(srcX, width)] - CLAMP -> p = inPixels[clamp(srcY, 0, height - 1) * width + clamp(srcX, 0, width - 1)] - else -> p = 0 - } - outPixels[x] = p - } else { - val i = width * srcY + srcX - rgb[0] = inPixels[i] - outPixels[x] = inPixels[i] - } - } - setRGB(dst, 0, y, transformedSpace.width, 1, outPixels) - } - return dst - } - - - protected fun transformInverse(x: Int, y: Int, out: FloatArray) { - out[0] = originalSpace.width * (A * x + B * y + C) / (G * x + H * y + I) - out[1] = originalSpace.height * (D * x + E * y + F) / (G * x + H * y + I) - } - - /* -public Rectangle2D getBounds2D( BufferedImage src ) { - return new Rectangle(0, 0, src.getWidth(), src.getHeight()); -} - -public Point2D getPoint2D( Point2D srcPt, Point2D dstPt ) { - if ( dstPt == null ) - dstPt = new Point2D.Double(); - dstPt.setLocation( srcPt.getX(), srcPt.getY() ); - return dstPt; -} -*/ - - /** - * A convenience method for getting ARGB pixels from an image. This tries to avoid the performance - * penalty of BufferedImage.getRGB unmanaging the image. - */ - fun getRGB(image: HTMLCanvasElement, x: Int, y: Int, width: Int, height: Int): IntArray { - // console.log("Getting RGB at $x, $y width: $width height: $height") - val imageData = (image.getContext("2d") as CanvasRenderingContext2D).getImageData(x.toDouble(), y.toDouble(), width.toDouble(), height.toDouble()) - val intList = mutableListOf() - val data = imageData.data - - for (i in 0 until imageData.data.length step 4) { - val r = data[i].toInt() - val g = data[i + 1].toInt() - val b = data[i + 2].toInt() - val a = data[i + 3].toInt() - // let's pack! - val packedRGB = (a shl 24) + (r shl 16) + (g shl 8) + b - intList.add(packedRGB) - } - - return intList.toIntArray() - } - - /** - * A convenience method for setting ARGB pixels in an image. This tries to avoid the performance - * penalty of BufferedImage.setRGB unmanaging the image. - */ - fun setRGB(image: HTMLCanvasElement, x: Int, y: Int, width: Int, height: Int, pixels: IntArray) { - // console.log("Setting RGB at $x, $y $width $height There are ${pixels.size} array pixels") - val ctx = image.getContext("2d") as CanvasRenderingContext2D - var xCoordinate = x - var yCoordinate = y - - for (packedRGB in pixels) { - val a = packedRGB shr 24 and 0x000000FF - val r = packedRGB shr 16 and 0x000000FF - val g = packedRGB shr 8 and 0x000000FF - val b = packedRGB and 0x000000FF - - // console.log("rgba($r, $g, $b, ${a / 255})") - - ctx.fillStyle = "rgba($r, $g, $b, ${a / 255})" - ctx.fillRect(xCoordinate.toDouble(), yCoordinate.toDouble(), 1.toDouble(), 1.toDouble()) - xCoordinate++ - - if (xCoordinate >= canvas.width) { - xCoordinate = x - yCoordinate++ - } - } - } - - /** - * Clamp a value to an interval. - * @param a the lower clamp threshold - * @param b the upper clamp threshold - * @param x the input parameter - * @return the clamped value - */ - private fun clamp(x: Float, a: Float, b: Float): Float { - return if (x < a) a else if (x > b) b else x - } - - /** - * Clamp a value to an interval. - * @param a the lower clamp threshold - * @param b the upper clamp threshold - * @param x the input parameter - * @return the clamped value - */ - private fun clamp(x: Int, a: Int, b: Int): Int { - return if (x < a) a else if (x > b) b else x - } - - /** - * Return a mod b. This differs from the % operator with respect to negative numbers. - * @param a the dividend - * @param b the divisor - * @return a mod b - */ - private fun mod(a: Double, b: Double): Double { - var a = a - val n = (a / b).toInt() - - a -= n * b - return if (a < 0) a + b else a - } - - /** - * Return a mod b. This differs from the % operator with respect to negative numbers. - * @param a the dividend - * @param b the divisor - * @return a mod b - */ - private fun mod(a: Float, b: Float): Float { - var a = a - val n = (a / b).toInt() - - a -= n * b - return if (a < 0) a + b else a - } - - /** - * Return a mod b. This differs from the % operator with respect to negative numbers. - * @param a the dividend - * @param b the divisor - * @return a mod b - */ - private fun mod(a: Int, b: Int): Int { - var a = a - val n = a / b - - a -= n * b - return if (a < 0) a + b else a - } - - - /** - * Bilinear interpolation of ARGB values. - * @param x the X interpolation parameter 0..1 - * @param y the y interpolation parameter 0..1 - * @return the interpolated value - */ - private fun bilinearInterpolate(x: Float, y: Float, nw: Int, ne: Int, sw: Int, se: Int): Int { - var m0: Float - var m1: Float - val a0 = nw shr 24 and 0xff - val r0 = nw shr 16 and 0xff - val g0 = nw shr 8 and 0xff - val b0 = nw and 0xff - val a1 = ne shr 24 and 0xff - val r1 = ne shr 16 and 0xff - val g1 = ne shr 8 and 0xff - val b1 = ne and 0xff - val a2 = sw shr 24 and 0xff - val r2 = sw shr 16 and 0xff - val g2 = sw shr 8 and 0xff - val b2 = sw and 0xff - val a3 = se shr 24 and 0xff - val r3 = se shr 16 and 0xff - val g3 = se shr 8 and 0xff - val b3 = se and 0xff - - val cx = 1.0f - x - val cy = 1.0f - y - - m0 = cx * a0 + x * a1 - m1 = cx * a2 + x * a3 - val a = (cy * m0 + y * m1).toInt() - - m0 = cx * r0 + x * r1 - m1 = cx * r2 + x * r3 - val r = (cy * m0 + y * m1).toInt() - - m0 = cx * g0 + x * g1 - m1 = cx * g2 + x * g3 - val g = (cy * m0 + y * m1).toInt() - - m0 = cx * b0 + x * b1 - m1 = cx * b2 + x * b3 - val b = (cy * m0 + y * m1).toInt() - - return a shl 24 or (r shl 16) or (g shl 8) or b - } - - companion object { - - val ZERO = 0 - val CLAMP = 1 - val WRAP = 2 - - val NEAREST_NEIGHBOUR = 0 - val BILINEAR = 1 - } - - -} //end skew class \ No newline at end of file diff --git a/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/imagegen/graphics/JSGraphics.kt b/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/imagegen/graphics/JSGraphics.kt deleted file mode 100644 index e845a90..0000000 --- a/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/imagegen/graphics/JSGraphics.kt +++ /dev/null @@ -1,10 +0,0 @@ -package net.perfectdreams.imagegen.graphics - -import org.w3c.dom.CanvasRenderingContext2D - -class JSGraphics(val context: CanvasRenderingContext2D) : Graphics { - override fun drawImage(image: Image, x: Int, y: Int) { - image as JSImage - context.drawImage((image.canvas.getContext("2d") as CanvasRenderingContext2D).canvas, x.toDouble(), y.toDouble()) - } -} \ No newline at end of file diff --git a/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/imagegen/graphics/JSImage.kt b/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/imagegen/graphics/JSImage.kt deleted file mode 100644 index 6b64cd1..0000000 --- a/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/imagegen/graphics/JSImage.kt +++ /dev/null @@ -1,62 +0,0 @@ -package net.perfectdreams.imagegen.graphics - -import net.perfectdreams.imagegen.utils.extensions.get2dContext -import org.w3c.dom.CanvasRenderingContext2D -import org.w3c.dom.HTMLCanvasElement - -class JSImage(val canvas: HTMLCanvasElement) : Image { - override val width: Int - get() = canvas.width - override val height: Int - get() = canvas.height - - override fun getScaledInstance(width: Int, height: Int, scaleType: Image.ScaleType): Image { - // Clonar imagem original - val scaledImage = createCanvas(width, height) - val ctx = scaledImage.getContext("2d") as CanvasRenderingContext2D - ctx.drawImage(this.canvas.get2dContext().canvas, 0.0, 0.0, width.toDouble(), height.toDouble()) - - println(scaledImage.width) - println(scaledImage.height) - - return JSImage(scaledImage) - } - - override fun getSkewedInstance(x0: Float, y0: Float, x1: Float, y1: Float, x2: Float, y2: Float, x3: Float, y3: Float): Image { - return JSImage( - HackySkew(canvas) - .setCorners( - x0, y0, - x1, y1, - x2, y2, - x3, y3 - ) - ) - } - - override fun createGraphics(): Graphics { - return JSGraphics(canvas.get2dContext()) - } - - override fun toByteArray(type: Image.FormatType): ByteArray { - val dataUrlFormat = when (type) { - Image.FormatType.PNG -> "image/png" - else -> throw IllegalArgumentException("Unsupported format $type") - } - - val dataUrl = canvas.toDataURL(dataUrlFormat) - val dataBase64 = dataUrl.split("base64,").last() - val buf = Buffer.from(dataBase64, "base64") - - return buf.toByteArray() - } - - /* override fun toByteArray(): ByteArray { - val ctx = canvas.getContext("2d") - val dataUrl = ctx.canvas.toDataURL("image/png") - val dataBase64 = dataUrl.split("base64,").last() - val buf = Buffer.from(dataBase64, "base64") - - return buf.toByteArray() - } */ -} \ No newline at end of file diff --git a/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/imagegen/graphics/createImage.kt b/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/imagegen/graphics/createImage.kt deleted file mode 100644 index bffa971..0000000 --- a/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/imagegen/graphics/createImage.kt +++ /dev/null @@ -1,5 +0,0 @@ -package net.perfectdreams.imagegen.graphics - -actual fun createImage(width: Int, height: Int, imageType: Image.ImageType): Image { - return JSImage(createCanvas(width, height)) -} \ No newline at end of file diff --git a/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/imagegen/utils/extensions/CanvasElementExtension.kt b/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/imagegen/utils/extensions/CanvasElementExtension.kt deleted file mode 100644 index 43f7c8c..0000000 --- a/gabriela-image-api/src/jsMain/kotlin/net/perfectdreams/imagegen/utils/extensions/CanvasElementExtension.kt +++ /dev/null @@ -1,6 +0,0 @@ -package net.perfectdreams.imagegen.utils.extensions - -import org.w3c.dom.CanvasRenderingContext2D -import org.w3c.dom.HTMLCanvasElement - -fun HTMLCanvasElement.get2dContext() = this.getContext("2d") as CanvasRenderingContext2D \ No newline at end of file diff --git a/gabriela-image-api/src/jvmMain/kotlin/net/perfectdreams/imagegen/graphics/JVMGraphics.kt b/gabriela-image-api/src/jvmMain/kotlin/net/perfectdreams/imagegen/graphics/JVMGraphics.kt deleted file mode 100644 index 76d3e61..0000000 --- a/gabriela-image-api/src/jvmMain/kotlin/net/perfectdreams/imagegen/graphics/JVMGraphics.kt +++ /dev/null @@ -1,8 +0,0 @@ -package net.perfectdreams.imagegen.graphics - -class JVMGraphics(val handle: java.awt.Graphics) : Graphics { - override fun drawImage(image: Image, x: Int, y: Int) { - image as JVMImage - handle.drawImage(image.handle, x, y, null) - } -} \ No newline at end of file diff --git a/gabriela-image-api/src/jvmMain/kotlin/net/perfectdreams/imagegen/graphics/JVMImage.kt b/gabriela-image-api/src/jvmMain/kotlin/net/perfectdreams/imagegen/graphics/JVMImage.kt deleted file mode 100644 index c3ce240..0000000 --- a/gabriela-image-api/src/jvmMain/kotlin/net/perfectdreams/imagegen/graphics/JVMImage.kt +++ /dev/null @@ -1,86 +0,0 @@ -package net.perfectdreams.imagegen.graphics - -import java.awt.image.BufferedImage -import java.io.ByteArrayOutputStream -import java.lang.IllegalArgumentException -import javax.imageio.ImageIO - -class JVMImage(val handle: java.awt.Image) : Image { - override val width: Int - get() = handle.getWidth(null) - override val height: Int - get() = handle.getHeight(null) - - override fun getScaledInstance(width: Int, height: Int, scaleType: Image.ScaleType): JVMImage { - val hints = when (scaleType) { - Image.ScaleType.SMOOTH -> java.awt.Image.SCALE_SMOOTH - } - return JVMImage(handle.getScaledInstance(width, height, hints)) - } - - override fun getSkewedInstance(x0: Float, y0: Float, x1: Float, y1: Float, x2: Float, y2: Float, x3: Float, y3: Float): Image { - val image = LorittaImage(toBufferedImage(handle)) - - image.setCorners( - x0, y0, - x1, y1, - x2, y2, - x3, y3 - ) - - return JVMImage(image.bufferedImage) - } - - override fun createGraphics(): Graphics { - return JVMGraphics(handle.graphics) - } - - override fun toByteArray(type: Image.FormatType): ByteArray { - val output = object : ByteArrayOutputStream() { - @Synchronized - override fun toByteArray(): ByteArray { - return this.buf - } - } - - val bufferedImage = if (handle !is BufferedImage) - toBufferedImage(handle) - else - handle - - ImageIO.write( - bufferedImage, - when (type) { - Image.FormatType.PNG -> "png" - Image.FormatType.JPEG -> "jpg" - else -> throw IllegalArgumentException("Unsupported format $type") - }, - output - ) - - return output.toByteArray() - } - - /** - * Converts a given Image into a BufferedImage - * - * @param img The Image to be converted - * @return The converted BufferedImage - */ - private fun toBufferedImage(img: java.awt.Image): BufferedImage { - if (img is BufferedImage) { - return img - } - - // Create a buffered image with transparency - val bimage = BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB) - - // Draw the image on to the buffered image - val bGr = bimage.createGraphics() - bGr.drawImage(img, 0, 0, null) - bGr.dispose() - - // Return the buffered image - return bimage - } -} \ No newline at end of file diff --git a/gabriela-image-api/src/jvmMain/kotlin/net/perfectdreams/imagegen/graphics/createImage.kt b/gabriela-image-api/src/jvmMain/kotlin/net/perfectdreams/imagegen/graphics/createImage.kt deleted file mode 100644 index 4e44b96..0000000 --- a/gabriela-image-api/src/jvmMain/kotlin/net/perfectdreams/imagegen/graphics/createImage.kt +++ /dev/null @@ -1,8 +0,0 @@ -package net.perfectdreams.imagegen.graphics - -import net.perfectdreams.imagegen.graphics.Image -import java.awt.image.BufferedImage - -actual fun createImage(width: Int, height: Int, imageType: Image.ImageType): Image { - return JVMImage(BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)) -} \ No newline at end of file diff --git a/image-generation-browser/backend/build.gradle.kts b/image-generation-browser/backend/build.gradle.kts deleted file mode 100644 index 789b7b2..0000000 --- a/image-generation-browser/backend/build.gradle.kts +++ /dev/null @@ -1,67 +0,0 @@ -plugins { - kotlin("jvm") version "1.4.10" - kotlin("plugin.serialization") version "1.4.10" apply true -} - -group = "net.perfectdreams.imagegeneratorserver" -version = "1.0-SNAPSHOT" - -repositories { - mavenCentral() - jcenter() - maven("https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven") -} - -dependencies { - implementation(kotlin("stdlib-jdk8")) - api(project(":image-generators")) - api(project(":image-generation-browser:generators-info")) - - // Logging Stuff - implementation("ch.qos.logback:logback-classic:1.3.0-alpha5") - implementation("io.github.microutils:kotlin-logging:1.8.3") - - api("io.ktor:ktor-server-core:1.4.1") - api("io.ktor:ktor-server-netty:1.4.1") - api("io.ktor:ktor-html-builder:1.4.0") - api("org.jetbrains.kotlinx:kotlinx-html-jvm:0.7.2") - - api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.0") - api("org.jetbrains.kotlinx:kotlinx-serialization-hocon:1.0.0") -} - -tasks { - val fatJar = task("fatJar", type = Jar::class) { - // We only want to execute this AFTER everything was built, not during the configuration phase - // doLast { - /* println("Building fat jar for ${project.name}...") - - archiveBaseName.set("${project.name}-fat") - - manifest { - attributes["Main-Class"] = "net.perfectdreams.imageserver.GabrielaImageGenLauncher" - attributes["Class-Path"] = - configurations.runtimeClasspath.get().joinToString(" ", transform = { "libs/" + it.name }) - } - - val libs = File(rootProject.projectDir, "libs") - // libs.deleteRecursively() - libs.mkdirs() - - from(configurations.runtimeClasspath.get().mapNotNull { - val output = File(libs, it.name) - - if (!output.exists()) - it.copyTo(output, true) - - null - }) - - with(jar.get() as CopySpec) */ - // } - } - - "build" { - dependsOn(fatJar) - } -} \ No newline at end of file diff --git a/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/CLITest.kt b/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/CLITest.kt deleted file mode 100644 index ecb66ef..0000000 --- a/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/CLITest.kt +++ /dev/null @@ -1,75 +0,0 @@ -package net.perfectdreams.imageserver - -import net.perfectdreams.imagegen.generators.BasicScaledImageGenerator -import net.perfectdreams.imagegen.generators.skewed.EdnaldoBandeiraGenerator -import net.perfectdreams.imagegen.generators.BasicSkewedImageGenerator -import net.perfectdreams.imagegen.graphics.Image -import net.perfectdreams.imagegen.graphics.JVMImage -import java.io.File -import java.lang.IllegalArgumentException -import javax.imageio.ImageIO - -fun convertToSnakeCase(input: String): String { - val x = input.removeSuffix("Test").removeSuffix("Generator") - - val newString = StringBuilder() - - for (index in x.indices) { - val charAt = x[index] - val nextChar = x.getOrNull(index + 1) - - if (charAt.isLowerCase() && nextChar?.isUpperCase() == true) { - newString.append(charAt.toLowerCase()) - newString.append("_") - } else { - newString.append(charAt.toLowerCase()) - } - } - - return newString.toString() -} - -fun main() { - while (true) { - val line = readLine()!! - - val (generatorType, filePath) = line.split(" ") - - val generatorPath = convertToSnakeCase(generatorType) - - val generator = Class.forName("net.perfectdreams.imagegen.generators.$generatorType") - .getConstructor(Image::class.java) - .newInstance( - JVMImage( - ImageIO.read( - loadFromJar(EdnaldoBandeiraGenerator::class.java, "/$generatorPath/template.png") - ) - ) - ) - - val image = if (generator is BasicScaledImageGenerator) { - generator.generate( - JVMImage( - ImageIO.read( - File(filePath) - ) - ) - ) - } else if (generator is BasicSkewedImageGenerator) { - generator.generate( - JVMImage( - ImageIO.read( - File(filePath) - ) - ) - ) - } else throw IllegalArgumentException("CLI doesn't support $generator") - - File("./$generatorPath.png") - .writeBytes(image.toByteArray(Image.FormatType.PNG)) - - println("Done!") - } -} - -fun loadFromJar(clazz: Class<*>, inputPath: String) = clazz.getResourceAsStream(inputPath) \ No newline at end of file diff --git a/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/GabrielaImageGen.kt b/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/GabrielaImageGen.kt deleted file mode 100644 index faff36b..0000000 --- a/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/GabrielaImageGen.kt +++ /dev/null @@ -1,126 +0,0 @@ -package net.perfectdreams.imageserver - -import io.ktor.application.* -import io.ktor.html.* -import io.ktor.http.* -import io.ktor.http.content.* -import io.ktor.response.* -import io.ktor.routing.* -import io.ktor.server.engine.* -import io.ktor.server.netty.* -import kotlinx.html.* -import mu.KotlinLogging -import net.perfectdreams.imagegen.generators.GeneratorsInfo -import net.perfectdreams.imageserver.routes.BaseRoute - -class GabrielaImageGen { - companion object { - private val logger = KotlinLogging.logger {} - } - - val routes = mutableListOf() - - fun start() { - val allGenerators = GeneratorsInfo.imageGenerators - - val server = embeddedServer(Netty, port = 8001) { - routing { - get("/") { - call.respondHtml { - head { - title("Gabriela Image Generation") - styleLink("/assets/css/style.css") - script(src = "/assets/js/frontend.js") {} - } - - body { - nav(classes = "navigation-bar fixed") { - div(classes = "left-side-entries") { - div(classes = "entry") { - + "OwO" - } - } - } - div(classes = "dummy-navigation-bar") {} - - div(classes = "centered-text") { - id = "one-column" - - div(classes = "media") { - div(classes = "media-body") { - p { - repeat(25) { - +"owo whats this? " - } - } - } - - div(classes = "media-figure") { - img(src = "/assets/img/gabriela_draw.png") { - style = "width: auto;" - } - } - } - - for (generator in allGenerators) { - div { - a(href = "/${generator.urlPath}") { - +generator.name - } - } - } - } - } - } - } - - for (generator in allGenerators) { - get("/${generator.path.replace("_", "-")}/") { - call.respondHtml { - head { - title("Generator ${generator.name}") - styleLink("/assets/css/style.css") - script(src = "/assets/js/frontend.js") {} - } - - body { - nav(classes = "navigation-bar fixed") { - div(classes = "left-side-entries") { - div(classes = "entry") { - + "OwO" - } - } - } - div(classes = "dummy-navigation-bar") {} - - div(classes = "centered-text") { - id = "one-column" - - h1 { - + generator.name - } - - div { - id = "generator-wrapper" - } - } - } - } - } - } - - static("/assets/") { - resources("/static/assets/") - } - - static("/assets/img/templates/") { - resources("/image_templates/") - } - - for (route in routes) - route.register(this) - } - } - server.start(wait = true) - } -} \ No newline at end of file diff --git a/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/GabrielaImageGenLauncher.kt b/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/GabrielaImageGenLauncher.kt deleted file mode 100644 index 28cce2a..0000000 --- a/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/GabrielaImageGenLauncher.kt +++ /dev/null @@ -1,11 +0,0 @@ -package net.perfectdreams.imageserver - -import javax.imageio.ImageIO - -object GabrielaImageGenLauncher { - @JvmStatic - fun main(args: Array) { - val m = GabrielaImageGen() - m.start() - } -} \ No newline at end of file diff --git a/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/routes/BaseRoute.kt b/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/routes/BaseRoute.kt deleted file mode 100644 index 1a95150..0000000 --- a/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/routes/BaseRoute.kt +++ /dev/null @@ -1,37 +0,0 @@ -package net.perfectdreams.imageserver.routes - -import io.ktor.application.ApplicationCall -import io.ktor.application.call -import io.ktor.http.HttpMethod -import io.ktor.routing.* -import io.ktor.util.pipeline.PipelineInterceptor - -abstract class BaseRoute(val path: String) { - abstract suspend fun onRequest(call: ApplicationCall) - - fun register(routing: Routing) = registerWithPath(routing, path) { onRequest(call) } - - fun registerWithPath(routing: Routing, path: String, callback: PipelineInterceptor) { - val method = getMethod() - when (method) { - HttpMethod.Get -> routing.get(path, callback) - HttpMethod.Post -> routing.post(path, callback) - HttpMethod.Patch -> routing.patch(path, callback) - HttpMethod.Put -> routing.put(path, callback) - HttpMethod.Delete -> routing.delete(path, callback) - else -> routing.get(path, callback) - } - } - - open fun getMethod(): HttpMethod { - val className = this::class.simpleName?.toLowerCase() ?: "Unknown" - return when { - className.startsWith("get") -> HttpMethod.Get - className.startsWith("post") -> HttpMethod.Post - className.startsWith("patch") -> HttpMethod.Patch - className.startsWith("put") -> HttpMethod.Put - className.startsWith("delete") -> HttpMethod.Delete - else -> HttpMethod.Get - } - } -} \ No newline at end of file diff --git a/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/routes/RouteUtils.kt b/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/routes/RouteUtils.kt deleted file mode 100644 index ce1525d..0000000 --- a/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/routes/RouteUtils.kt +++ /dev/null @@ -1,28 +0,0 @@ -package net.perfectdreams.imageserver.routes - -object RouteUtils { - /** - * Converts the [input] to kebab-case - * - * @return the string converted to kebab case - */ - fun convertToKebabCase(input: String): String { - val x = input.removeSuffix("Generator") - - val newString = StringBuilder() - - for (index in x.indices) { - val charAt = x[index] - val nextChar = x.getOrNull(index + 1) - - if (charAt.isLowerCase() && nextChar?.isUpperCase() == true) { - newString.append(charAt.toLowerCase()) - newString.append("-") - } else { - newString.append(charAt.toLowerCase()) - } - } - - return newString.toString() - } -} \ No newline at end of file diff --git a/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/utils/Constants.kt b/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/utils/Constants.kt deleted file mode 100644 index a4d3326..0000000 --- a/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/utils/Constants.kt +++ /dev/null @@ -1,5 +0,0 @@ -package net.perfectdreams.imageserver.utils - -object Constants { - const val API_VERSION = "v1" -} \ No newline at end of file diff --git a/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/utils/DrakeTest.kt b/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/utils/DrakeTest.kt deleted file mode 100644 index 24252b5..0000000 --- a/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/utils/DrakeTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -package net.perfectdreams.imageserver.utils - -import net.perfectdreams.imagegen.generators.drake.BolsoDrakeGenerator -import net.perfectdreams.imagegen.generators.drake.LoriDrakeGenerator -import net.perfectdreams.imagegen.graphics.Image -import net.perfectdreams.imagegen.graphics.JVMImage -import java.io.File -import javax.imageio.ImageIO - -fun main() { - println("Test") - val samBadge = - JVMImage( - ImageIO.read( - BolsoDrakeGenerator::class.java.getResourceAsStream("/image_templates/rip_tv/template.png") - ) - ) - - val f = File("C:\\Users\\Leonardo\\Documents\\IdeaProjects\\GabrielaImageGen\\image-generators\\src\\jvmTest\\resources\\sources\\cat_passion.jpg") - - println( - f.exists() - ) - - val catPassion = - JVMImage( - ImageIO.read( - File("C:\\Users\\Leonardo\\Documents\\IdeaProjects\\GabrielaImageGen\\image-generators\\src\\jvmTest\\resources\\sources\\cat_passion.jpg") - ) - ) - - val samGenerator = LoriDrakeGenerator(samBadge) - - File("generated_sam.png") - .writeBytes( - samGenerator.generate(catPassion, catPassion) - .toByteArray(Image.FormatType.PNG) - ) - - File("generated_sam2.png") - .writeBytes( - samGenerator.generate(catPassion, catPassion) - .toByteArray(Image.FormatType.PNG) - ) -} \ No newline at end of file diff --git a/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/utils/Gifsicle.kt b/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/utils/Gifsicle.kt deleted file mode 100644 index d04323b..0000000 --- a/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/utils/Gifsicle.kt +++ /dev/null @@ -1,39 +0,0 @@ -package net.perfectdreams.imageserver.utils - -import mu.KotlinLogging -import java.io.File -import kotlin.concurrent.thread - -class Gifsicle(val binaryPath: File) { - companion object { - private val logger = KotlinLogging.logger {} - } - - fun optimizeGIF(input: ByteArray, lossy: Int = 200): ByteArray { - logger.info { "Optimizing GIF in Gifsicle! Input has ${input.size} bytes!!" } - val processBuilder = ProcessBuilder( - binaryPath.toString(), - "-w", // ignore warnings - "--careful" // avoids discord bugs - // "-O3", - // "--lossy=$lossy", - // "--colors", - // "256" - ).redirectErrorStream(true) - - val process = processBuilder.start() - - val outputStream = process.outputStream - - logger.info { "Writing bytes..." } - outputStream.write(input) - logger.info { "Flushing bytes..." } - outputStream.flush() - logger.info { "Closing output stream..." } - outputStream.close() - - process.waitFor() - - return process.inputStream.readAllBytes() - } -} \ No newline at end of file diff --git a/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/utils/ImageUtils.kt b/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/utils/ImageUtils.kt deleted file mode 100644 index deb660a..0000000 --- a/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/utils/ImageUtils.kt +++ /dev/null @@ -1,29 +0,0 @@ -package net.perfectdreams.imageserver.utils - -import java.awt.Image -import java.awt.image.BufferedImage - -object ImageUtils { - /** - * Converts a given Image into a BufferedImage - * - * @param img The Image to be converted - * @return The converted BufferedImage - */ - fun toBufferedImage(img: Image): BufferedImage { - if (img is BufferedImage) { - return img - } - - // Create a buffered image with transparency - val bimage = BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB) - - // Draw the image on to the buffered image - val bGr = bimage.createGraphics() - bGr.drawImage(img, 0, 0, null) - bGr.dispose() - - // Return the buffered image - return bimage - } -} \ No newline at end of file diff --git a/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/utils/extensions/ImageExtensions.kt b/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/utils/extensions/ImageExtensions.kt deleted file mode 100644 index 4d5f8b3..0000000 --- a/image-generation-browser/backend/src/main/kotlin/net/perfectdreams/imageserver/utils/extensions/ImageExtensions.kt +++ /dev/null @@ -1,9 +0,0 @@ -package net.perfectdreams.imageserver.utils.extensions - -import net.perfectdreams.imageserver.utils.ImageUtils -import java.awt.Image -import java.awt.image.BufferedImage - -fun Image.toBufferedImage() : BufferedImage { - return ImageUtils.toBufferedImage(this) -} diff --git a/image-generation-browser/backend/src/main/resources/static/assets/css/lovely-style/README.md b/image-generation-browser/backend/src/main/resources/static/assets/css/lovely-style/README.md deleted file mode 100644 index 1a54165..0000000 --- a/image-generation-browser/backend/src/main/resources/static/assets/css/lovely-style/README.md +++ /dev/null @@ -1,207 +0,0 @@ - -

-

💞 Lovely Design 💞

- -

- - -

- -> "What a lovely design!" - -Lovely Design is a collection of tiny (S)CSS classes that can be reused in different projects. - -Yes, there already is a lot of other "CSS Frameworks" like [Bootstrap](https://getbootstrap.com/), [Bulma](https://bulma.io/), [Tailwind](https://tailwindcss.com/)... but we decided to create our own smol framework because... -* We wanted something small that can be easily integrated into already existing projects, so nothing that when you include it in your project it already styles a lot of stuff that you *don't* want to be styled. -* We didn't want a complete JS + CSS framework or something that requires a lot of JS to work well. -* We didn't want a framework that *forces* you to do your own stuff their way. "It is my code so I want to code it my own way!" -* We like to reinvent the wheel. 🤪 - -## 🤔 How to use? - -Clone the repository - -Create a style.scss file - -Some packages requires a `primary-color` variable -`$primary-color: #00c0ff;` - -Lovely Style works in a "programming" like style, you need to *import* the file for it to be added to your spreadsheet. If a style requires argument, you need to call *include* them. - -### Styles - -#### reset.scss -```scss -@import 'lovely-style/rainbow.scss' -``` - -Because some browsers are dumb and provide their own styles, causing inconsistencies between browsers - -#### body.scss -```scss -@import 'lovely-style/body.scss' - -body { - @include lovely-body($background-color: #f3f3f3, $text-color: #333333, $hide-overflow-x: false) -} -``` - -Creates a pretty "default" body, all variables are optional. - -There is also a `hide-overflow-x`, useful if you have those pesky bugs that cause a horizontal scroll bar to show up. - -#### buttons.scss -```scss -@import 'lovely-style/buttons.scss' - -lovely-button-colors() // Imports default button colors - -// You can also create your own colors -button-color("color-name", #fafafa) -``` - -Buttons! - -```html -
-This is a button -
- -
-Angry button grrr -
- -text text text owo text text text -``` - -#### emotes.scss -```scss -@import 'lovely-style/emotes.scss' -``` -Sometimes you want to have *custom* emotes (with images) in your texts, `emotes.scss` allows you to place inline image emotes, and it looks cool! - -```html -I love you! -``` - -#### fancy-hr.scss -```scss -@import 'lovely-style/fancy-hr.scss' -``` -A fancy `
` tag, because browser's default is ugly. - -#### fancy-links.scss -```scss -@import 'lovely-style/fancy-links.scss' -``` -A fancy `` tag, because browser's default is ugly. - - -#### fancy-table.scss -```scss -@import 'lovely-style/fancy-table.scss' -``` -Fancy tables with horizontal divisors between cells and a nice table header with your website's primary color! - -```html - - - - - - - - - - - - - - - - - -
NameDate
Lovely Style2020
Loritta2017
SparklyPower2014
-``` - -#### navigation-bar.scss -```scss -@import 'lovely-style/navigation-bar.scss' - -@include navigation-bar($navbar-color: $primary-color, $navbar-font-family: "Oswald, Impact, Arial, sans-serif", $navbar-height: 46px); -``` - -A nice navigation bar for your website! - -```html -