feat(kotlin): add ergonomic API with SlimgImage fluent chaining#7
feat(kotlin): add ergonomic API with SlimgImage fluent chaining#7
Conversation
decode, optimize, formatFromMagicBytes 함수에 InputStream 및 ByteBuffer 오버로드를 추가하여 WebFlux DataBuffer 등과의 통합을 용이하게 함
UByte/UInt 변환 없이 Int로 quality를 전달하고, PipelineOptions 대신 개별 파라미터로 convert를 호출할 수 있는 래퍼 object 추가. solidColor 헬퍼 포함.
decode → resize/crop/extend → encode 흐름을 체이닝으로 연결하는 SlimgImage 래퍼 클래스 추가. Int 파라미터로 UInt/UByte 변환 불필요.
Quick Start, 3단계 API 레이어 설명, InputStream/ByteBuffer 예시, SlimgImage 체이닝 패턴 등 새 API 기준으로 전면 재작성
…al badge 릴리스마다 문서 버전 수정 누락 방지
Kotlin ergonomic API (SlimgImage fluent API, Slimg wrapper object, InputStream/ByteBuffer overloads) 추가에 따른 minor version bump
LICENSE 파일 생성 및 모든 매니페스트/문서에서 라이센스 참조 변경
Summary of ChangesHello @clroot, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the Kotlin bindings for the Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
| fun resize(width: Int? = null, height: Int? = null): SlimgImage { | ||
| val mode = when { | ||
| width != null && height != null -> ResizeMode.Exact(width.toUInt(), height.toUInt()) | ||
| width != null -> ResizeMode.Width(width.toUInt()) | ||
| height != null -> ResizeMode.Height(height.toUInt()) | ||
| else -> throw IllegalArgumentException("At least one of width or height must be specified") | ||
| } | ||
| return transformed(io.clroot.slimg.resize(imageData, mode)) | ||
| } |
There was a problem hiding this comment.
음수 width 또는 height 값이 toUInt()를 통해 예기치 않은 큰 양수로 변환될 수 있습니다. 이는 의도치 않은 리사이즈 동작이나 오류를 발생시킬 수 있습니다. require를 사용하여 width와 height가 양수인지 확인하는 로직을 추가하는 것이 좋습니다.
fun resize(width: Int? = null, height: Int? = null): SlimgImage {
require(width == null || width > 0) { "Width must be positive." }
require(height == null || height > 0) { "Height must be positive." }
val mode = when {
width != null && height != null -> ResizeMode.Exact(width.toUInt(), height.toUInt())
width != null -> ResizeMode.Width(width.toUInt())
height != null -> ResizeMode.Height(height.toUInt())
else -> throw IllegalArgumentException("At least one of width or height must be specified")
}
return transformed(io.clroot.slimg.resize(imageData, mode))
}| fun resize(fit: Pair<Int, Int>): SlimgImage { | ||
| val mode = ResizeMode.Fit(fit.first.toUInt(), fit.second.toUInt()) | ||
| return transformed(io.clroot.slimg.resize(imageData, mode)) | ||
| } |
There was a problem hiding this comment.
fit의 Pair에 음수 값이 전달될 경우, toUInt()에 의해 의도치 않은 큰 값으로 변환될 수 있습니다. require를 사용하여 fit의 두 값이 모두 양수인지 검증하는 것이 안전합니다.
fun resize(fit: Pair<Int, Int>): SlimgImage {
require(fit.first > 0 && fit.second > 0) { "Fit dimensions must be positive." }
val mode = ResizeMode.Fit(fit.first.toUInt(), fit.second.toUInt())
return transformed(io.clroot.slimg.resize(imageData, mode))
}| @Throws(SlimgException::class) | ||
| fun resize(scale: Double): SlimgImage = | ||
| transformed(io.clroot.slimg.resize(imageData, ResizeMode.Scale(scale))) |
There was a problem hiding this comment.
| fun crop(x: Int, y: Int, width: Int, height: Int): SlimgImage { | ||
| val mode = CropMode.Region(x.toUInt(), y.toUInt(), width.toUInt(), height.toUInt()) | ||
| return transformed(io.clroot.slimg.crop(imageData, mode)) | ||
| } |
There was a problem hiding this comment.
crop 파라미터에 음수 값이 전달될 경우 toUInt() 변환 시 예기치 않은 동작을 유발할 수 있습니다. x, y는 0 이상, width, height는 0보다 큰 값이어야 합니다. require를 사용하여 입력값을 검증하는 것이 좋습니다.
fun crop(x: Int, y: Int, width: Int, height: Int): SlimgImage {
require(x >= 0 && y >= 0) { "Crop coordinates (x, y) must be non-negative." }
require(width > 0 && height > 0) { "Crop dimensions (width, height) must be positive." }
val mode = CropMode.Region(x.toUInt(), y.toUInt(), width.toUInt(), height.toUInt())
return transformed(io.clroot.slimg.crop(imageData, mode))
}| fun crop(aspectRatio: Pair<Int, Int>): SlimgImage { | ||
| val mode = CropMode.AspectRatio(aspectRatio.first.toUInt(), aspectRatio.second.toUInt()) | ||
| return transformed(io.clroot.slimg.crop(imageData, mode)) | ||
| } |
There was a problem hiding this comment.
aspectRatio에 음수 값이 전달되면 toUInt() 변환 시 의도치 않은 동작을 할 수 있습니다. require를 사용하여 aspectRatio의 두 값이 모두 양수인지 검증하는 것이 좋습니다.
fun crop(aspectRatio: Pair<Int, Int>): SlimgImage {
require(aspectRatio.first > 0 && aspectRatio.second > 0) { "Aspect ratio components must be positive." }
val mode = CropMode.AspectRatio(aspectRatio.first.toUInt(), aspectRatio.second.toUInt())
return transformed(io.clroot.slimg.crop(imageData, mode))
}| fun extend( | ||
| width: Int, | ||
| height: Int, | ||
| fill: FillColor = FillColor.Transparent, | ||
| ): SlimgImage { | ||
| val mode = ExtendMode.Size(width.toUInt(), height.toUInt()) | ||
| return transformed(io.clroot.slimg.extend(imageData, mode, fill)) | ||
| } |
There was a problem hiding this comment.
extend의 width, height에 음수 값이 전달되면 toUInt() 변환 시 예기치 않은 동작을 할 수 있습니다. require를 사용하여 두 값이 모두 양수인지 검증하는 것이 좋습니다.
fun extend(
width: Int,
height: Int,
fill: FillColor = FillColor.Transparent,
): SlimgImage {
require(width > 0 && height > 0) { "Extend dimensions (width, height) must be positive." }
val mode = ExtendMode.Size(width.toUInt(), height.toUInt())
return transformed(io.clroot.slimg.extend(imageData, mode, fill))
}| fun extend( | ||
| aspectRatio: Pair<Int, Int>, | ||
| fill: FillColor = FillColor.Transparent, | ||
| ): SlimgImage { | ||
| val mode = ExtendMode.AspectRatio(aspectRatio.first.toUInt(), aspectRatio.second.toUInt()) | ||
| return transformed(io.clroot.slimg.extend(imageData, mode, fill)) | ||
| } |
There was a problem hiding this comment.
extend의 aspectRatio에 음수 값이 전달되면 toUInt() 변환 시 예기치 않은 동작을 할 수 있습니다. require를 사용하여 aspectRatio의 두 값이 모두 양수인지 검증하는 것이 좋습니다.
fun extend(
aspectRatio: Pair<Int, Int>,
fill: FillColor = FillColor.Transparent,
): SlimgImage {
require(aspectRatio.first > 0 && aspectRatio.second > 0) { "Aspect ratio components must be positive." }
val mode = ExtendMode.AspectRatio(aspectRatio.first.toUInt(), aspectRatio.second.toUInt())
return transformed(io.clroot.slimg.extend(imageData, mode, fill))
}| fun solidColor(r: Int, g: Int, b: Int, a: Int = 255): FillColor = | ||
| FillColor.Solid(r.toUByte(), g.toUByte(), b.toUByte(), a.toUByte()) |
There was a problem hiding this comment.
RGBA 색상 컴포넌트가 0..255 범위를 벗어나는 경우 toUByte()에 의해 예기치 않은 값으로 변환될 수 있습니다. (예: 256.toUByte()는 0u, (-1).toUByte()는 255u). require를 사용하여 각 컴포넌트가 0..255 범위 내에 있는지 검증하면 API를 더 안전하게 만들 수 있습니다.
fun solidColor(r: Int, g: Int, b: Int, a: Int = 255): FillColor {
require(r in 0..255) { "Red component must be in range 0-255." }
require(g in 0..255) { "Green component must be in range 0-255." }
require(b in 0..255) { "Blue component must be in range 0-255." }
require(a in 0..255) { "Alpha component must be in range 0-255." }
return FillColor.Solid(r.toUByte(), g.toUByte(), b.toUByte(), a.toUByte())
}
Summary
SlimgImagefluent API 추가 — decode → resize/crop/extend → encode 체이닝 지원Slimgwrapper object 추가 —Int파라미터로UByte/UInt변환 불필요InputStream/ByteBuffer오버로드 추가 — WebFluxDataBuffer등과 통합 용이MIT OR Apache-2.0→MIT변경 +LICENSE파일 생성0.3.1→0.4.0bumpTest plan
SlimgStreamsTest— InputStream/ByteBuffer 오버로드 테스트SlimgObjectTest— Slimg wrapper object 테스트SlimgImageTest— fluent API 체이닝 테스트SlimgTest전체 통과 확인cargo check빌드 확인🤖 Generated with Claude Code