diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/message/SendImageUtilsAndroid.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/message/SendImageUtilsAndroid.kt new file mode 100644 index 000000000..78ec64ec5 --- /dev/null +++ b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/message/SendImageUtilsAndroid.kt @@ -0,0 +1,67 @@ +@file:Suppress("unused") + +package net.mamoe.mirai.message + +import android.graphics.Bitmap +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Dispatchers.IO +import kotlinx.coroutines.withContext +import net.mamoe.mirai.contact.Contact +import net.mamoe.mirai.network.protocol.tim.packet.action.OverFileSizeMaxException +import net.mamoe.mirai.utils.ExternalImage +import net.mamoe.mirai.utils.sendTo +import net.mamoe.mirai.utils.toExternalImage +import net.mamoe.mirai.utils.upload +import java.io.File +import java.io.IOException +import java.io.InputStream + +/* + * 发送图片的一些扩展函数. + */ +/** + * 保存为临时文件然后调用 [File.toExternalImage] + */ +@Throws(IOException::class) +fun Bitmap.toExternalImage(): ExternalImage { + val file = createTempFile().apply { deleteOnExit() } + file.outputStream().use { + this.compress(Bitmap.CompressFormat.PNG, 100, it) + } + return file.toExternalImage() +} + +/** + * 在 [IO] 中进行 [InputStream.toExternalImage] + */ +@Suppress("unused") +suspend fun InputStream.suspendToExternalImage() = withContext(IO) { toExternalImage() } + + +/** + * 在 [Dispatchers.IO] 中将图片发送到指定联系人. 会创建临时文件 + * @throws OverFileSizeMaxException + */ +@Throws(OverFileSizeMaxException::class) +suspend fun Bitmap.sendTo(contact: Contact) = withContext(IO) { toExternalImage() }.sendTo(contact) + +/** + * 在 [Dispatchers.IO] 中将图片上传后构造 [Image]. 会创建临时文件 + * @throws OverFileSizeMaxException + */ +@Throws(OverFileSizeMaxException::class) +suspend fun Bitmap.upload(contact: Contact): Image = withContext(IO) { toExternalImage() }.upload(contact) + +/** + * 在 [Dispatchers.IO] 中将图片发送到指定联系人. 会保存临时文件 + * @throws OverFileSizeMaxException + */ +@Throws(OverFileSizeMaxException::class) +suspend inline fun Contact.sendImage(bitmap: Bitmap) = bitmap.sendTo(this) + +/** + * 在 [Dispatchers.IO] 中将图片发送到指定联系人. 会保存临时文件 + * @throws OverFileSizeMaxException + */ +@Throws(OverFileSizeMaxException::class) +suspend inline fun Contact.uploadImage(bitmap: Bitmap): Image = bitmap.upload(this) \ No newline at end of file diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/event/MessagePacket.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/event/MessagePacket.kt index f85c9a4e1..ec19fda7c 100644 --- a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/event/MessagePacket.kt +++ b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/event/MessagePacket.kt @@ -1,10 +1,40 @@ package net.mamoe.mirai.network.protocol.tim.packet.event +import android.graphics.Bitmap +import kotlinx.io.core.Input import net.mamoe.mirai.contact.Contact +import net.mamoe.mirai.message.* import net.mamoe.mirai.utils.InternalAPI +import java.io.File +import java.io.InputStream +import java.net.URL /** * 平台相关扩展 */ @UseExperimental(InternalAPI::class) -actual sealed class MessagePacket : MessagePacketBase() \ No newline at end of file +actual sealed class MessagePacket : MessagePacketBase() { + suspend inline fun uploadImage(image: Bitmap): Image = subject.uploadImage(image) + suspend inline fun uploadImage(image: URL): Image = subject.uploadImage(image) + suspend inline fun uploadImage(image: Input): Image = subject.uploadImage(image) + suspend inline fun uploadImage(image: InputStream): Image = subject.uploadImage(image) + suspend inline fun uploadImage(image: File): Image = subject.uploadImage(image) + + suspend inline fun sendImage(image: Bitmap) = subject.sendImage(image) + suspend inline fun sendImage(image: URL) = subject.sendImage(image) + suspend inline fun sendImage(image: Input) = subject.sendImage(image) + suspend inline fun sendImage(image: InputStream) = subject.sendImage(image) + suspend inline fun sendImage(image: File) = subject.sendImage(image) + + suspend inline fun Bitmap.upload(): Image = upload(subject) + suspend inline fun URL.uploadAsImage(): Image = uploadAsImage(subject) + suspend inline fun Input.uploadAsImage(): Image = uploadAsImage(subject) + suspend inline fun InputStream.uploadAsImage(): Image = uploadAsImage(subject) + suspend inline fun File.uploadAsImage(): Image = uploadAsImage(subject) + + suspend inline fun Bitmap.send() = sendTo(subject) + suspend inline fun URL.sendAsImage() = sendAsImageTo(subject) + suspend inline fun Input.sendAsImage() = sendAsImageTo(subject) + suspend inline fun InputStream.sendAsImage() = sendAsImageTo(subject) + suspend inline fun File.sendAsImage() = sendAsImageTo(subject) +} \ No newline at end of file diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt index 30eee0c36..97876b73d 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt @@ -12,7 +12,6 @@ import kotlinx.io.errors.IOException import kotlinx.io.streams.asInput import java.awt.image.BufferedImage import java.io.File -import java.io.FileOutputStream import java.io.InputStream import java.io.OutputStream import java.net.URL @@ -63,7 +62,7 @@ fun File.toExternalImage(): ExternalImage { return ExternalImage( width = image.getWidth(0), height = image.getHeight(0), - md5 = this.inputStream().md5(), + md5 = this.inputStream().use { it.md5() }, imageFormat = image.formatName, input = this.inputStream().asInput(IoBuffer.Pool), inputSize = this.length() @@ -82,7 +81,11 @@ suspend fun File.suspendToExternalImage() = withContext(IO) { toExternalImage() @Throws(IOException::class) fun URL.toExternalImage(): ExternalImage { val file = createTempFile().apply { deleteOnExit() } - openStream().transferTo(FileOutputStream(file)) + file.outputStream().use { output -> + openStream().use { input -> + input.transferTo(output) + } + } return file.toExternalImage() } @@ -98,7 +101,9 @@ suspend fun URL.suspendToExternalImage() = withContext(IO) { toExternalImage() } @Throws(IOException::class) fun InputStream.toExternalImage(): ExternalImage { val file = createTempFile().apply { deleteOnExit() } - this.transferTo(FileOutputStream(file)) + file.outputStream().use { + this.transferTo(it) + } this.close() return file.toExternalImage() } @@ -115,7 +120,9 @@ suspend fun InputStream.suspendToExternalImage() = withContext(IO) { toExternalI @Throws(IOException::class) fun Input.toExternalImage(): ExternalImage { val file = createTempFile().apply { deleteOnExit() } - this.asStream().transferTo(FileOutputStream(file)) + file.outputStream().use { + this.asStream() + } return file.toExternalImage() }