Skip to content

Commit ee6cc19

Browse files
committed
Issue viliusle#266 - Draw border by analyising the pixel data
1 parent 8b180cb commit ee6cc19

File tree

2 files changed

+76
-19
lines changed

2 files changed

+76
-19
lines changed

src/js/libs/image-border-effect.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
function hexToRgb(hex) {
2+
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
3+
4+
return result
5+
? [
6+
parseInt(result[1], 16),
7+
parseInt(result[2], 16),
8+
parseInt(result[3], 16),
9+
]
10+
: [0, 0, 0];
11+
}
12+
13+
const drawBorder = (ctx, hexColor) => {
14+
const width = ctx.canvas.width,
15+
height = ctx.canvas.height;
16+
const imageData = ctx.getImageData(0, 0, width, height);
17+
18+
const dataCopy = new Uint8ClampedArray(imageData.data);
19+
const length = imageData.data.length;
20+
21+
const changeColor = (position) => {
22+
if (imageData.data[position + 3] === 0) {
23+
dataCopy.set([...hexToRgb(hexColor), 255], position);
24+
}
25+
};
26+
27+
for (let i = 0; i < length; i += 4) {
28+
const top = i - width * 4;
29+
const bottom = i + width * 4;
30+
const left = i - 4;
31+
const right = i + 4;
32+
const topLeftCorner = i - width * 4 - 4;
33+
const topRightCorner = i - width * 4 + 4;
34+
const bottomLeftCorner = i + width * 4 - 4;
35+
const bottomRightCorner = i + width * 4 + 4;
36+
37+
let isNoneTransparent = imageData.data[i + 3] > 0;
38+
if (
39+
!isNoneTransparent ||
40+
i % (width * 4) === 0 ||
41+
i + width * 4 >= length
42+
) {
43+
continue;
44+
}
45+
46+
// Change left, top, right and bottom neighbors colors if they are transparent
47+
changeColor(left);
48+
changeColor(top);
49+
changeColor(right);
50+
changeColor(bottom);
51+
52+
// Changes corner neighbors colors if they are transparent
53+
changeColor(topLeftCorner);
54+
changeColor(topRightCorner);
55+
changeColor(bottomLeftCorner);
56+
changeColor(bottomRightCorner);
57+
}
58+
59+
imageData.data.set(dataCopy);
60+
61+
return imageData;
62+
};
63+
64+
export default drawBorder;

src/js/modules/effects/borders.js

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Base_layers_class from "./../../core/base-layers.js";
44
import Dialog_class from "./../../libs/popup.js";
55
import alertify from "./../../../../node_modules/alertifyjs/build/alertify.min.js";
66
import Effects_browser_class from "./browser";
7+
import drawBorder from "../../libs/image-border-effect.js";
78

89
class Effects_borders_class {
910
constructor() {
@@ -48,7 +49,6 @@ class Effects_borders_class {
4849
demo(canvas_id, canvas_thumb) {
4950
var canvas = document.getElementById(canvas_id);
5051
var ctx = canvas.getContext("2d");
51-
5252
//draw
5353
ctx.drawImage(
5454
canvas_thumb,
@@ -70,7 +70,6 @@ class Effects_borders_class {
7070

7171
render_post(ctx, data, layer) {
7272
const size = Math.max(0, data.params.size);
73-
7473
const x = layer.x;
7574
const y = layer.y;
7675
const width = parseInt(layer.width);
@@ -84,24 +83,18 @@ class Effects_borders_class {
8483

8584
ctx.save();
8685

87-
//set styles
88-
ctx.strokeStyle = data.params.color;
89-
ctx.lineWidth = size;
86+
// We need to get aspect ratio for preview canvas and for the main canvas when it gets zoom < 1
87+
const aspectRatio = ctx.canvas.height / config.HEIGHT;
9088

91-
//draw with rotation support
92-
ctx.translate(layer.x + width / 2, layer.y + height / 2);
93-
ctx.rotate((layer.rotate * Math.PI) / 180);
94-
const x_new = -width / 2;
95-
const y_new = -height / 2;
96-
97-
ctx.beginPath();
98-
ctx.rect(
99-
x_new - size * 0.5,
100-
y_new - size * 0.5,
101-
width + size,
102-
height + size
103-
);
104-
ctx.stroke();
89+
let borderWidth = size * aspectRatio;
90+
// This is the case when it's zoomed more than the canvas size
91+
if (aspectRatio >= 1 && aspectRatio <= config.ZOOM) {
92+
borderWidth = size * config.ZOOM;
93+
}
94+
// Draw border multiple times to get the necessary with in pixels
95+
for (let i = 0; i < borderWidth; i++) {
96+
ctx.putImageData(drawBorder(ctx, data.params.color), 0, 0);
97+
}
10598

10699
ctx.restore();
107100
}

0 commit comments

Comments
 (0)