收藏
回答

救命啊,选择的图片用canvas缩小重绘后图片文件大小变大了?

步骤:1 选择图片文件得到图片的地址数组

2 获取文件的大小 [(path,width,height}]

3创建离屏水印画布,将水印图片绘制到离屏画布上,得到离屏图片对象宽475高475

以下用的画布不是离屏画布

4.1返回SelectorQuery 对象实例

4.2依据画布的id得到canvas

4.3循环==》选择的图片次数

4.3.1清除画布区域内容 大小为选择的图片的大小

4.3.2创建图片对象

4.3.3依据选择的图片的大小缩放画布:宽高大于3200时缩小为3200,小于800时放大为800(依据原图比例缩放)

4.4.4将绘制选择的图片

4.4.5绘制水印图片

4.4.6把画布生成图片

5.上传图片至云

完毕

问题:选择的图片的宽高超过3200, 经缩放画布后绘制,生成的图片大小体积反超原图片2倍以上(在云开发==>存储里面可见)

可能有的东西我没理解对,不知道哪里错了???求解

以下源码:

index.js

const app = getApp()

var _this

Page({

  data: {

    canvas: {

      width: 800,

      height: 800

    }

  },

  onLoad() {

    _this = this

  },

  //选择图片

  bindtap: function () {

    wx.chooseImage({

      success(res) {

        _this.compress(res.tempFilePaths)

        //_this.tempFilePaths = res.tempFilePaths

      },

      fail(err) {

        console.log('选择图片错误', err)

      }

    })

  },

  /**

   * 压缩图片

   * @param {*} tempFilePaths //所选图片的地址 数组

   */

  compress: async function (tempFilePaths) {

    //===========================================================================生成 水印 watermarkImage 对象 ↓↓↓↓↓↓↓↓↓↓↓

    const offCanvas = wx.createOffscreenCanvas({ //离屏画布 上面绘制的是小程序二维码

      type: '2d',

      width: 475,

      height: 475

    })

    const offContext = offCanvas.getContext('2d'//离屏绘图上下文

    const watermarkImage = offCanvas.createImage() //小程序二给码的水印图片

    await new Promise(resolve => {

      watermarkImage.onload = resolve,

        watermarkImage.src = '/image/小程序体验版.jpg' //小程序的二维码

    })

    offContext.clearRect(0, 0, 475, 475//清除画布内容

    offContext.drawImage(watermarkImage, 0, 0//将水印绘制在画布上

    //===========================================================================生成 水印 watermarkImage 对象 ↑↑↑↑↑↑↑↑↑↑↑

    let imageS = [] //最终绘制好的图片

    //===========================================================================获取图片的 宽 高 路径 ↓↓↓↓↓↓↓↓↓↓↓

    let imageArr = [] //图片数组[{路径,宽,高}]

    for (let i = 0, len = tempFilePaths.length; i < len; i++{

      imageArr[i= await GetImageInfo(tempFilePaths[i]) //获取图片属性

    }

    //===========================================================================获取图片的 宽 高 路径 ↑↑↑↑↑↑↑↑↑↑↑


    //=========================================================================== 压缩图片 过大时缩小画布 过小是放大画布↓↓↓↓↓↓↓↓↓↓↓

    const query = wx.createSelectorQuery() //返回一个 SelectorQuery 对象实例

    const canvas = await new Promise((resolve, reject) => {

      query.select('#myCanvas'//在当前页面下选择第一个匹配选择器 selector 的节点。返回一个 NodesRef 对象实例,可以用于获取节点信息 得到id为myCanvas的节点信息

        .fields({ //获取节点的相关信息

          node: true, //是否返回节点对应的 Node 实例

          size: true //是否返回节点尺寸

        })

        .exec((res) => {

          if (res[0&& res[0].node{

            resolve(res[0].node)

          } else {

            reject(res)

          }

        })

    })

    const ctx = canvas.getContext('2d')

    for (let i = 0, len = imageArr.length; i < len; i++{

      ctx.clearRect(0, 0, imageArr[i].width, imageArr[i].height//清除画布上该区域的内容

      let image = canvas.createImage() //创建一个图片对象

      await new Promise(resolve => { //等待图片加载完成

        image.onload = resolve

        image.src = imageArr[i].path // 要加载的图片 url

      })

      let {

        CW,

        CH

      } = zoomCanvas(imageArr[i].width, imageArr[i].height//返回画布的宽高

      console.log('原图宽:' + imageArr[i].width + '原图高:' + imageArr[i].height + '画布宽' + CW + '画布高' + CH)

      canvas.width = CW;

      canvas.height = CH;

      ctx.drawImage(image, 0, 0, CW, CH//绘制缩放后的图片

      ctx.drawImage(watermarkImage, 0, 0, 475, 475, CW - 475, CH - 475, 475, 475)//右下角绘制水印(二维码)

      imageS[imageS.length] = await produce(canvas, CW, CH//生成图片

      

    }

    //=========================================================================== 压缩图片 过大时缩小画布 过小是放大画布↑↑↑↑↑↑↑↑↑↑↑

    /**

     * 问题:????????????????????????????????????????????????????

     * 完成后这里上传图片文件至云(采用云开发,上传至)

     * 打开 云开发->存储->找到文件所在位置 

     * 发现图片文件大小严重超过原图的大小(在选择图片时选择的是宽高在3200以上的)

     * 但在绘制图片前,控制台输出的 原图宽高 和 画布宽高 正确按比例缩小了

     * 求解:本人老白,不太懂哪里错了?????????????????????????????

     */

    _this.setData({

      imageS: imageS

    })

  },

  /**

   * 预览图片

   */

  image_tap:function(){

    wx.previewImage({

      urls:_this.data.imageS

    })

  }

})


/**

 * 缩放画布 返回缩放的大小

 * @param {number} imageW 所选图片的宽

 * @param {number} imageH 所选图片的高

 */

function zoomCanvas(imageW, imageH) {

  let CW = imageW

  let CH = imageH

  let multiple = 1 //定义缩放的倍数

  if (CW > 3200{

    multiple = 3200 / imageW //定义缩放的倍数

  } else if (CH > 3200{

    multiple = 3200 / imageW //定义缩放的倍数

  } else if (CW < 800{

    multiple = 800 / imageW //定义缩放的倍数

  } else if (CH{

    multiple = 800 / imageW //定义缩放的倍数

  }

  CW = parseInt(imageW * multiple)

  CH = parseInt(imageH * multiple)

  _this.setData({ //刷新页面画布宽高

    canvas: {

      width: CW,

      height: CH

    }

  })

  return {

    CW,

    CH

  }

}

/**

 * 获取图片的宽高路径 返回图片路径 宽 高

 * @param {string} path 图片路径数组

 */

async function GetImageInfo(path) {

  return new Promise((resolve, reject) => wx.getImageInfo({

    src: path,

    success(res) {

      resolve({

        path: res.path,

        width: res.width,

        height: res.height

      })

    },

    fail(err) {

      reject(err)

    }

  }))

}

/**

 * 生成图片 返回生成的图片地址

 * @param {object} canvas 图片对象

 * @param {number} width 要输出的图片的宽

 * @param {number} height 要输出的图片的高

 */

function produce(canvas, width, height) {

  return new Promise((resolve, reject) => wx.canvasToTempFilePath({

    canvas: canvas,

    destWidth: width, //输出的图片的宽 

    destHeight: height, //输出的图片的高

    fileType: 'jpg', //生成的图片格式

    success(res) {

      resolve(res.tempFilePath)

    },

    fail(err) {

      reject(err)

    }

  }))

}

/**

 * 保存文件

 * @param {arr} imageS 文件地址数组

 */

function preservation(imageS) {

  let catalogue=wx.env.USER_DATA_PATH//文件系统中的用户目录路径 (本地路径)

  let C=0

  for(let i=0,len=imageS.length;i<len;i++){

    wx.saveFileToDisk({

      filePath:catalogue+'/image/水印图片/'+i+'jpg',

      success(res){

        console.log(res)

      },

      fail(err){

        console.error('保存文件失败',err)

      }

    })

  }

}


.html

<label wx:for="{{imageS}}wx:key='key'>

    <image src="{{imageS}}"bindtap='image_tap'></image>

</label>

<button bindtap="bindtap">选择图片</button>

<canvas type='2did="myCanvasstyle="width:{{canvas.width}}rpx; height:{{canvas.height}}rpx;"></canvas>


最后一次编辑于  2021-06-26
回答关注问题邀请回答
收藏

2 个回答

  • 社区技术运营专员--许涛
    社区技术运营专员--许涛
    2021-06-27

    你好,麻烦提供出现问题的具体机型、微信版本号、系统版本号,以及能复现问题的代码片段(https://developers.weixin.qq.com/miniprogram/dev/devtools/minicode.html)

    2021-06-27
    有用
    回复 1
    • 大尾巴狼
      大尾巴狼
      2021-06-28
      你这链接,给的真的是。。。
      2021-06-28
      回复
  • Li
    Li
    2022-05-12

    请问楼主问题解决了吗,我也遇到同样的问题

    2022-05-12
    有用
    回复
登录 后发表内容