期中考试 | 用Kotlin实现图片处理程序
朱涛
你好,我是朱涛。不知不觉间,咱们的课程就已经进行一半了,我们已经学完很多内容:
基础篇,我们学完了所有 Kotlin 基础语法和重要特性。
加餐篇,我们学习了 Kotlin 编程的 5 大编程思维:函数式思维、表达式思维、不变性思维、空安全思维、协程思维。
协程篇,我们也已经学完了所有基础的协程概念。
所以现在,是时候来一次阶段性的验收了。这次,我们一起来做一个图片处理程序,来考察一下自己对于 Kotlin 编程知识的理解和应用掌握情况。初始化工程的代码在这里GitHub,你可以像往常那样,将其 clone 下来,然后用 IntelliJ 打开即可。
我们仍然会分为两个版本 1.0、2.0,不过,这一次要轮到你亲自动手写代码了!
1.0 版本:处理本地图片
当你将初始化工程打开以后,你会发现“src/main/resources/images/”这个目录下有一张图片:android.png,它就是我们要处理的图片对象。
一般来说,我们想要处理图片,会第一时间想到 Photoshop,但其实简单的图片处理任务,我们完全可以通过代码来实现,比如图片横向翻转、图片纵向翻转、图片裁切。
关于图片的底层定义,Java SDK 已经提供了很好的支持,我们在 Kotlin 代码当中可以直接使用相关的类。为了防止你对 JDK 不熟悉,我在初始化工程当中,已经为你做好了前期准备工作:
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
本文介绍了使用Kotlin实现图片处理程序的过程。作者首先回顾了课程学习内容,包括Kotlin基础语法、编程思维和协程概念。随后,作者提出了期中考试的任务:实现一个图片处理程序的两个版本。在1.0版本中,读者需要实现图片的横向翻转、纵向翻转和裁切功能,并编写相应的单元测试代码。在2.0版本中,读者需要实现一个挂起函数,用于以HTTP方式下载图片并保存到本地。此外,作者还展望了基于该工程的扩展可能性,包括实现更复杂的图形学算法和功能。整体而言,本文涵盖了Kotlin编程知识的应用,以及图片处理程序的实现和扩展方向。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《朱涛 · Kotlin 编程第一课》,新⼈⾸单¥59
《朱涛 · Kotlin 编程第一课》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(8)
- 最新
- 精选
- 曾帅git clone 之后,打开编译就报错,MultipleCompilationErrorsException 。把 gradle/wrapper/gradle-wrapper.properties 里面的 7.1 版本改成 7.2 之后重新编译就可以了。 有同样问题的同学可以参考一下。
作者回复: 不同版本之间确实存在类似的问题。感谢这位同学的提醒。
2022-03-014 - better// Image 添加方法,同时 去掉 pixels 的 private fun getHorArray(x: Int): Array<Color> { return pixels[x] } //// fun Image.flipHorizontal(): Image { for (i in (0 until this.height())) { this.getHorArray(i).reverse() } return this } fun Image.flipVertical(): Image { this.pixels.reverse() return this } fun Image.crop(startY: Int, startX: Int, width: Int, height: Int): Image { return Array(width - startY) { y -> Array(height - startX) { x -> Color(this.getPixel(x, y).rgb) } }.let { Image(it) } }
作者回复: reverse()用的挺好,在这个场景下很合适。
2022-02-273 - 白乾涛fun main() = runBlocking { File(BASE_PATH).mkdirs() downloadFile(URL, getPathFile("origin")) .loadImage() .also { it.flipVertical().writeToFile(getPathFile("vertical")) } .also { it.flipHorizontal().writeToFile(getPathFile("horizontal")) } .also { it.crop(0, 0, 100, 50).writeToFile(getPathFile("crop")) } delay(10L) }
作者回复: 蛮好的~
2022-03-061 - A Lonely Cat图片下载功能 private val client = OkHttpClient.Builder() .build() /** * 挂起函数,以http的方式下载图片,保存到本地 */ suspend fun downloadImage(url: String, outputFile: File): Boolean = suspendCoroutine { con -> val request = Request.Builder() .url(url) .get() .build() client.newCall(request) .enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { e.printStackTrace() con.resume(false) } override fun onResponse(call: Call, response: Response) { if (response.isSuccessful) { response.body?.bytes()?.let { outputFile.writeBytes(it) } con.resume(true) } else { con.resume(false) } } }) } fun main() = runBlocking { val url = "http://img.netbian.com/file/2020/1202/smallaaa773e8cc9729977037e80b19f955891606922519.jpg" val file = File("${BASE_PATH}wallpaper.png") val success = downloadImage(url, file) println("Download file status is success:$success") }
作者回复: 不错,代码写的很好。
2022-02-251 - Geek_Adr// 先交作业,后看参考实现 // 图片处理 单测Case 较难实现,偷懒写本地肉眼看 /** * 写到本地,方便可看效果 */ fun Image.writeJPEG(outputFile: File): Boolean = ImageIO.write(BufferedImage(width(), height(), BufferedImage.TYPE_INT_RGB).apply { repeat(height) { y -> repeat(width) { x -> setRGB(x, y, getPixel(y, x).rgb) } } }, "JPEG", outputFile) /** * 图片裁切 */ fun Image.crop(startY: Int, startX: Int, width: Int, height: Int): Image = Array(height) { y -> Array(width) { x -> getPixel(y + startY, x + startX) } }.let { Image(it) } /** * 横向翻转图片 */ fun Image.flipHorizontal(): Image = Array(height()) { y -> Array(width()) { x -> getPixel(y, width() - x - 1) } }.let { Image(it) } /** * 纵向翻转图片 */ fun Image.flipVertical(): Image = Array(height()) { y -> Array(width()) { x -> getPixel(height() - y - 1, x) } }.let { Image(it) } /** * 挂起函数,以http的方式下载图片,保存到本地 */ suspend fun downloadImage(url: String, outputFile: File): Boolean = withContext(Dispatchers.IO) { OkHttpClient.Builder().build().run { newCall(Request.Builder().apply { url(url) get() }.build()).execute().run { if (!isSuccessful) { return@run false } return@run body?.byteStream()?.source()?.let { outputFile.sink().buffer().writeAll(it) > 0 } ?: false } } }
作者回复: 代码不错,赞~
2022-03-12 - PoPlus/** * 挂起函数,以http的方式下载图片,保存到本地 */ suspend fun downloadImage(url: String, outputFile: File) = withContext(Dispatchers.IO) { val client = OkHttpClient() val request = Request.Builder() .url(url) .build() val response = client .newCall(request) .execute() var size = 0L response.body?.byteStream()?.readAllBytes()?.let { bytes -> outputFile.writeBytes(bytes) size = bytes.size.toLong() } if (size == response.headersContentLength()) { return@withContext true } return@withContext false } /** * 主函数 */ fun main() = runBlocking { val url = "https://raw.githubusercontent.com/chaxiu/ImageProcessor/main/src/main/resources/images/android.png" val path = "./download.png" val success = downloadImage(url, File(path)) println(success) val image = loadImage(File(path)) println("Width = ${image.width()};Height = ${image.height()}") } 看到有同学使用 suspendCoroutine 函数处理,不知道和我这个方法比较有什么区别 👀
作者回复: 挺好的。
2022-02-28 - 小江爱学术当然是要把第一部分和第二部分的内容结合起来啦: 首先自己创建一个获取图片的接口: @GetMapping("/{name}", produces = [MediaType.IMAGE_JPEG_VALUE]) fun picture(@PathVariable name: String): ByteArray { return pictureService.getPicture(name) } 然后用之前的KtCall发请求: @GET("/picture/mountain") fun image(): KtCall<ByteArray> suspend fun downloadImage() = runBlocking { val deferred = async { KtHttpProxy.create(ApiService::class.java) .image() .await() } println("still in progress") return@runBlocking deferred.await() }2023-01-15归属地:重庆
- Michael使用系统自带的 api 下载文件 suspend fun downloadImage(url: String, outputFile: File): Boolean = withContext(Dispatchers.IO) { kotlin.runCatching { URL(url).openStream().use { outputFile.writeBytes(it.readAllBytes()) } } }.isSuccess2022-06-29
收起评论