uniapp 使用canvas画图时,图片没有成功显示

我在使用uniapp开发时遇到了一个问题
我的开发步骤是
1:传入下面方法中一张图片,然后使用uni.getImageInfo获取图片宽高等信息,并将这张图片写入名为signCanvas的画布中
2:接着使用uni.canvasGetImageData方法读取signCanvas画布的图片像素数据,紧接着通过循环方式将符合条件的像素改变颜色,并将新的像素数据保存到grayImageData中
3:接着在使用uni.canvasPutImageData方法将新的像素数据重新写入signCanvas画布中,最后结束

但是我遇到问题了,代码跑完后,新的像素数据总是很随机,有时候显示的是原来的图片,有时候显示的又确实是新的像素图片,就很随机,也没有发现问题出在哪里。

麻烦大家帮我看看呗,怎么优化和修改

<template>
    <view>
        <image v-if="imageSrc" :src="imageSrc" :style="{width: width + 'px',height: height + 'px'}"></image>
        <view>1</view>
        <canvas canvas-id="signCanvas" :style="{width: width + 'px',height: height + 'px'}"></canvas>
    </view> 
</template>



async processImage(tempFilePath) {
              return new Promise((resolve, reject) => {
                this.imageSrc = tempFilePath;//裁剪的图片
                uni.getImageInfo({
                    src: tempFilePath,
                    success: async (imageInfo) => {
                        this.height = imageInfo.height;
                        this.width = imageInfo.width;
                        const canvas = uni.createCanvasContext('signCanvas',this);
                        canvas.clearRect(0, 0, imageInfo.width, imageInfo.height)
                        canvas.drawImage(imageInfo.path, 0, 0, imageInfo.width, imageInfo.height);
                        //canvas.draw(true);
                        //await sleep(2000);
                        console.log("112")
                        //await this.sleep(200) // 某些平台 canvas 渲染慢,需要等待
                        uni.canvasGetImageData({
                          canvasId: 'signCanvas',
                          x: 0,
                          y: 0,
                          width: imageInfo.width,
                          height: imageInfo.height,
                          success: async (res) => {
                            console.log("canvasGetImageData",res)
                            const data = res.data;
                            const grayImageData = res.data;//灰度图数据 */
                            let grayValue = 0; // 灰度值范围为0-255  
                            let greenPixels = 0;
                            for (let i = 0; i < data.length; i += 4) {
                              const red = data[i];
                              const green = data[i + 1];
                              const blue = data[i + 2];
                              let hsv = this.rgbToHsb(red,green,blue);
                                if (hsv[0] >= 0.075 && hsv[1] >= 0.15 &&
                                        hsv[2] > 0.1389 && hsv[2] <= 0.4444) {
                                    greenPixels++;
                                }else{
                                    grayValue = Math.floor(data[i] * 0.114 + data[i + 1] * 0.587 + data[i + 2] * 0.299);//根据RGB值计算灰度值
                                    grayImageData[i] = 255; // 将灰度值存储到数组中对应位置的R值
                                    grayImageData[i + 1] = 255; // 将灰度值存储到数组中对应位置的G值
                                    grayImageData[i + 2] = 255; // 将灰度值存储到数组中对应位置的B值
                                    grayImageData[i + 3] = data[i + 3]; // 保留原始图片的透明度值
                                }
                            }
                            console.log("canvasGetImageData11111",grayImageData)
                            //await this.sleep(2000) // 某些平台 canvas 渲染慢,需要等待
                            canvas.draw();
                            
                            uni.canvasPutImageData(
                            {
                                canvasId: "signCanvas",
                                x: 0,
                                y: 0,
                                width: imageInfo.width,
                                data: res.data,
                            },
                            false,
                            );
                            resolve(grayImageData);
                          },
                        })
                    },
                })
              })
            },

引用 皆我百晓生 小程序回复内容作答:
根据你提供的代码,有几个可能导致图片没有成功显示的问题:

  1. 在canvas绘制之前,未等待画布渲染完毕。在async函数中,canvas的绘制是一个异步操作,因此需要等待画布渲染完毕之后再进行下一步操作。你可以尝试在canvas.draw()之后使用await关键字等待画布渲染完毕,然后再执行后续操作。

  2. uni.canvasPutImageData方法中,你传递了res.data作为参数,而正确的应该是grayImageData,因为你修改了像素数据保存到了grayImageData中。

  3. 你在uni.canvasPutImageData方法中的第二个参数设置为了false,这表示将使用原始像素覆盖画布。如果你想要完全替换画布中的像素数据,可以将第二个参数设置为true

我稍作修改的代码如下:

async processImage(tempFilePath) {
  return new Promise((resolve, reject) => {
    this.imageSrc = tempFilePath; //裁剪的图片
    uni.getImageInfo({
      src: tempFilePath,
      success: async (imageInfo) => {
        this.height = imageInfo.height;
        this.width = imageInfo.width;
        const canvas = uni.createCanvasContext('signCanvas', this);
        canvas.clearRect(0, 0, imageInfo.width, imageInfo.height)
        canvas.drawImage(imageInfo.path, 0, 0, imageInfo.width, imageInfo.height);
        //canvas.draw(true);
        //await sleep(2000);
        console.log("112")
        //await this.sleep(200) // 某些平台 canvas 渲染慢,需要等待
        uni.canvasGetImageData({
          canvasId: 'signCanvas',
          x: 0,
          y: 0,
          width: imageInfo.width,
          height: imageInfo.height,
          success: async (res) => {
            console.log("canvasGetImageData", res)
            const data = res.data;
            const grayImageData = new Uint8ClampedArray(data.length); // 创建一个与原始像素数据相同大小的数组
            let grayValue = 0; // 灰度值范围为0-255  
            let greenPixels = 0;
            for (let i = 0; i < data.length; i += 4) {
              const red = data[i];
              const green = data[i + 1];
              const blue = data[i + 2];
              let hsv = this.rgbToHsb(red, green, blue);
              if (hsv[0] >= 0.075 && hsv[1] >= 0.15 &&
                hsv[2] > 0.1389 && hsv[2] <= 0.4444) {
                greenPixels++;
              } else {
                grayValue = Math.floor(data[i] * 0.114 + data[i + 1] * 0.587 + data[i + 2] * 0.299); //根据RGB值计算灰度值
                grayImageData[i] = 255; // 将灰度值存储到数组中对应位置的R值
                grayImageData[i + 1] = 255; // 将灰度值存储到数组中对应位置的G值
                grayImageData[i + 2] = 255; // 将灰度值存储到数组中对应位置的B值
                grayImageData[i + 3] = data[i + 3]; // 保留原始图片的透明度值
              }
            }
            console.log("canvasGetImageData11111", grayImageData)
            //await this.sleep(2000) // 某些平台 canvas 渲染慢,需要等待
            canvas.draw(false, async () => {
              uni.canvasPutImageData(
                {
                  canvasId: "signCanvas",
                  x: 0,
                  y: 0,
                  width: imageInfo.width,
                  data: grayImageData, // 传入修改后的像素数据
                },
                true,  // 替换整个画布像素数据
                () => {
                  resolve(grayImageData);
                }
              );
            });
          },
        })
      },
    })
  })
}

请尝试根据这个修改后的代码运行,看看问题是否得到解决。如果还有问题,请提供更多信息。