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();
}
相关推荐
web147862107238 分钟前
C# .Net Web 路由相关配置
前端·c#·.net
m0_748247809 分钟前
Flutter Intl包使用指南:实现国际化和本地化
前端·javascript·flutter
飞的肖13 分钟前
前端使用 Element Plus架构vue3.0实现图片拖拉拽,后等比压缩,上传到Spring Boot后端
前端·spring boot·架构
青灯文案120 分钟前
前端 HTTP 请求由 Nginx 反向代理和 API 网关到后端服务的流程
前端·nginx·http
m0_7482548825 分钟前
DataX3.0+DataX-Web部署分布式可视化ETL系统
前端·分布式·etl
ZJ_.36 分钟前
WPSJS:让 WPS 办公与 JavaScript 完美联动
开发语言·前端·javascript·vscode·ecmascript·wps
GIS开发特训营41 分钟前
Vue零基础教程|从前端框架到GIS开发系列课程(七)响应式系统介绍
前端·vue.js·前端框架·gis开发·webgis·三维gis
Cachel wood1 小时前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
学代码的小前端1 小时前
0基础学前端-----CSS DAY9
前端·css
joan_851 小时前
layui表格templet图片渲染--模板字符串和字符串拼接
前端·javascript·layui