通过二进制获取图片格式以及宽高

通过把文件的二进制数据转为16进制字符转再进行相应的判断获取图片格式以及宽高等

二进制转字符串

  • 通过readAsBinaryString转换blob对象为二进制字符串
  • 通过charCodeAt转换二进制字符串Unicode
  • Unicode码转换为16进制
async blobToString(blob){
      return new Promise(resolve=>{
        const reader = new FileReader()
        reader.onload = function () {
          const l= reader.result.split('')
          const m = l.map(v=>v.charCodeAt())
          const x = m.map(v=>v.toString(16).toUpperCase())
          const y = x.map(v=>v.padStart(2,'0')) //不足2位补0
          const ret = y.join(' ')
          resolve(ret)
        }
        reader.readAsBinaryString(blob)
      })
    }

获取宽高

移除空格并以16进制为基数转换为整形

async getRectByOffset(file,widthOffset,heightOffset,reverse){
      let width = await this.blobToString(file.slice(...widthOffset))
      let height = await this.blobToString(file.slice(...heightOffset))

      if(reverse){
        // 比如gif 的宽,6和7 是反着排的 大小端存储
        // 比如6位是89,7位是02, gif就是 0289 而不是8902的值 切分后翻转一下
        width = [width.slice(3,5),width.slice(0,2)].join(' ')
        height = [height.slice(3,5),height.slice(0,2)].join(' ')
      }
      const w = parseInt(width.replace(' ', ''),16)
      const h = parseInt(height.replace(' ', ''),16)
      return {w,h}
    }

判断PNG

png格式文件信息前8位保存格式信息为89 50 4E 47 0D 0A 1A 0A
宽保存在18位到20
高保存在22位到24

async isPng(file){
      const ret = await this.blobToString(file.slice(0,8))
      const ispng = ret==='89 50 4E 47 0D 0A 1A 0A'
      if(ispng){
        console.log('png宽高',w,h)
        const {w,h} = await this.getRectByOffset(file,[18,20],[22,24])
        if(w>IMG_WIDTH_LIMIT || h>IMG_HEIGHT_LIMIT){
          this.$message.error("png图片宽高不得超过!"+IMG_WIDTH_LIMIT+'和'+IMG_HEIGHT_LIMIT);
          return false
        }
      }
      return ispng
    }

判断jpg

async isJpg(file){
      // jpg开头两个是 FF D8
      // 结尾两个是 FF D9
      const len = file.size
      const start = await this.blobToString(file.slice(0,2))
      const tail = await this.blobToString(file.slice(-2,len))
      const isjpg = start==='FF D8' && tail==='FF D9'
      if(isjpg){
        const heightStart = parseInt('A3',16)
        const widthStart = parseInt('A5',16)
        const {w,h} = await this.getRectByOffset(file,[widthStart,widthStart+2],[heightStart,heightStart+2])
        console.log('jpg大小',w, h)
      }
      return isjpg

    }

判断gif

async isGif(file){
      const ret = await this.blobToString(file.slice(0,6))
      const isgif = (ret==='47 49 46 38 39 61') || (ret==='47 49 46 38 37 61')
      if(isgif){
        console.log('文件是gif')

        const {w,h} = await this.getRectByOffset(file,[6,8],[8,10],true)
        console.log('gif宽高',w,h)
        if(w>IMG_WIDTH_LIMIT || h>IMG_HEIGHT_LIMIT){
          this.$message.error("gif图片宽高不得超过!"+IMG_WIDTH_LIMIT+'和'+IMG_HEIGHT_LIMIT);
          return false
        }

      }
      return isgif
      // 文件头16进制 47 49 46 38 39 61 或者47 49 46 38 37 61
      // 分别是89年和87年的规范
      // const tmp = '47 49 46 38 39 61'.split(' ')
      //               .map(v=>parseInt(v,16))
      //               .map(v=>String.fromCharCode(v))
      // console.log('gif头信息',tmp)
      // // 或者把字符串转为16进制 两个方法用那个都行
      // const tmp1 = 'GIF89a'.split('')
      //                 .map(v=>v.charCodeAt())
      //                 .map(v=>v.toString(16))
      // console.log('gif头信息',tmp1)

      // return ret ==='GIF89a' || ret==='GIF87a'
      // 文件头标识 (6 bytes) 47 49 46 38 39(37) 61

    }
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页