konva Image 对上报不同格式客户端处理方式

vue3组件

javascript 复制代码
<v-stage
        id="konva_stage"
        :config="konvaConfig"
        ref="konvaStageRef"
        @wheel="wheelForScale($event)"
      >
        <v-layer>
          <v-group :config="group">
            <v-image
              :config="{
                image: pgmImage,
              }"
            />
          </v-group>
        </v-layer>
      </v-stage>
  1. Blob 对象(推荐)
javascript 复制代码
if (data instanceof Blob) {
      const url = URL.createObjectURL(data);
      pgmImage.value = new Image();
      pgmImage.value.src = url;
      pgmImage.value.onload = function () {
        console.log("pgmImage.width", pgmImage.value.naturalWidth);
        console.log("pgmImage.height", pgmImage.value.naturalHeight);
      };
}

2.base64(此种方式,读取图片内容转换成base64格式会比原图片大大概1/3)

javascript 复制代码
const base64Str = imgData; // imgData 从后端接口或者websocket 上报数据
pgmImage.value = new Image();
pgmImage.value.src = base64Str;
pgmImage.value.onload = ()=> {
    // 获取图片参数 参与逻辑操作
}
  1. pgm 这种非常不推荐pgm本身比其他图片格式大,且不能压缩处理,对图片较大情况下非常不友好!

解析接口传递过来的pgm 数据

