@midscene/shared 0.5.2-beta-20241010035503.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/es/img.js CHANGED
@@ -36,6 +36,9 @@ function base64Encoded(image, withHeader = true) {
36
36
  }
37
37
  throw new Error("unsupported image type");
38
38
  }
39
+ function base64ToPngFormat(base64) {
40
+ return `data:image/png;base64,${base64}`;
41
+ }
39
42
 
40
43
  // src/img/transform.ts
41
44
  import { Buffer as Buffer2 } from "buffer";
@@ -115,21 +118,34 @@ var createSvgOverlay = (elements, imageWidth, imageHeight) => {
115
118
  const createPngOverlay = async (elements2, imageWidth2, imageHeight2) => {
116
119
  const image = new Jimp3(imageWidth2, imageHeight2, 0);
117
120
  const colors = [
118
- { rect: 65535, text: 4294967295 },
119
- // blue, white
120
- { rect: 2336560127, text: 4294967295 }
121
- // brown, white
121
+ { rect: 4278190335, text: 4294967295 }
122
+ // red, white
123
+ // { rect: 0x0000ffff, text: 0xffffffff }, // blue, white
124
+ // { rect: 0x8b4513ff, text: 0xffffffff }, // brown, white
122
125
  ];
126
+ const boxPadding = 5;
123
127
  for (let index = 0; index < elements2.length; index++) {
124
128
  const element = elements2[index];
125
129
  const color = colors[index % colors.length];
130
+ const paddedRect = {
131
+ left: Math.max(0, element.rect.left - boxPadding),
132
+ top: Math.max(0, element.rect.top - boxPadding),
133
+ width: Math.min(
134
+ imageWidth2 - element.rect.left,
135
+ element.rect.width + boxPadding * 2
136
+ ),
137
+ height: Math.min(
138
+ imageHeight2 - element.rect.top,
139
+ element.rect.height + boxPadding * 2
140
+ )
141
+ };
126
142
  image.scan(
127
- element.x,
128
- element.y,
129
- element.width,
130
- element.height,
143
+ paddedRect.left,
144
+ paddedRect.top,
145
+ paddedRect.width,
146
+ paddedRect.height,
131
147
  function(x, y, idx) {
132
- if (x === element.x || x === element.x + element.width - 1 || y === element.y || y === element.y + element.height - 1) {
148
+ if (x === paddedRect.left || x === paddedRect.left + paddedRect.width - 1 || y === paddedRect.top || y === paddedRect.top + paddedRect.height - 1) {
133
149
  this.bitmap.data[idx + 0] = color.rect >> 24 & 255;
134
150
  this.bitmap.data[idx + 1] = color.rect >> 16 & 255;
135
151
  this.bitmap.data[idx + 2] = color.rect >> 8 & 255;
@@ -137,15 +153,15 @@ var createSvgOverlay = (elements, imageWidth, imageHeight) => {
137
153
  }
138
154
  }
139
155
  );
140
- const textWidth = element.label.length * 8;
156
+ const textWidth = element.indexId.toString().length * 8;
141
157
  const textHeight = 12;
142
158
  const rectWidth = textWidth + 5;
143
159
  const rectHeight = textHeight + 4;
144
- let rectX = element.x - rectWidth;
145
- let rectY = element.y + element.height / 2 - textHeight / 2 - 2;
160
+ let rectX = paddedRect.left - rectWidth;
161
+ let rectY = paddedRect.top + paddedRect.height / 2 - textHeight / 2 - 2;
146
162
  if (rectX < 0) {
147
- rectX = element.x;
148
- rectY = element.y - rectHeight;
163
+ rectX = paddedRect.left;
164
+ rectY = paddedRect.top - rectHeight;
149
165
  }
150
166
  image.scan(rectX, rectY, rectWidth, rectHeight, function(x, y, idx) {
151
167
  this.bitmap.data[idx + 0] = color.rect >> 24 & 255;
@@ -159,7 +175,7 @@ var createSvgOverlay = (elements, imageWidth, imageHeight) => {
159
175
  rectX,
160
176
  rectY,
161
177
  {
162
- text: element.label,
178
+ text: element.indexId.toString(),
163
179
  alignmentX: Jimp3.HORIZONTAL_ALIGN_CENTER,
164
180
  alignmentY: Jimp3.VERTICAL_ALIGN_MIDDLE
165
181
  },
@@ -171,63 +187,60 @@ var createSvgOverlay = (elements, imageWidth, imageHeight) => {
171
187
  };
172
188
  return createPngOverlay(elements, imageWidth, imageHeight);
173
189
  };
174
- var processImageElementInfo = async (options) => {
175
- const base64Image = options.inputImgBase64.split(";base64,").pop();
176
- assert2(base64Image, "base64Image is undefined");
177
- const imageBuffer = Buffer3.from(base64Image, "base64");
190
+ var compositeElementInfoImg = async (options) => {
191
+ const { inputImgBase64, elementsPositionInfo } = options;
192
+ const imageBuffer = Buffer3.from(inputImgBase64, "base64");
178
193
  const image = await Jimp3.read(imageBuffer);
179
194
  const { width, height } = image.bitmap;
180
- if (width && height) {
181
- const svgOverlay = await createSvgOverlay(
182
- options.elementsPositionInfo,
183
- width,
184
- height
185
- );
186
- const svgOverlayWithoutText = await createSvgOverlay(
187
- options.elementsPositionInfoWithoutText,
188
- width,
189
- height
190
- );
191
- const compositeElementInfoImgBase64 = await Jimp3.read(imageBuffer).then(async (image2) => {
192
- const svgImage = await Jimp3.read(svgOverlay);
193
- return image2.composite(svgImage, 0, 0, {
194
- mode: Jimp3.BLEND_SOURCE_OVER,
195
- opacitySource: 1,
196
- opacityDest: 1
197
- });
198
- }).then((compositeImage) => {
199
- return compositeImage.getBufferAsync(Jimp3.MIME_PNG);
200
- }).then((buffer) => {
201
- return buffer.toString("base64");
202
- }).catch((error) => {
203
- throw error;
204
- });
205
- const compositeElementInfoImgWithoutTextBase64 = await Jimp3.read(
206
- imageBuffer
207
- ).then(async (image2) => {
208
- const svgImage = await Jimp3.read(svgOverlayWithoutText);
209
- return image2.composite(svgImage, 0, 0, {
210
- mode: Jimp3.BLEND_SOURCE_OVER,
211
- opacitySource: 1,
212
- opacityDest: 1
213
- });
214
- }).then((compositeImage) => {
215
- return compositeImage.getBufferAsync(Jimp3.MIME_PNG);
216
- }).then((buffer) => {
217
- return buffer.toString("base64");
218
- }).catch((error) => {
219
- throw error;
220
- });
221
- return {
222
- compositeElementInfoImgBase64,
223
- compositeElementInfoImgWithoutTextBase64
224
- };
195
+ if (!width || !height) {
196
+ throw Error("Image processing failed because width or height is undefined");
225
197
  }
226
- throw Error("Image processing failed because width or height is undefined");
198
+ const svgOverlay = await createSvgOverlay(
199
+ elementsPositionInfo,
200
+ width,
201
+ height
202
+ );
203
+ return await Jimp3.read(imageBuffer).then(async (image2) => {
204
+ const svgImage = await Jimp3.read(svgOverlay);
205
+ return image2.composite(svgImage, 0, 0, {
206
+ mode: Jimp3.BLEND_SOURCE_OVER,
207
+ opacitySource: 1,
208
+ opacityDest: 1
209
+ });
210
+ }).then((compositeImage) => {
211
+ return compositeImage.getBufferAsync(Jimp3.MIME_PNG);
212
+ }).then((buffer) => {
213
+ return buffer.toString("base64");
214
+ }).catch((error) => {
215
+ throw error;
216
+ });
217
+ };
218
+ var processImageElementInfo = async (options) => {
219
+ const base64Image = options.inputImgBase64.split(";base64,").pop();
220
+ assert2(base64Image, "base64Image is undefined");
221
+ const [
222
+ compositeElementInfoImgBase64,
223
+ compositeElementInfoImgWithoutTextBase64
224
+ ] = await Promise.all([
225
+ compositeElementInfoImg({
226
+ inputImgBase64: options.inputImgBase64,
227
+ elementsPositionInfo: options.elementsPositionInfo
228
+ }),
229
+ compositeElementInfoImg({
230
+ inputImgBase64: options.inputImgBase64,
231
+ elementsPositionInfo: options.elementsPositionInfoWithoutText
232
+ })
233
+ ]);
234
+ return {
235
+ compositeElementInfoImgBase64,
236
+ compositeElementInfoImgWithoutTextBase64
237
+ };
227
238
  };
228
239
  export {
229
240
  base64Encoded,
241
+ base64ToPngFormat,
230
242
  calculateNewDimensions,
243
+ compositeElementInfoImg,
231
244
  imageInfo,
232
245
  imageInfoOfBase64,
233
246
  processImageElementInfo,
package/dist/lib/img.js CHANGED
@@ -31,7 +31,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var img_exports = {};
32
32
  __export(img_exports, {
33
33
  base64Encoded: () => base64Encoded,
34
+ base64ToPngFormat: () => base64ToPngFormat,
34
35
  calculateNewDimensions: () => calculateNewDimensions,
36
+ compositeElementInfoImg: () => compositeElementInfoImg,
35
37
  imageInfo: () => imageInfo,
36
38
  imageInfoOfBase64: () => imageInfoOfBase64,
37
39
  processImageElementInfo: () => processImageElementInfo,
@@ -80,6 +82,9 @@ function base64Encoded(image, withHeader = true) {
80
82
  }
81
83
  throw new Error("unsupported image type");
82
84
  }
85
+ function base64ToPngFormat(base64) {
86
+ return `data:image/png;base64,${base64}`;
87
+ }
83
88
 
84
89
  // src/img/transform.ts
85
90
  var import_node_buffer2 = require("buffer");
@@ -159,21 +164,34 @@ var createSvgOverlay = (elements, imageWidth, imageHeight) => {
159
164
  const createPngOverlay = async (elements2, imageWidth2, imageHeight2) => {
160
165
  const image = new import_jimp3.default(imageWidth2, imageHeight2, 0);
161
166
  const colors = [
162
- { rect: 65535, text: 4294967295 },
163
- // blue, white
164
- { rect: 2336560127, text: 4294967295 }
165
- // brown, white
167
+ { rect: 4278190335, text: 4294967295 }
168
+ // red, white
169
+ // { rect: 0x0000ffff, text: 0xffffffff }, // blue, white
170
+ // { rect: 0x8b4513ff, text: 0xffffffff }, // brown, white
166
171
  ];
172
+ const boxPadding = 5;
167
173
  for (let index = 0; index < elements2.length; index++) {
168
174
  const element = elements2[index];
169
175
  const color = colors[index % colors.length];
176
+ const paddedRect = {
177
+ left: Math.max(0, element.rect.left - boxPadding),
178
+ top: Math.max(0, element.rect.top - boxPadding),
179
+ width: Math.min(
180
+ imageWidth2 - element.rect.left,
181
+ element.rect.width + boxPadding * 2
182
+ ),
183
+ height: Math.min(
184
+ imageHeight2 - element.rect.top,
185
+ element.rect.height + boxPadding * 2
186
+ )
187
+ };
170
188
  image.scan(
171
- element.x,
172
- element.y,
173
- element.width,
174
- element.height,
189
+ paddedRect.left,
190
+ paddedRect.top,
191
+ paddedRect.width,
192
+ paddedRect.height,
175
193
  function(x, y, idx) {
176
- if (x === element.x || x === element.x + element.width - 1 || y === element.y || y === element.y + element.height - 1) {
194
+ if (x === paddedRect.left || x === paddedRect.left + paddedRect.width - 1 || y === paddedRect.top || y === paddedRect.top + paddedRect.height - 1) {
177
195
  this.bitmap.data[idx + 0] = color.rect >> 24 & 255;
178
196
  this.bitmap.data[idx + 1] = color.rect >> 16 & 255;
179
197
  this.bitmap.data[idx + 2] = color.rect >> 8 & 255;
@@ -181,15 +199,15 @@ var createSvgOverlay = (elements, imageWidth, imageHeight) => {
181
199
  }
182
200
  }
183
201
  );
184
- const textWidth = element.label.length * 8;
202
+ const textWidth = element.indexId.toString().length * 8;
185
203
  const textHeight = 12;
186
204
  const rectWidth = textWidth + 5;
187
205
  const rectHeight = textHeight + 4;
188
- let rectX = element.x - rectWidth;
189
- let rectY = element.y + element.height / 2 - textHeight / 2 - 2;
206
+ let rectX = paddedRect.left - rectWidth;
207
+ let rectY = paddedRect.top + paddedRect.height / 2 - textHeight / 2 - 2;
190
208
  if (rectX < 0) {
191
- rectX = element.x;
192
- rectY = element.y - rectHeight;
209
+ rectX = paddedRect.left;
210
+ rectY = paddedRect.top - rectHeight;
193
211
  }
194
212
  image.scan(rectX, rectY, rectWidth, rectHeight, function(x, y, idx) {
195
213
  this.bitmap.data[idx + 0] = color.rect >> 24 & 255;
@@ -203,7 +221,7 @@ var createSvgOverlay = (elements, imageWidth, imageHeight) => {
203
221
  rectX,
204
222
  rectY,
205
223
  {
206
- text: element.label,
224
+ text: element.indexId.toString(),
207
225
  alignmentX: import_jimp3.default.HORIZONTAL_ALIGN_CENTER,
208
226
  alignmentY: import_jimp3.default.VERTICAL_ALIGN_MIDDLE
209
227
  },
@@ -215,64 +233,61 @@ var createSvgOverlay = (elements, imageWidth, imageHeight) => {
215
233
  };
216
234
  return createPngOverlay(elements, imageWidth, imageHeight);
217
235
  };
218
- var processImageElementInfo = async (options) => {
219
- const base64Image = options.inputImgBase64.split(";base64,").pop();
220
- (0, import_node_assert2.default)(base64Image, "base64Image is undefined");
221
- const imageBuffer = import_node_buffer3.Buffer.from(base64Image, "base64");
236
+ var compositeElementInfoImg = async (options) => {
237
+ const { inputImgBase64, elementsPositionInfo } = options;
238
+ const imageBuffer = import_node_buffer3.Buffer.from(inputImgBase64, "base64");
222
239
  const image = await import_jimp3.default.read(imageBuffer);
223
240
  const { width, height } = image.bitmap;
224
- if (width && height) {
225
- const svgOverlay = await createSvgOverlay(
226
- options.elementsPositionInfo,
227
- width,
228
- height
229
- );
230
- const svgOverlayWithoutText = await createSvgOverlay(
231
- options.elementsPositionInfoWithoutText,
232
- width,
233
- height
234
- );
235
- const compositeElementInfoImgBase64 = await import_jimp3.default.read(imageBuffer).then(async (image2) => {
236
- const svgImage = await import_jimp3.default.read(svgOverlay);
237
- return image2.composite(svgImage, 0, 0, {
238
- mode: import_jimp3.default.BLEND_SOURCE_OVER,
239
- opacitySource: 1,
240
- opacityDest: 1
241
- });
242
- }).then((compositeImage) => {
243
- return compositeImage.getBufferAsync(import_jimp3.default.MIME_PNG);
244
- }).then((buffer) => {
245
- return buffer.toString("base64");
246
- }).catch((error) => {
247
- throw error;
248
- });
249
- const compositeElementInfoImgWithoutTextBase64 = await import_jimp3.default.read(
250
- imageBuffer
251
- ).then(async (image2) => {
252
- const svgImage = await import_jimp3.default.read(svgOverlayWithoutText);
253
- return image2.composite(svgImage, 0, 0, {
254
- mode: import_jimp3.default.BLEND_SOURCE_OVER,
255
- opacitySource: 1,
256
- opacityDest: 1
257
- });
258
- }).then((compositeImage) => {
259
- return compositeImage.getBufferAsync(import_jimp3.default.MIME_PNG);
260
- }).then((buffer) => {
261
- return buffer.toString("base64");
262
- }).catch((error) => {
263
- throw error;
264
- });
265
- return {
266
- compositeElementInfoImgBase64,
267
- compositeElementInfoImgWithoutTextBase64
268
- };
241
+ if (!width || !height) {
242
+ throw Error("Image processing failed because width or height is undefined");
269
243
  }
270
- throw Error("Image processing failed because width or height is undefined");
244
+ const svgOverlay = await createSvgOverlay(
245
+ elementsPositionInfo,
246
+ width,
247
+ height
248
+ );
249
+ return await import_jimp3.default.read(imageBuffer).then(async (image2) => {
250
+ const svgImage = await import_jimp3.default.read(svgOverlay);
251
+ return image2.composite(svgImage, 0, 0, {
252
+ mode: import_jimp3.default.BLEND_SOURCE_OVER,
253
+ opacitySource: 1,
254
+ opacityDest: 1
255
+ });
256
+ }).then((compositeImage) => {
257
+ return compositeImage.getBufferAsync(import_jimp3.default.MIME_PNG);
258
+ }).then((buffer) => {
259
+ return buffer.toString("base64");
260
+ }).catch((error) => {
261
+ throw error;
262
+ });
263
+ };
264
+ var processImageElementInfo = async (options) => {
265
+ const base64Image = options.inputImgBase64.split(";base64,").pop();
266
+ (0, import_node_assert2.default)(base64Image, "base64Image is undefined");
267
+ const [
268
+ compositeElementInfoImgBase64,
269
+ compositeElementInfoImgWithoutTextBase64
270
+ ] = await Promise.all([
271
+ compositeElementInfoImg({
272
+ inputImgBase64: options.inputImgBase64,
273
+ elementsPositionInfo: options.elementsPositionInfo
274
+ }),
275
+ compositeElementInfoImg({
276
+ inputImgBase64: options.inputImgBase64,
277
+ elementsPositionInfo: options.elementsPositionInfoWithoutText
278
+ })
279
+ ]);
280
+ return {
281
+ compositeElementInfoImgBase64,
282
+ compositeElementInfoImgWithoutTextBase64
283
+ };
271
284
  };
272
285
  // Annotate the CommonJS export names for ESM import in node:
273
286
  0 && (module.exports = {
274
287
  base64Encoded,
288
+ base64ToPngFormat,
275
289
  calculateNewDimensions,
290
+ compositeElementInfoImg,
276
291
  imageInfo,
277
292
  imageInfoOfBase64,
278
293
  processImageElementInfo,
@@ -1,7 +1,7 @@
1
1
  import { Buffer } from 'node:buffer';
2
2
  import { NodeType } from './constants.js';
3
3
 
4
- interface Size {
4
+ interface Size$1 {
5
5
  width: number;
6
6
  height: number;
7
7
  }
@@ -12,7 +12,7 @@ interface Size {
12
12
  * @returns A Promise that resolves to an object containing the width and height of the image
13
13
  * @throws Error if the image data is invalid
14
14
  */
15
- declare function imageInfo(image: string | Buffer): Promise<Size>;
15
+ declare function imageInfo(image: string | Buffer): Promise<Size$1>;
16
16
  /**
17
17
  * Retrieves the dimensions of an image from a base64-encoded string
18
18
  *
@@ -20,7 +20,7 @@ declare function imageInfo(image: string | Buffer): Promise<Size>;
20
20
  * @returns A Promise that resolves to an object containing the width and height of the image
21
21
  * @throws Error if the image data is invalid
22
22
  */
23
- declare function imageInfoOfBase64(imageBase64: string): Promise<Size>;
23
+ declare function imageInfoOfBase64(imageBase64: string): Promise<Size$1>;
24
24
  /**
25
25
  * Encodes an image file to a base64 encoded string
26
26
  *
@@ -32,6 +32,7 @@ declare function imageInfoOfBase64(imageBase64: string): Promise<Size>;
32
32
  * @throws When the image type is not supported, an error will be thrown
33
33
  */
34
34
  declare function base64Encoded(image: string, withHeader?: boolean): string;
35
+ declare function base64ToPngFormat(base64: string): string;
35
36
 
36
37
  /**
37
38
  * Saves a Base64-encoded image to a file
@@ -91,17 +92,31 @@ declare function trimImage(image: string | Buffer): Promise<{
91
92
  height: number;
92
93
  } | null>;
93
94
 
94
- type ElementType = {
95
- x: number;
96
- y: number;
95
+ interface Point {
96
+ left: number;
97
+ top: number;
98
+ }
99
+ interface Size {
97
100
  width: number;
98
101
  height: number;
99
- label: string;
102
+ }
103
+ type Rect = Point & Size;
104
+
105
+ type ElementType = {
106
+ locator: string;
107
+ rect: Rect;
108
+ center: [number, number];
109
+ id: string;
110
+ indexId: number;
100
111
  attributes: {
101
- [key: string]: string;
102
112
  nodeType: NodeType;
113
+ [key: string]: string;
103
114
  };
104
115
  };
116
+ declare const compositeElementInfoImg: (options: {
117
+ inputImgBase64: string;
118
+ elementsPositionInfo: Array<ElementType>;
119
+ }) => Promise<string>;
105
120
  declare const processImageElementInfo: (options: {
106
121
  inputImgBase64: string;
107
122
  elementsPositionInfo: Array<ElementType>;
@@ -111,4 +126,4 @@ declare const processImageElementInfo: (options: {
111
126
  compositeElementInfoImgWithoutTextBase64: string;
112
127
  }>;
113
128
 
114
- export { base64Encoded, calculateNewDimensions, imageInfo, imageInfoOfBase64, processImageElementInfo, resizeImg, saveBase64Image, transformImgPathToBase64, trimImage };
129
+ export { base64Encoded, base64ToPngFormat, calculateNewDimensions, compositeElementInfoImg, imageInfo, imageInfoOfBase64, processImageElementInfo, resizeImg, saveBase64Image, transformImgPathToBase64, trimImage };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@midscene/shared",
3
- "version": "0.5.2-beta-20241010035503.0",
3
+ "version": "0.5.2",
4
4
  "types": "./dist/types/index.d.ts",
5
5
  "main": "./dist/lib/index.js",
6
6
  "module": "./dist/es/index.js",
@@ -1,18 +1,24 @@
1
1
  import assert from 'node:assert';
2
2
  import { Buffer } from 'node:buffer';
3
+ import type { Rect } from '@/types';
3
4
  import Jimp from 'jimp';
4
5
  import type { NodeType } from '../constants';
5
6
 
6
7
  // Define picture path
7
8
  type ElementType = {
8
- x: number;
9
- y: number;
10
- width: number;
11
- height: number;
12
- label: string;
9
+ locator: string;
10
+
11
+ rect: Rect;
12
+
13
+ center: [number, number];
14
+
15
+ id: string;
16
+
17
+ indexId: number;
18
+
13
19
  attributes: {
14
- [key: string]: string;
15
20
  nodeType: NodeType;
21
+ [key: string]: string;
16
22
  };
17
23
  };
18
24
 
@@ -30,26 +36,42 @@ const createSvgOverlay = (
30
36
 
31
37
  // Define color array
32
38
  const colors = [
33
- { rect: 0x0000ffff, text: 0xffffffff }, // blue, white
34
- { rect: 0x8b4513ff, text: 0xffffffff }, // brown, white
39
+ { rect: 0xff0000ff, text: 0xffffffff }, // red, white
40
+ // { rect: 0x0000ffff, text: 0xffffffff }, // blue, white
41
+ // { rect: 0x8b4513ff, text: 0xffffffff }, // brown, white
35
42
  ];
36
43
 
44
+ const boxPadding = 5;
37
45
  for (let index = 0; index < elements.length; index++) {
38
46
  const element = elements[index];
39
47
  const color = colors[index % colors.length];
40
48
 
49
+ // Add 5px padding to the rect
50
+ const paddedRect = {
51
+ left: Math.max(0, element.rect.left - boxPadding),
52
+ top: Math.max(0, element.rect.top - boxPadding),
53
+ width: Math.min(
54
+ imageWidth - element.rect.left,
55
+ element.rect.width + boxPadding * 2,
56
+ ),
57
+ height: Math.min(
58
+ imageHeight - element.rect.top,
59
+ element.rect.height + boxPadding * 2,
60
+ ),
61
+ };
62
+
41
63
  // Draw rectangle
42
64
  image.scan(
43
- element.x,
44
- element.y,
45
- element.width,
46
- element.height,
65
+ paddedRect.left,
66
+ paddedRect.top,
67
+ paddedRect.width,
68
+ paddedRect.height,
47
69
  function (x, y, idx) {
48
70
  if (
49
- x === element.x ||
50
- x === element.x + element.width - 1 ||
51
- y === element.y ||
52
- y === element.y + element.height - 1
71
+ x === paddedRect.left ||
72
+ x === paddedRect.left + paddedRect.width - 1 ||
73
+ y === paddedRect.top ||
74
+ y === paddedRect.top + paddedRect.height - 1
53
75
  ) {
54
76
  this.bitmap.data[idx + 0] = (color.rect >> 24) & 0xff; // R
55
77
  this.bitmap.data[idx + 1] = (color.rect >> 16) & 0xff; // G
@@ -60,17 +82,17 @@ const createSvgOverlay = (
60
82
  );
61
83
 
62
84
  // Calculate text position
63
- const textWidth = element.label.length * 8;
85
+ const textWidth = element.indexId.toString().length * 8;
64
86
  const textHeight = 12;
65
87
  const rectWidth = textWidth + 5;
66
88
  const rectHeight = textHeight + 4;
67
- let rectX = element.x - rectWidth;
68
- let rectY = element.y + element.height / 2 - textHeight / 2 - 2;
89
+ let rectX = paddedRect.left - rectWidth;
90
+ let rectY = paddedRect.top + paddedRect.height / 2 - textHeight / 2 - 2;
69
91
 
70
92
  // Check if obscured by the left
71
93
  if (rectX < 0) {
72
- rectX = element.x;
73
- rectY = element.y - rectHeight;
94
+ rectX = paddedRect.left;
95
+ rectY = paddedRect.top - rectHeight;
74
96
  }
75
97
 
76
98
  // Draw text background
@@ -87,7 +109,7 @@ const createSvgOverlay = (
87
109
  rectX,
88
110
  rectY,
89
111
  {
90
- text: element.label,
112
+ text: element.indexId.toString(),
91
113
  alignmentX: Jimp.HORIZONTAL_ALIGN_CENTER,
92
114
  alignmentY: Jimp.VERTICAL_ALIGN_MIDDLE,
93
115
  },
@@ -102,78 +124,71 @@ const createSvgOverlay = (
102
124
  return createPngOverlay(elements, imageWidth, imageHeight);
103
125
  };
104
126
 
105
- export const processImageElementInfo = async (options: {
127
+ export const compositeElementInfoImg = async (options: {
106
128
  inputImgBase64: string;
107
129
  elementsPositionInfo: Array<ElementType>;
108
- elementsPositionInfoWithoutText: Array<ElementType>;
109
130
  }) => {
110
- // Get the size of the original image
111
- const base64Image = options.inputImgBase64.split(';base64,').pop();
112
- assert(base64Image, 'base64Image is undefined');
113
-
114
- const imageBuffer = Buffer.from(base64Image, 'base64');
131
+ const { inputImgBase64, elementsPositionInfo } = options;
132
+ const imageBuffer = Buffer.from(inputImgBase64, 'base64');
115
133
  const image = await Jimp.read(imageBuffer);
116
134
  const { width, height } = image.bitmap;
117
135
 
118
- if (width && height) {
119
- // Create svg overlay
120
- const svgOverlay = await createSvgOverlay(
121
- options.elementsPositionInfo,
122
- width,
123
- height,
124
- );
125
- const svgOverlayWithoutText = await createSvgOverlay(
126
- options.elementsPositionInfoWithoutText,
127
- width,
128
- height,
129
- );
130
-
131
- // Composite picture
132
- const compositeElementInfoImgBase64 = await Jimp.read(imageBuffer)
133
- .then(async (image: Jimp) => {
134
- const svgImage = await Jimp.read(svgOverlay);
135
- return image.composite(svgImage, 0, 0, {
136
- mode: Jimp.BLEND_SOURCE_OVER,
137
- opacitySource: 1,
138
- opacityDest: 1,
139
- });
140
- })
141
- .then((compositeImage: Jimp) => {
142
- return compositeImage.getBufferAsync(Jimp.MIME_PNG);
143
- })
144
- .then((buffer: Buffer) => {
145
- return buffer.toString('base64');
146
- })
147
- .catch((error: unknown) => {
148
- throw error;
149
- });
136
+ if (!width || !height) {
137
+ throw Error('Image processing failed because width or height is undefined');
138
+ }
150
139
 
151
- // Composite picture withoutText
152
- const compositeElementInfoImgWithoutTextBase64 = await Jimp.read(
153
- imageBuffer,
154
- )
155
- .then(async (image: Jimp) => {
156
- const svgImage = await Jimp.read(svgOverlayWithoutText);
157
- return image.composite(svgImage, 0, 0, {
158
- mode: Jimp.BLEND_SOURCE_OVER,
159
- opacitySource: 1,
160
- opacityDest: 1,
161
- });
162
- })
163
- .then((compositeImage: Jimp) => {
164
- return compositeImage.getBufferAsync(Jimp.MIME_PNG);
165
- })
166
- .then((buffer: Buffer) => {
167
- return buffer.toString('base64');
168
- })
169
- .catch((error: unknown) => {
170
- throw error;
140
+ // Create svg overlay
141
+ const svgOverlay = await createSvgOverlay(
142
+ elementsPositionInfo,
143
+ width,
144
+ height,
145
+ );
146
+
147
+ return await Jimp.read(imageBuffer)
148
+ .then(async (image: Jimp) => {
149
+ const svgImage = await Jimp.read(svgOverlay);
150
+ return image.composite(svgImage, 0, 0, {
151
+ mode: Jimp.BLEND_SOURCE_OVER,
152
+ opacitySource: 1,
153
+ opacityDest: 1,
171
154
  });
155
+ })
156
+ .then((compositeImage: Jimp) => {
157
+ return compositeImage.getBufferAsync(Jimp.MIME_PNG);
158
+ })
159
+ .then((buffer: Buffer) => {
160
+ return buffer.toString('base64');
161
+ })
162
+ .catch((error: unknown) => {
163
+ throw error;
164
+ });
165
+ };
172
166
 
173
- return {
174
- compositeElementInfoImgBase64,
175
- compositeElementInfoImgWithoutTextBase64,
176
- };
177
- }
178
- throw Error('Image processing failed because width or height is undefined');
167
+ export const processImageElementInfo = async (options: {
168
+ inputImgBase64: string;
169
+ elementsPositionInfo: Array<ElementType>;
170
+ elementsPositionInfoWithoutText: Array<ElementType>;
171
+ }) => {
172
+ // Get the size of the original image
173
+ const base64Image = options.inputImgBase64.split(';base64,').pop();
174
+ assert(base64Image, 'base64Image is undefined');
175
+
176
+ const [
177
+ compositeElementInfoImgBase64,
178
+ compositeElementInfoImgWithoutTextBase64,
179
+ ] = await Promise.all([
180
+ compositeElementInfoImg({
181
+ inputImgBase64: options.inputImgBase64,
182
+ elementsPositionInfo: options.elementsPositionInfo,
183
+ }),
184
+ compositeElementInfoImg({
185
+ inputImgBase64: options.inputImgBase64,
186
+ elementsPositionInfo: options.elementsPositionInfoWithoutText,
187
+ }),
188
+ ]);
189
+
190
+ return {
191
+ compositeElementInfoImgBase64,
192
+ compositeElementInfoImgWithoutTextBase64,
193
+ };
179
194
  };
package/src/img/index.ts CHANGED
@@ -1,4 +1,9 @@
1
- export { imageInfo, imageInfoOfBase64, base64Encoded } from './info';
1
+ export {
2
+ imageInfo,
3
+ imageInfoOfBase64,
4
+ base64Encoded,
5
+ base64ToPngFormat,
6
+ } from './info';
2
7
  export {
3
8
  trimImage,
4
9
  calculateNewDimensions,
@@ -6,4 +11,4 @@ export {
6
11
  transformImgPathToBase64,
7
12
  saveBase64Image,
8
13
  } from './transform';
9
- export { processImageElementInfo } from './box-select';
14
+ export { processImageElementInfo, compositeElementInfoImg } from './box-select';
package/src/img/info.ts CHANGED
@@ -69,3 +69,7 @@ export function base64Encoded(image: string, withHeader = true) {
69
69
  }
70
70
  throw new Error('unsupported image type');
71
71
  }
72
+
73
+ export function base64ToPngFormat(base64: string) {
74
+ return `data:image/png;base64,${base64}`;
75
+ }