package io.nyris.example import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.Color import android.graphics.Paint import android.graphics.RectF import okhttp3.MediaType.Companion.toMediaType import okhttp3.MultipartBody import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.RequestBody.Companion.toRequestBody import java.io.ByteArrayOutputStream import kotlin.math.roundToInt import kotlin.math.sqrt /** Area-based resize used by the nyris example web app (includes upscaling small sources). */ fun jpegForSearch(source: Bitmap, maxSide: Int = 1024, quality: Int = 90): ByteArray { val aspect = source.width.toFloat() / source.height.coerceAtLeast(1) val area = maxSide * maxSide.toFloat() val width = sqrt(area * aspect).roundToInt().coerceAtLeast(1) val height = (width / aspect).roundToInt().coerceAtLeast(1) val out = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) val canvas = Canvas(out) canvas.drawColor(Color.WHITE) val paint = Paint(Paint.FILTER_BITMAP_FLAG) canvas.drawBitmap(source, null, RectF(0f, 0f, width.toFloat(), height.toFloat()), paint) val stream = ByteArrayOutputStream() out.compress(Bitmap.CompressFormat.JPEG, quality, stream) return stream.toByteArray() } /** Blocking calls. Run them off the main thread (for example `withContext(Dispatchers.IO)`). */ class FindClient( private val apiKey: String, private val baseUrl: String = "https://api.nyris.io", private val http: OkHttpClient = OkHttpClient(), ) { fun find(jpeg: ByteArray?, text: String?): String { require(apiKey.isNotBlank()) { "Find API key is missing" } require(jpeg != null || !text.isNullOrBlank()) { "Need an image or text" } val multipart = MultipartBody.Builder().setType(MultipartBody.FORM) if (jpeg != null) { multipart.addFormDataPart( "image", "query.jpg", jpeg.toRequestBody("image/jpeg".toMediaType()), ) } if (!text.isNullOrBlank()) { multipart.addFormDataPart("text", text) } val request = Request.Builder() .url("$baseUrl/find/v1.1") .header("X-Api-Key", apiKey) .header("Accept", "application/items.complete+json") .post(multipart.build()) .build() http.newCall(request).execute().use { response -> val body = response.body?.string().orEmpty() if (!response.isSuccessful) error("HTTP ${response.code}: ${body.take(300)}") return body } } fun regions(jpeg: ByteArray): String { require(apiKey.isNotBlank()) { "Find API key is missing" } val request = Request.Builder() .url("$baseUrl/find/v2/regions") .header("X-Api-Key", apiKey) .post(jpeg.toRequestBody("image/jpeg".toMediaType())) .build() http.newCall(request).execute().use { response -> val body = response.body?.string().orEmpty() if (!response.isSuccessful) error("HTTP ${response.code}: ${body.take(300)}") return body } } }