知识图库
Java知识库
JDK线程池实现原理
Java中的强、软、弱、虚引用
深入拆解Java虚拟机
01 开篇词 | 为什么我们要学习Java虚拟机?
02 Java代码是怎么运行的?
03 Java的基本类型
04 Java虚拟机是如何加载Java类的?
05 JVM是如何执行方法调用的?(上)
06 JVM是如何执行方法调用的?(下)
7 JVM是如何处理异常的?
Java面试常见问题整理
Java面试常见问题-Java 基础篇
Java面试常见问题-Jvm篇
Java面试常见问题-并发篇
Android知识库
Kotlin编程第一课
1 开篇词 | 入门Kotlin有多容易,精通Kotlin就有多难
2 Kotlin基础语法:正式开启学习之旅
3 面向对象:理解Kotlin设计者的良苦用心
4 Kotlin原理:编译器在幕后干了哪些“好事”?
5 实战:构建一个Kotlin版本的四则运算计算器
6 object关键字:你到底有多少种用法?
7 扩展:你的能力边界到底在哪里?
8 高阶函数:为什么说函数是Kotlin的“一等公民”?
9 实战:用Kotlin写一个英语词频统计程序
10 加餐一 | 初识Kotlin函数式编程
11 委托:你为何总是被低估?
12 泛型:逆变or协变,傻傻分不清?
13 注解与反射:进阶必备技能
14 实战:用Kotlin实现一个网络请求框架KtHttp
15 加餐二 | 什么是“表达式思维”?
16 加餐三 | 什么是“不变性思维”?
17 加餐四 | 什么是“空安全思维”?
18 春节刷题计划(一)| 当Kotlin遇上LeetCode
19 春节刷题计划(二)| 一题三解,搞定版本号判断
20 春节刷题计划(三)| 一题双解,搞定求解方程
21 春节刷题计划(四)| 一题三解,搞定分式加减法
22 什么是“协程思维模型”?
23 如何启动协程?
24 挂起函数:Kotlin协程的核心
25 Job:协程也有生命周期吗?
26 Context:万物皆为Context?
27 实战:让KtHttp支持挂起函数
28 期中考试 | 用Kotlin实现图片处理程序
29 题目解答 | 期中考试版本参考实现
30 Channel:为什么说Channel是“热”的?
31 Flow:为什么说Flow是“冷”的?
32 select:到底是在选择什么?
33 并发:协程不需要处理同步吗?
34 异常:try-catch居然会不起作用?坑!
35 实战:让KtHttp支持Flow
36 答疑(一)| Java和Kotlin到底谁好谁坏?
37 集合操作符:你也会“看完就忘”吗?
38 协程源码的地图:如何读源码才不会迷失?
39 图解挂起函数:原来你就是个状态机?
40 加餐五 | 深入理解协程基础元素
41 launch的背后到底发生了什么?
42 Dispatchers是如何工作的?
43 CoroutineScope是如何管理协程的?
44 图解Channel:如何理解它的CSP通信模型?
45 图解Flow:原来你是只纸老虎?
46 Java Android开发者还会有未来吗?
47 Kotlin与Jetpack简直是天生一对!
48 用Kotlin写一个GitHub Trending App
49 结课测试 | “Kotlin编程第一课”100分试卷等你来挑战!
50 结束语 | 不忘初心
Android Framework 教程—基础篇
01 Ubuntu 使用快速入门
02 Make 构建工具入门
03 理解 Unicode UTF-8 UTF-16 UTF-32
04 Linux Shell 脚本编程入门1——核心基础语法
05 SeAndroid 使用极速上手
06 理解 C++ 的 Memory Order
07 AOSP 极速上手
08 系统开发工具推荐
09 添加 Product
运动相关知识
爱上跑步
01 开篇词 | 跑步,不那么简单的事儿
02 跑两步就喘了,是不是我不适合跑步?
03 正确的跑步姿势是什么样的?
04 为什么跑步要先热身?
05 怎样制定你的第一个10公里跑步计划?
06 快跑和慢跑,哪个更燃脂?
07 普通跑步者应该如何选择跑鞋?
08 买跑步装备,不要踩这些坑儿
09 跑步前到底应不应该吃东西?
10 跑步到底伤不伤膝盖?
11 参加了20场马拉松,我是如何准备的?
12 除了马拉松,还能参加哪些跑步赛事?
13 热点问题答疑 :跑完第二天浑身疼,还要不要继续跑?
健身房计划
[DeepSeek]减脂塑形计划
【DeepSeek】训练周期安排
每日餐饮热量控制
减脂期间食物推荐避坑指南
HarmonyOS知识库
其他知识类目
心理学相关
如何学点心理学——关于非专业人士学心理学的一点建议
投射性认同
-
+
首页
28 期中考试 | 用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不熟悉,我在初始化工程当中,已经为你做好了前期准备工作: ```kotlin class Image(private val pixels: Array>) { fun height(): Int { return pixels.size } fun width(): Int { return pixels[0].size } /** * 底层不处理越界 */ fun getPixel(y: Int, x: Int): Color { return pixels[y][x] } } ``` 这是我定义的一个Image类,它的作用就是封装图片的内存对象。我们都知道,图片的本质是一堆像素点(Pixel),而每个像素点,都可以用RGB来表示,这里我们用Java SDK当中的Color来表示。 当我们把图片放大到足够倍数的时候,我们就可以看到其中的正方形像素点了。  所以,最终我们就可以用“Array>”这样一个二维数组来表示一张图片。 另外,从本地加载图片到内存的代码,我也帮你写好了: ```kotlin const val BASE_PATH = "./src/main/resources/images/" fun main() { val image = loadImage(File("${BASE_PATH}android.png")) println("Width = ${image.width()};Height = ${image.height()}") } /** * 加载本地图片到内存中 */ fun loadImage(imageFile: File) = ImageIO.read(imageFile) .let { Array(it.height) { y -> Array(it.width) { x -> Color(it.getRGB(x, y)) } } }.let { Image(it) } ``` 那么,唯一需要你做的,就是实现这几个函数的功能:图片横向翻转、图片纵向翻转、图片裁切。 ```kotlin /** * 横向翻转图片 * 待实现 */ fun Image.flipHorizontal(): Image = TODO() /** * 纵向翻转图片 * 待实现 */ fun Image.flipVertical(): Image = TODO() /** * 图片裁切 * 待实现 */ fun Image.crop(startY: Int, startX: Int, width: Int, height: Int): Image = TODO() ``` 另外,如果你有兴趣的话,还可以去实现对应的单元测试代码: ```kotlin class TestImageProcessor { /** * 待实现的单元测试 */ @Test fun testFlipHorizontal() { } /** * 待实现的单元测试 */ @Test fun testFlipVertical() { } /** * 待实现的单元测试 */ @Test fun testCrop() { } } ``` 这样一来,我们1.0版本的代码就算完成了。不过,我们还没用上协程的知识啊! 请看2.0版本。 ### 2.0版本:增加图片下载功能 在上个版本中,我们的代码仅支持本地图片的处理,但有的时候,我们想要处理网络上的图片该怎么办呢?所以这时候,我们可以增加一个下载网络图片的功能。 这个版本,你只需要实现一个函数: ```kotlin /** * 挂起函数,以http的方式下载图片,保存到本地 * 待实现 */ suspend fun downloadImage(url: String, outputFile: File): Boolean = TODO() ``` 需要注意的是,由于下载网络图片比较耗时,我们需要将其定义成一个挂起函数,这样一来,我们后续在使用它的时候就可以更得心应手了。 ```kotlin fun main() = runBlocking { // 不一定非要下载我提供的链接 val url = "https://raw.githubusercontent.com/chaxiu/ImageProcessor/main/src/main/resources/images/android.png" val path = "${BASE_PATH}downloaded.png" // 调用挂起函数 downloadImage(url, File(path)) val image = loadImage(File(path)) println("Width = ${image.width()};Height = ${image.height()}") } ``` 在上面的代码中,我是以“https://raw.githubusercontent.com/chaxiu/ImageProcessor/main/src/main/resources/images/android.png” 这个链接为例,这是一个HTTPS的链接,你在实际开发的时候,也可以随便去找一个普通的HTTP图片链接,这样就不必处理SSL的问题了。 程序实际运行效果会是这样的:  在下节课里,我会给出我的代码参考,不过在看我的代码之前,记得先要自己动手啊。 其实,以我们这个工程为基础,再加上一些图形学算法,我们完全可以做出Photoshop当中的一些高级功能,比如图片缩放、图片参数调节、图片滤镜、抠像,甚至图片识别,等等。如果你本身就有图形学方面的知识储备,也欢迎你在此基础上实现更复杂的功能! 好了,我们下节课再见!
嘿手大叔
2024年10月29日 11:48
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码