From a775b1e78446fb0ceef8f65af411422cc3213aa9 Mon Sep 17 00:00:00 2001
From: lefengyang <lefengyang@tencent.com>
Date: Tue, 15 Sep 2026 15:12:22 +0800
Subject: [PATCH] 图片转点阵图
---
ledApp/pages/addTemplate/addTemplate.vue | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 106 insertions(+), 0 deletions(-)
diff --git a/ledApp/pages/addTemplate/addTemplate.vue b/ledApp/pages/addTemplate/addTemplate.vue
index 086bec2..40d8b14 100644
--- a/ledApp/pages/addTemplate/addTemplate.vue
+++ b/ledApp/pages/addTemplate/addTemplate.vue
@@ -159,6 +159,7 @@
<uv-button type="primary" :plain="true" text="颜色" @click="changeColor()"></uv-button>
<uv-button type="primary" :plain="true" text="单帧移动" @click="enterMoveMode()"></uv-button>
<uv-button type="primary" :plain="true" text="多帧移动" @click="enterMultiMoveMode()"></uv-button>
+ <uv-button type="primary" :plain="true" text="图片上传" @click="chooseImage()"></uv-button>
<uv-button type="primary" :plain="true" text="文字" @click="addText()"></uv-button>
<uv-button type="primary" :plain="true" text="清除" @click="clear()"></uv-button>
<uv-button type="primary" :plain="true" text="保存" @click="clickSaveData"></uv-button>
@@ -1256,6 +1257,111 @@
});
},
+ // 选择图片(相册或拍照)
+ chooseImage() {
+ uni.chooseImage({
+ count: 1,
+ sizeType: ['compressed'],
+ sourceType: ['album', 'camera'],
+ success: (res) => {
+ console.log('chooseImage', JSON.stringify(res))
+ const tempFilePath = res.tempFilePaths[0]
+ uni.showLoading({ title: '转换中', mask: true })
+ this.imageToDotMatrix(tempFilePath).then(pixelArray => {
+ this.pixelData = pixelArray
+ uni.hideLoading()
+ }).catch(err => {
+ uni.hideLoading()
+ console.error('图片转点阵失败:', err)
+ uni.showToast({ title: '图片转点阵失败', icon: 'none' })
+ })
+ }
+ })
+ },
+ // 将图片转成点数据,参考generateDotMatrix的采样逻辑
+ imageToDotMatrix(imagePath) {
+ return new Promise((resolve, reject) => {
+ // 先获取图片信息,得到原始宽高用于按比例缩放
+ uni.getImageInfo({
+ src: imagePath,
+ success: (imgInfo) => {
+ const imgW = imgInfo.width
+ const imgH = imgInfo.height
+ if (!imgW || !imgH) {
+ reject(new Error('图片尺寸异常'))
+ return
+ }
+ // 等比缩放,使图片完整包含在画布内并居中
+ const scale = Math.min(this.canvasWidth / imgW, this.canvasHeight / imgH)
+ const drawW = imgW * scale
+ const drawH = imgH * scale
+ const drawX = (this.canvasWidth - drawW) / 2
+ const drawY = (this.canvasHeight - drawH) / 2
+
+ ctx = uni.createCanvasContext('myCanvas', this)
+ ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
+ // 将缩放后的图片绘制到画布
+ ctx.drawImage(imagePath, drawX, drawY, drawW, drawH)
+ ctx.draw(false, () => {
+ setTimeout(() => {
+ uni.canvasGetImageData({
+ canvasId: 'myCanvas',
+ x: 0,
+ y: 0,
+ width: this.canvasWidth,
+ height: this.canvasHeight,
+ success: (res) => {
+ console.log('canvasGetImageData', JSON.stringify(res))
+ const imageData = res.data
+ const colCount = this.width * (this.modeVal == 2 ? 10 : 1)
+ const pixelArray = new Array(this.height * colCount).fill('')
+ const cellWidth = this.canvasWidth / colCount
+ const cellHeight = this.canvasHeight / this.height
+ if (!imageData) {
+ reject(new Error('读取图片像素数据异常'))
+ return
+ }
+ // 按格子采样,判断每个格子是否为前景(暗)像素
+ for (let y = 0; y < this.height; y++) {
+ for (let x = 0; x < colCount; x++) {
+ let darkPixels = 0
+ let totalPixels = 0
+ for (let py = 0; py < cellHeight; py++) {
+ for (let px = 0; px < cellWidth; px++) {
+ const pixelY = Math.floor(y * cellHeight + py)
+ const pixelX = Math.floor(x * cellWidth + px)
+ const idx = (pixelY * this.canvasWidth + pixelX) * 4
+ const r = imageData[idx]
+ const g = imageData[idx + 1]
+ const b = imageData[idx + 2]
+ const a = imageData[idx + 3]
+ const brightness = 0.3 * r + 0.59 * g + 0.11 * b
+ if (brightness < 128 && a > 128) {
+ darkPixels++
+ }
+ totalPixels++
+ }
+ }
+ const isDark = darkPixels / totalPixels > 0.3
+ const arrayIndex = y * colCount + x
+ pixelArray[arrayIndex] = isDark ? this.color : ''
+ }
+ }
+ resolve(pixelArray)
+ },
+ fail: (err) => {
+ reject(err)
+ }
+ })
+ }, 1000)
+ })
+ },
+ fail: (err) => {
+ reject(err)
+ }
+ })
+ })
+ },
openPreview() {
if (this.fpsList.length === 0 || this.fpsList.every(f => f === null || f === undefined)) {
uni.showToast({
--
Gitblit v1.10.0