javascript 复制代码
const MapImage = function (data) {
  let exp = /^(\S+)\s+(\#.*?\n)*\s*(\d+)\s+(\d+)\s+(\d+)?\s*/;
  let match = data && data.match(exp);

  if (match) {
    let width = (this.width = parseInt(match[3], 10));
    let height = (this.height = parseInt(match[4], 10));
    let maxVal = parseInt(match[5], 10);
    let bytes = maxVal < 256 ? 1 : 2;
    let imgData = data.substr(match[0].length);

    switch (match[1]) {
      case "P1":
        this._parser = new ASCIIParser(maxVal + " " + imgData, bytes);
        this._formatter = new PBMFormatter(width, height);
        break;

      case "P2":
        this._parser = new ASCIIParser(imgData, bytes);
        this._formatter = new PGMFormatter(width, height, maxVal);
        break;

      case "P3":
        this._parser = new ASCIIParser(imgData, bytes);
        this._formatter = new PPMFormatter(width, height, maxVal);
        break;

      case "P4":
        this._parser = new BinaryParser(imgData, bytes);
        this._formatter = new PBMFormatter(width, height);
        break;

      case "P5":
        this._parser = new BinaryParser(imgData, bytes);
        this._formatter = new PGMFormatter(width, height, maxVal);
        break;

      case "P6":
        this._parser = new BinaryParser(data, bytes);
        this._formatter = new PPMFormatter(width, height, maxVal);
        break;

      default:
        throw new TypeError(
          "Sorry, your file format is not supported. [" + match[1] + "]"
        );
    }
  } else {
    throw new TypeError("Sorry, file does not appear to be a Netpbm file.");
  }
};

MapImage.prototype.getInitMap = function (type = "image") {
  let canvas = this._formatter.getPainting(this._parser, type);
  return canvas;
};

const BinaryParser = function (data, bytes) {
  this._data = data;
  this._bytes = bytes;
  this._pointer = 0;
};

BinaryParser.prototype.getNextSample = function () {
  if (this._pointer >= this._data.length) return false;

  let val = 0;
  for (let i = 0; i < this._bytes; i++) {
    val = val * 255 + this._data.charCodeAt(this._pointer++);
  }

  return val;
};

const ASCIIParser = function (data, bytes) {
  this._data = data.split(/\s+/);
  this._bytes = bytes;
  this._pointer = 0;
};

ASCIIParser.prototype.getNextSample = function () {
  if (this._pointer >= this._data.length) return false;

  let val = 0;
  for (let i = 0; i < this._bytes; i++) {
    val = val * 255 + parseInt(this._data[this._pointer++], 10);
  }

  return val;
};

const PPMFormatter = function (width, height, maxVal) {
  this._width = width;
  this._height = height;
  this._maxVal = maxVal;
};

PPMFormatter.prototype.getPainting = function (parser, type) {
  let paintData = null;
  let canvas = null;
  let ctx = null;
  let img = null;
  if (type === "canvas") {
    canvas = document.createElement("canvas");
    ctx = canvas.getContext("2d");

    canvas.width = ctx.width = this._width;
    canvas.height = ctx.height = this._height;
    paintData = ctx.getImageData(0, 0, this._width, this._height);
  } else {
    paintData = new Uint8ClampedArray(this._width * this._height * 4);
  }
  let dataArr = type === "canvas" ? paintData.data : paintData;
  for (let row = 0; row < this._height; row++) {
    for (let col = 0; col < this._width; col++) {
      let factor = 255 / this._maxVal;
      let r = factor * parser.getNextSample();
      let g = factor * parser.getNextSample();
      let b = factor * parser.getNextSample();
      let pos = (row * this._width + col) * 4;

      dataArr[pos] = r;
      dataArr[pos + 1] = g;
      dataArr[pos + 2] = b;
      dataArr[pos + 3] = 255;
    }
  }
  if (type === "canvas") {
    ctx.putImageData(paintData, 0, 0);
    return canvas;
  } else {
    img = new ImageData(paintData, this._width, this._height);
    return img;
  }
};

const PGMFormatter = function (width, height, maxVal) {
  this._width = width;
  this._height = height;
  this._maxVal = maxVal;
};

PGMFormatter.prototype.getPainting = function (parser, type) {
  let paintData = null;
  let canvas = null;
  let ctx = null;
  let img = null;
  if (type === "canvas") {
    canvas = document.createElement("canvas");
    ctx = canvas.getContext("2d");

    canvas.width = ctx.width = this._width;
    canvas.height = ctx.height = this._height;
    paintData = ctx.getImageData(0, 0, this._width, this._height);
  } else {
    paintData = new Uint8ClampedArray(this._width * this._height * 4);
  }

  let dataArr = type === "canvas" ? paintData.data : paintData;
  for (let row = 0; row < this._height; row++) {
    for (let col = 0; col < this._width; col++) {
      let d = parser.getNextSample() * (255 / this._maxVal);
      let pos = (row * this._width + col) * 4;
      dataArr[pos] = d;
      dataArr[pos + 1] = d;
      dataArr[pos + 2] = d;
      dataArr[pos + 3] = 255;
    }
  }
  if (type === "canvas") {
    ctx.putImageData(paintData, 0, 0);
    return canvas;
  } else {
    img = new ImageData(paintData, this._width, this._height);
    return img;
  }
};

const PBMFormatter = function (width, height) {
  this._width = width;
  this._height = height;
};

PBMFormatter.prototype.getPainting = function (parser, type) {
  let paintData = null;
  let canvas = null;
  let ctx = null;
  let img = null;
  if (type === "canvas") {
    canvas = document.createElement("canvas");
    ctx = canvas.getContext("2d");
    canvas.width = ctx.width = this._width;
    canvas.height = ctx.height = this._height;
    paintData = ctx.getImageData(0, 0, this._width, this._height);
  }

  if (parser instanceof BinaryParser) {
    let data = "";
    let byte = null;
    let bytesPerLine = Math.ceil(this._width / 8);

    for (let i = 0; i < this._height; i++) {
      let line = parser._data.substr(i * bytesPerLine, bytesPerLine);
      let lineData = "";

      for (let j = 0; j < line.length; j++)
        lineData += ("0000000" + line.charCodeAt(j).toString(2)).substr(-8);
      data += lineData.substr(0, this._width);
    }

    while ((byte = parser.getNextSample()) !== false) {
      data += ("0000000" + byte.toString(2)).substr(-8);
    }

    parser = new ASCIIParser(data.split("").join(" "), 1);
  }
  let dataArr = type === "canvas" ? paintData.data : paintData;
  for (let row = 0; row < this._height; row++) {
    for (let col = 0; col < this._width; col++) {
      let d = (1 - parser.getNextSample()) * 255;
      let pos = (row * this._width + col) * 4;
      dataArr[pos] = d;
      dataArr[pos + 1] = d;
      dataArr[pos + 2] = d;
      dataArr[pos + 3] = 255;
    }
  }
  if (type === "canvas") {
    ctx.putImageData(paintData, 0, 0);
    return canvas;
  } else {
    img = new ImageData(paintData, this._width, this._height);
    return img;
  }
};

export { MapImage };

vue2 使用方式:

javascript 复制代码
if (pgmImageData) { //pgmImageData 接口返回
   let img = new MapImage(pgmImageData);
   let canvasImg = img.getInitMap("canvas");
   // canvasImg.width, canvasImg.height
   this.konvaConfig.pgmImage = new Image();
   this.konvaConfig.pgmImage.src = canvasImg.toDataURL();
}
相关推荐
weixin_382395237 小时前
为小工厂量身打造:本地部署的物料管理系统带缺料计算
前端·制造
__zRainy__7 小时前
解决pnpm v10+不自动构建
前端·pnpm·工程化
猫猫不是喵喵.8 小时前
Vue3 Props 属性
前端·javascript·vue.js
醉城夜风~9 小时前
CSS元素显示模式(display)
前端·css
AI大模型-小华9 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子12 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅12 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni12 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学13 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端