pixel-data-js 0.16.0 → 0.17.0
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/index.dev.cjs +1648 -908
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +1629 -906
- package/dist/index.dev.js.map +1 -1
- package/dist/index.prod.cjs +1648 -908
- package/dist/index.prod.cjs.map +1 -1
- package/dist/index.prod.d.ts +287 -67
- package/dist/index.prod.js +1629 -906
- package/dist/index.prod.js.map +1 -1
- package/package.json +1 -1
- package/src/BlendModes/BlendModeRegistry.ts +34 -50
- package/src/BlendModes/blend-modes-perfect.ts +313 -136
- package/src/BlendModes/blend-modes.ts +6 -0
- package/src/History/HistoryManager.ts +83 -0
- package/src/History/PixelAccumulator.ts +191 -0
- package/src/History/PixelEngineConfig.ts +18 -0
- package/src/History/PixelMutator/mutatorApplyMask.ts +20 -0
- package/src/History/PixelMutator/mutatorBlendColor.ts +22 -0
- package/src/History/PixelMutator/mutatorBlendPixel.ts +37 -0
- package/src/History/PixelMutator/mutatorBlendPixelData.ts +24 -0
- package/src/History/PixelMutator/mutatorFillPixelData.ts +21 -0
- package/src/History/PixelMutator/mutatorInvert.ts +18 -0
- package/src/History/PixelMutator.ts +18 -0
- package/src/History/PixelPatchTiles.ts +52 -0
- package/src/History/PixelWriter.ts +79 -0
- package/src/ImageData/{writeImageDataPixels.ts → writeImageDataBuffer.ts} +3 -3
- package/src/PixelData/applyCircleBrushToPixelData.ts +69 -0
- package/src/PixelData/applyMaskToPixelData.ts +1 -1
- package/src/PixelData/applyRectBrushToPixelData.ts +102 -0
- package/src/PixelData/invertPixelData.ts +74 -7
- package/src/PixelData/writePixelDataBuffer.ts +65 -0
- package/src/_types.ts +31 -11
- package/src/index.ts +18 -1
package/dist/index.dev.js
CHANGED
|
@@ -29,33 +29,37 @@ overwriteBase.isOverwrite = true;
|
|
|
29
29
|
|
|
30
30
|
// src/BlendModes/BlendModeRegistry.ts
|
|
31
31
|
function makeBlendModeRegistry(blendModes, initialEntries) {
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
const
|
|
32
|
+
const blendToName = /* @__PURE__ */ new Map();
|
|
33
|
+
const blendToIndex = /* @__PURE__ */ new Map();
|
|
34
|
+
const indexToName = [];
|
|
35
|
+
const indexToBlend = [];
|
|
36
|
+
const nameToBlend = {};
|
|
37
|
+
const nameToIndex = {};
|
|
36
38
|
const add = (name, index, blendFn) => {
|
|
37
|
-
if (
|
|
38
|
-
throw new Error(`
|
|
39
|
+
if (!Number.isFinite(index)) {
|
|
40
|
+
throw new Error(`Index "${index}" is not a number. Attempting to add name: "${name}", index: "${index}"`);
|
|
39
41
|
}
|
|
40
|
-
if (
|
|
41
|
-
throw new Error(`Blend Mode name: "${name}"
|
|
42
|
+
if (indexToBlend[index]) {
|
|
43
|
+
throw new Error(`Blend Mode index: ${index} is already used. Attempting to add name: "${name}", index: "${index}"`);
|
|
42
44
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
indexToName[index] = name;
|
|
46
|
+
indexToBlend[index] = blendFn;
|
|
47
|
+
blendToIndex.set(blendFn, index);
|
|
48
|
+
blendToName.set(blendFn, name);
|
|
49
|
+
nameToBlend[name] = blendFn;
|
|
50
|
+
nameToIndex[name] = index;
|
|
48
51
|
};
|
|
49
52
|
for (const [name, index] of Object.entries(blendModes)) {
|
|
50
53
|
const blend = initialEntries[index];
|
|
51
54
|
add(name, index, blend);
|
|
52
55
|
}
|
|
53
56
|
return {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
nameToBlend,
|
|
58
|
+
nameToIndex,
|
|
59
|
+
blendToIndex,
|
|
60
|
+
blendToName,
|
|
61
|
+
indexToBlend,
|
|
62
|
+
indexToName,
|
|
59
63
|
indexType: null,
|
|
60
64
|
nameType: null
|
|
61
65
|
};
|
|
@@ -840,14 +844,18 @@ var sourceOverPerfect = (src, dst) => {
|
|
|
840
844
|
const sa = src >>> 24 & 255;
|
|
841
845
|
if (sa === 255) return src;
|
|
842
846
|
if (sa === 0) return dst;
|
|
847
|
+
const invA = 255 - sa;
|
|
843
848
|
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
844
849
|
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
845
850
|
const da = dst >>> 24 & 255;
|
|
846
|
-
const
|
|
847
|
-
const r =
|
|
848
|
-
const
|
|
849
|
-
const
|
|
850
|
-
const
|
|
851
|
+
const tR = sr * sa + dr * invA;
|
|
852
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
853
|
+
const tG = sg * sa + dg * invA;
|
|
854
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
855
|
+
const tB = sb * sa + db * invA;
|
|
856
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
857
|
+
const tA = 255 * sa + da * invA;
|
|
858
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
851
859
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
852
860
|
};
|
|
853
861
|
var darkenPerfect = (src, dst) => {
|
|
@@ -860,44 +868,71 @@ var darkenPerfect = (src, dst) => {
|
|
|
860
868
|
const bb = sb < db ? sb : db;
|
|
861
869
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
862
870
|
const invA = 255 - sa;
|
|
863
|
-
const
|
|
864
|
-
const
|
|
865
|
-
const
|
|
866
|
-
const
|
|
871
|
+
const da = dst >>> 24 & 255;
|
|
872
|
+
const tR = br * sa + dr * invA;
|
|
873
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
874
|
+
const tG = bg * sa + dg * invA;
|
|
875
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
876
|
+
const tB = bb * sa + db * invA;
|
|
877
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
878
|
+
const tA = 255 * sa + da * invA;
|
|
879
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
867
880
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
868
881
|
};
|
|
869
882
|
var multiplyPerfect = (src, dst) => {
|
|
870
883
|
const sa = src >>> 24 & 255;
|
|
871
884
|
if (sa === 0) return dst;
|
|
872
|
-
const
|
|
873
|
-
const
|
|
874
|
-
const
|
|
875
|
-
const
|
|
876
|
-
const
|
|
885
|
+
const dr = dst & 255;
|
|
886
|
+
const dg = dst >>> 8 & 255;
|
|
887
|
+
const db = dst >>> 16 & 255;
|
|
888
|
+
const da = dst >>> 24 & 255;
|
|
889
|
+
const sr = src & 255;
|
|
890
|
+
const sg = src >>> 8 & 255;
|
|
891
|
+
const sb = src >>> 16 & 255;
|
|
892
|
+
const mR = sr * dr;
|
|
893
|
+
const br = mR + 1 + (mR >> 8) >> 8;
|
|
894
|
+
const mG = sg * dg;
|
|
895
|
+
const bg = mG + 1 + (mG >> 8) >> 8;
|
|
896
|
+
const mB = sb * db;
|
|
897
|
+
const bb = mB + 1 + (mB >> 8) >> 8;
|
|
877
898
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
878
899
|
const invA = 255 - sa;
|
|
879
|
-
const
|
|
880
|
-
const r =
|
|
881
|
-
const
|
|
882
|
-
const
|
|
883
|
-
const
|
|
900
|
+
const tR = br * sa + dr * invA;
|
|
901
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
902
|
+
const tG = bg * sa + dg * invA;
|
|
903
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
904
|
+
const tB = bb * sa + db * invA;
|
|
905
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
906
|
+
const tA = 255 * sa + da * invA;
|
|
907
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
884
908
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
885
909
|
};
|
|
886
910
|
var colorBurnPerfect = (src, dst) => {
|
|
887
911
|
const sa = src >>> 24 & 255;
|
|
888
912
|
if (sa === 0) return dst;
|
|
889
|
-
const
|
|
890
|
-
const
|
|
891
|
-
const
|
|
892
|
-
const
|
|
893
|
-
const
|
|
913
|
+
const dr = dst & 255;
|
|
914
|
+
const dg = dst >>> 8 & 255;
|
|
915
|
+
const db = dst >>> 16 & 255;
|
|
916
|
+
const sr = src & 255;
|
|
917
|
+
const sg = src >>> 8 & 255;
|
|
918
|
+
const sb = src >>> 16 & 255;
|
|
919
|
+
const resR = dr === 255 ? 255 : sr === 0 ? 0 : 255 - ((255 - dr) * 255 / sr | 0);
|
|
920
|
+
const br = resR < 0 ? 0 : resR;
|
|
921
|
+
const resG = dg === 255 ? 255 : sg === 0 ? 0 : 255 - ((255 - dg) * 255 / sg | 0);
|
|
922
|
+
const bg = resG < 0 ? 0 : resG;
|
|
923
|
+
const resB = db === 255 ? 255 : sb === 0 ? 0 : 255 - ((255 - db) * 255 / sb | 0);
|
|
924
|
+
const bb = resB < 0 ? 0 : resB;
|
|
894
925
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
895
926
|
const invA = 255 - sa;
|
|
896
927
|
const da = dst >>> 24 & 255;
|
|
897
|
-
const
|
|
898
|
-
const
|
|
899
|
-
const
|
|
900
|
-
const
|
|
928
|
+
const tR = br * sa + dr * invA;
|
|
929
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
930
|
+
const tG = bg * sa + dg * invA;
|
|
931
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
932
|
+
const tB = bb * sa + db * invA;
|
|
933
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
934
|
+
const tA = 255 * sa + da * invA;
|
|
935
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
901
936
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
902
937
|
};
|
|
903
938
|
var linearBurnPerfect = (src, dst) => {
|
|
@@ -913,10 +948,15 @@ var linearBurnPerfect = (src, dst) => {
|
|
|
913
948
|
const bb = bbU < 0 ? 0 : bbU;
|
|
914
949
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
915
950
|
const invA = 255 - sa;
|
|
916
|
-
const
|
|
917
|
-
const
|
|
918
|
-
const
|
|
919
|
-
const
|
|
951
|
+
const da = dst >>> 24 & 255;
|
|
952
|
+
const tR = br * sa + dr * invA;
|
|
953
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
954
|
+
const tG = bg * sa + dg * invA;
|
|
955
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
956
|
+
const tB = bb * sa + db * invA;
|
|
957
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
958
|
+
const tA = 255 * sa + da * invA;
|
|
959
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
920
960
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
921
961
|
};
|
|
922
962
|
var darkerPerfect = (src, dst) => {
|
|
@@ -938,10 +978,15 @@ var darkerPerfect = (src, dst) => {
|
|
|
938
978
|
}
|
|
939
979
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
940
980
|
const invA = 255 - sa;
|
|
941
|
-
const
|
|
942
|
-
const
|
|
943
|
-
const
|
|
944
|
-
const
|
|
981
|
+
const da = dst >>> 24 & 255;
|
|
982
|
+
const tR = br * sa + dr * invA;
|
|
983
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
984
|
+
const tG = bg * sa + dg * invA;
|
|
985
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
986
|
+
const tB = bb * sa + db * invA;
|
|
987
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
988
|
+
const tA = 255 * sa + da * invA;
|
|
989
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
945
990
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
946
991
|
};
|
|
947
992
|
var lightenPerfect = (src, dst) => {
|
|
@@ -953,10 +998,15 @@ var lightenPerfect = (src, dst) => {
|
|
|
953
998
|
const bb = (src >>> 16 & 255) > db ? src >>> 16 & 255 : db;
|
|
954
999
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
955
1000
|
const invA = 255 - sa;
|
|
956
|
-
const
|
|
957
|
-
const
|
|
958
|
-
const
|
|
959
|
-
const
|
|
1001
|
+
const da = dst >>> 24 & 255;
|
|
1002
|
+
const tR = br * sa + dr * invA;
|
|
1003
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1004
|
+
const tG = bg * sa + dg * invA;
|
|
1005
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1006
|
+
const tB = bb * sa + db * invA;
|
|
1007
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1008
|
+
const tA = 255 * sa + da * invA;
|
|
1009
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
960
1010
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
961
1011
|
};
|
|
962
1012
|
var screenPerfect = (src, dst) => {
|
|
@@ -968,26 +1018,43 @@ var screenPerfect = (src, dst) => {
|
|
|
968
1018
|
const bb = 255 - ((255 - (src >>> 16 & 255)) * (255 - db) / 255 | 0);
|
|
969
1019
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
970
1020
|
const invA = 255 - sa;
|
|
971
|
-
const
|
|
972
|
-
const
|
|
973
|
-
const
|
|
974
|
-
const
|
|
1021
|
+
const da = dst >>> 24 & 255;
|
|
1022
|
+
const tR = br * sa + dr * invA;
|
|
1023
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1024
|
+
const tG = bg * sa + dg * invA;
|
|
1025
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1026
|
+
const tB = bb * sa + db * invA;
|
|
1027
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1028
|
+
const tA = 255 * sa + da * invA;
|
|
1029
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
975
1030
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
976
1031
|
};
|
|
977
1032
|
var colorDodgePerfect = (src, dst) => {
|
|
978
1033
|
const sa = src >>> 24 & 255;
|
|
979
1034
|
if (sa === 0) return dst;
|
|
980
|
-
const dr = dst & 255
|
|
981
|
-
const
|
|
982
|
-
const
|
|
983
|
-
const
|
|
984
|
-
const
|
|
1035
|
+
const dr = dst & 255;
|
|
1036
|
+
const dg = dst >>> 8 & 255;
|
|
1037
|
+
const db = dst >>> 16 & 255;
|
|
1038
|
+
const sr = src & 255;
|
|
1039
|
+
const sg = src >>> 8 & 255;
|
|
1040
|
+
const sb = src >>> 16 & 255;
|
|
1041
|
+
const resR = sr === 255 ? 255 : dr * 255 / (255 - sr) | 0;
|
|
1042
|
+
const br = resR > 255 ? 255 : resR;
|
|
1043
|
+
const resG = sg === 255 ? 255 : dg * 255 / (255 - sg) | 0;
|
|
1044
|
+
const bg = resG > 255 ? 255 : resG;
|
|
1045
|
+
const resB = sb === 255 ? 255 : db * 255 / (255 - sb) | 0;
|
|
1046
|
+
const bb = resB > 255 ? 255 : resB;
|
|
985
1047
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
986
1048
|
const invA = 255 - sa;
|
|
987
|
-
const
|
|
988
|
-
const
|
|
989
|
-
const
|
|
990
|
-
const
|
|
1049
|
+
const da = dst >>> 24 & 255;
|
|
1050
|
+
const tR = br * sa + dr * invA;
|
|
1051
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1052
|
+
const tG = bg * sa + dg * invA;
|
|
1053
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1054
|
+
const tB = bb * sa + db * invA;
|
|
1055
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1056
|
+
const tA = 255 * sa + da * invA;
|
|
1057
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
991
1058
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
992
1059
|
};
|
|
993
1060
|
var linearDodgePerfect = (src, dst) => {
|
|
@@ -1002,10 +1069,15 @@ var linearDodgePerfect = (src, dst) => {
|
|
|
1002
1069
|
const bb = bbU > 255 ? 255 : bbU;
|
|
1003
1070
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1004
1071
|
const invA = 255 - sa;
|
|
1005
|
-
const
|
|
1006
|
-
const
|
|
1007
|
-
const
|
|
1008
|
-
const
|
|
1072
|
+
const da = dst >>> 24 & 255;
|
|
1073
|
+
const tR = br * sa + dr * invA;
|
|
1074
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1075
|
+
const tG = bg * sa + dg * invA;
|
|
1076
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1077
|
+
const tB = bb * sa + db * invA;
|
|
1078
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1079
|
+
const tA = 255 * sa + da * invA;
|
|
1080
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1009
1081
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1010
1082
|
};
|
|
1011
1083
|
var lighterPerfect = (src, dst) => {
|
|
@@ -1027,10 +1099,15 @@ var lighterPerfect = (src, dst) => {
|
|
|
1027
1099
|
}
|
|
1028
1100
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1029
1101
|
const invA = 255 - sa;
|
|
1030
|
-
const
|
|
1031
|
-
const
|
|
1032
|
-
const
|
|
1033
|
-
const
|
|
1102
|
+
const da = dst >>> 24 & 255;
|
|
1103
|
+
const tR = br * sa + dr * invA;
|
|
1104
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1105
|
+
const tG = bg * sa + dg * invA;
|
|
1106
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1107
|
+
const tB = bb * sa + db * invA;
|
|
1108
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1109
|
+
const tA = 255 * sa + da * invA;
|
|
1110
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1034
1111
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1035
1112
|
};
|
|
1036
1113
|
var overlayPerfect = (src, dst) => {
|
|
@@ -1043,10 +1120,15 @@ var overlayPerfect = (src, dst) => {
|
|
|
1043
1120
|
const bb = db < 128 ? 2 * sb * db / 255 | 0 : 255 - (2 * (255 - sb) * (255 - db) / 255 | 0);
|
|
1044
1121
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1045
1122
|
const invA = 255 - sa;
|
|
1046
|
-
const
|
|
1047
|
-
const
|
|
1048
|
-
const
|
|
1049
|
-
const
|
|
1123
|
+
const da = dst >>> 24 & 255;
|
|
1124
|
+
const tR = br * sa + dr * invA;
|
|
1125
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1126
|
+
const tG = bg * sa + dg * invA;
|
|
1127
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1128
|
+
const tB = bb * sa + db * invA;
|
|
1129
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1130
|
+
const tA = 255 * sa + da * invA;
|
|
1131
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1050
1132
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1051
1133
|
};
|
|
1052
1134
|
var softLightPerfect = (src, dst) => {
|
|
@@ -1054,15 +1136,26 @@ var softLightPerfect = (src, dst) => {
|
|
|
1054
1136
|
if (sa === 0) return dst;
|
|
1055
1137
|
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
1056
1138
|
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
1057
|
-
const
|
|
1058
|
-
const
|
|
1059
|
-
const
|
|
1139
|
+
const mR = sr * dr;
|
|
1140
|
+
const scR = (255 - sr) * (255 - dr);
|
|
1141
|
+
const br = (255 - dr) * (mR + 1 + (mR >> 8) >> 8) + dr * (255 - (scR + 1 + (scR >> 8) >> 8)) + 1 + ((255 - dr) * (mR + 1 + (mR >> 8) >> 8) + dr * (255 - (scR + 1 + (scR >> 8) >> 8)) >> 8) >> 8;
|
|
1142
|
+
const mG = sg * dg;
|
|
1143
|
+
const scG = (255 - sg) * (255 - dg);
|
|
1144
|
+
const bg = (255 - dg) * (mG + 1 + (mG >> 8) >> 8) + dg * (255 - (scG + 1 + (scG >> 8) >> 8)) + 1 + ((255 - dg) * (mG + 1 + (mG >> 8) >> 8) + dg * (255 - (scG + 1 + (scG >> 8) >> 8)) >> 8) >> 8;
|
|
1145
|
+
const mB = sb * db;
|
|
1146
|
+
const scB = (255 - sb) * (255 - db);
|
|
1147
|
+
const bb = (255 - db) * (mB + 1 + (mB >> 8) >> 8) + db * (255 - (scB + 1 + (scB >> 8) >> 8)) + 1 + ((255 - db) * (mB + 1 + (mB >> 8) >> 8) + db * (255 - (scB + 1 + (scB >> 8) >> 8)) >> 8) >> 8;
|
|
1060
1148
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1061
1149
|
const invA = 255 - sa;
|
|
1062
|
-
const
|
|
1063
|
-
const
|
|
1064
|
-
const
|
|
1065
|
-
const
|
|
1150
|
+
const da = dst >>> 24 & 255;
|
|
1151
|
+
const tR = br * sa + dr * invA;
|
|
1152
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1153
|
+
const tG = bg * sa + dg * invA;
|
|
1154
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1155
|
+
const tB = bb * sa + db * invA;
|
|
1156
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1157
|
+
const tA = 255 * sa + da * invA;
|
|
1158
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1066
1159
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1067
1160
|
};
|
|
1068
1161
|
var hardLightPerfect = (src, dst) => {
|
|
@@ -1075,10 +1168,15 @@ var hardLightPerfect = (src, dst) => {
|
|
|
1075
1168
|
const bb = sb < 128 ? 2 * sb * db / 255 | 0 : 255 - (2 * (255 - sb) * (255 - db) / 255 | 0);
|
|
1076
1169
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1077
1170
|
const invA = 255 - sa;
|
|
1078
|
-
const
|
|
1079
|
-
const
|
|
1080
|
-
const
|
|
1081
|
-
const
|
|
1171
|
+
const da = dst >>> 24 & 255;
|
|
1172
|
+
const tR = br * sa + dr * invA;
|
|
1173
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1174
|
+
const tG = bg * sa + dg * invA;
|
|
1175
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1176
|
+
const tB = bb * sa + db * invA;
|
|
1177
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1178
|
+
const tA = 255 * sa + da * invA;
|
|
1179
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1082
1180
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1083
1181
|
};
|
|
1084
1182
|
var vividLightPerfect = (src, dst) => {
|
|
@@ -1091,10 +1189,15 @@ var vividLightPerfect = (src, dst) => {
|
|
|
1091
1189
|
const bb = sb < 128 ? sb === 0 ? 0 : Math.max(0, 255 - ((255 - db) * 255 / (2 * sb) | 0)) : sb === 255 ? 255 : Math.min(255, db * 255 / (2 * (255 - sb)) | 0);
|
|
1092
1190
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1093
1191
|
const invA = 255 - sa;
|
|
1094
|
-
const
|
|
1095
|
-
const
|
|
1096
|
-
const
|
|
1097
|
-
const
|
|
1192
|
+
const da = dst >>> 24 & 255;
|
|
1193
|
+
const tR = br * sa + dr * invA;
|
|
1194
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1195
|
+
const tG = bg * sa + dg * invA;
|
|
1196
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1197
|
+
const tB = bb * sa + db * invA;
|
|
1198
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1199
|
+
const tA = 255 * sa + da * invA;
|
|
1200
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1098
1201
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1099
1202
|
};
|
|
1100
1203
|
var linearLightPerfect = (src, dst) => {
|
|
@@ -1110,10 +1213,15 @@ var linearLightPerfect = (src, dst) => {
|
|
|
1110
1213
|
const bb = bbU < 0 ? 0 : bbU > 255 ? 255 : bbU;
|
|
1111
1214
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1112
1215
|
const invA = 255 - sa;
|
|
1113
|
-
const
|
|
1114
|
-
const
|
|
1115
|
-
const
|
|
1116
|
-
const
|
|
1216
|
+
const da = dst >>> 24 & 255;
|
|
1217
|
+
const tR = br * sa + dr * invA;
|
|
1218
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1219
|
+
const tG = bg * sa + dg * invA;
|
|
1220
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1221
|
+
const tB = bb * sa + db * invA;
|
|
1222
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1223
|
+
const tA = 255 * sa + da * invA;
|
|
1224
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1117
1225
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1118
1226
|
};
|
|
1119
1227
|
var pinLightPerfect = (src, dst) => {
|
|
@@ -1131,10 +1239,14 @@ var pinLightPerfect = (src, dst) => {
|
|
|
1131
1239
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1132
1240
|
const invA = 255 - sa;
|
|
1133
1241
|
const da = dst >>> 24 & 255;
|
|
1134
|
-
const
|
|
1135
|
-
const
|
|
1136
|
-
const
|
|
1137
|
-
const
|
|
1242
|
+
const tR = br * sa + dr * invA;
|
|
1243
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1244
|
+
const tG = bg * sa + dg * invA;
|
|
1245
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1246
|
+
const tB = bb * sa + db * invA;
|
|
1247
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1248
|
+
const tA = 255 * sa + da * invA;
|
|
1249
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1138
1250
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1139
1251
|
};
|
|
1140
1252
|
var hardMixPerfect = (src, dst) => {
|
|
@@ -1147,33 +1259,36 @@ var hardMixPerfect = (src, dst) => {
|
|
|
1147
1259
|
const bb = (sb < 128 ? sb === 0 ? 0 : Math.max(0, 255 - ((255 - db) * 255 / (2 * sb) | 0)) : sb === 255 ? 255 : Math.min(255, db * 255 / (2 * (255 - sb)) | 0)) < 128 ? 0 : 255;
|
|
1148
1260
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1149
1261
|
const invA = 255 - sa;
|
|
1150
|
-
const
|
|
1151
|
-
const
|
|
1152
|
-
const
|
|
1153
|
-
const
|
|
1262
|
+
const da = dst >>> 24 & 255;
|
|
1263
|
+
const tR = br * sa + dr * invA;
|
|
1264
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1265
|
+
const tG = bg * sa + dg * invA;
|
|
1266
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1267
|
+
const tB = bb * sa + db * invA;
|
|
1268
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1269
|
+
const tA = 255 * sa + da * invA;
|
|
1270
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1154
1271
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1155
1272
|
};
|
|
1156
1273
|
var differencePerfect = (src, dst) => {
|
|
1157
1274
|
const sa = src >>> 24 & 255;
|
|
1158
1275
|
if (sa === 0) return dst;
|
|
1159
|
-
const dr = dst & 255;
|
|
1160
|
-
const
|
|
1161
|
-
const
|
|
1162
|
-
const
|
|
1163
|
-
const
|
|
1164
|
-
|
|
1165
|
-
const br = Math.abs(dr - sr);
|
|
1166
|
-
const bg = Math.abs(dg - sg);
|
|
1167
|
-
const bb = Math.abs(db - sb);
|
|
1168
|
-
if (sa === 255) {
|
|
1169
|
-
return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1170
|
-
}
|
|
1276
|
+
const dr = dst & 255, dg = dst >>> 8 & 255, db = dst >>> 16 & 255;
|
|
1277
|
+
const sr = src & 255, sg = src >>> 8 & 255, sb = src >>> 16 & 255;
|
|
1278
|
+
const br = dr > sr ? dr - sr : sr - dr;
|
|
1279
|
+
const bg = dg > sg ? dg - sg : sg - dg;
|
|
1280
|
+
const bb = db > sb ? db - sb : sb - db;
|
|
1281
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1171
1282
|
const invA = 255 - sa;
|
|
1172
1283
|
const da = dst >>> 24 & 255;
|
|
1173
|
-
const
|
|
1174
|
-
const
|
|
1175
|
-
const
|
|
1176
|
-
const
|
|
1284
|
+
const tR = br * sa + dr * invA;
|
|
1285
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1286
|
+
const tG = bg * sa + dg * invA;
|
|
1287
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1288
|
+
const tB = bb * sa + db * invA;
|
|
1289
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1290
|
+
const tA = 255 * sa + da * invA;
|
|
1291
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1177
1292
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1178
1293
|
};
|
|
1179
1294
|
var exclusionPerfect = (src, dst) => {
|
|
@@ -1185,18 +1300,23 @@ var exclusionPerfect = (src, dst) => {
|
|
|
1185
1300
|
const sr = src & 255;
|
|
1186
1301
|
const sg = src >>> 8 & 255;
|
|
1187
1302
|
const sb = src >>> 16 & 255;
|
|
1188
|
-
const
|
|
1189
|
-
const
|
|
1190
|
-
const
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1303
|
+
const r2 = dr * sr;
|
|
1304
|
+
const br = dr + sr - (r2 + r2 + 1 + (r2 + r2 >> 8) >> 8);
|
|
1305
|
+
const g2 = dg * sg;
|
|
1306
|
+
const bg = dg + sg - (g2 + g2 + 1 + (g2 + g2 >> 8) >> 8);
|
|
1307
|
+
const b2 = db * sb;
|
|
1308
|
+
const bb = db + sb - (b2 + b2 + 1 + (b2 + b2 >> 8) >> 8);
|
|
1309
|
+
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1194
1310
|
const invA = 255 - sa;
|
|
1195
1311
|
const da = dst >>> 24 & 255;
|
|
1196
|
-
const
|
|
1197
|
-
const
|
|
1198
|
-
const
|
|
1199
|
-
const
|
|
1312
|
+
const tR = br * sa + dr * invA;
|
|
1313
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1314
|
+
const tG = bg * sa + dg * invA;
|
|
1315
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1316
|
+
const tB = bb * sa + db * invA;
|
|
1317
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1318
|
+
const tA = 255 * sa + da * invA;
|
|
1319
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1200
1320
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1201
1321
|
};
|
|
1202
1322
|
var subtractPerfect = (src, dst) => {
|
|
@@ -1212,10 +1332,15 @@ var subtractPerfect = (src, dst) => {
|
|
|
1212
1332
|
const bb = bbU < 0 ? 0 : bbU;
|
|
1213
1333
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1214
1334
|
const invA = 255 - sa;
|
|
1215
|
-
const
|
|
1216
|
-
const
|
|
1217
|
-
const
|
|
1218
|
-
const
|
|
1335
|
+
const da = dst >>> 24 & 255;
|
|
1336
|
+
const tR = br * sa + dr * invA;
|
|
1337
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1338
|
+
const tG = bg * sa + dg * invA;
|
|
1339
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1340
|
+
const tB = bb * sa + db * invA;
|
|
1341
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1342
|
+
const tA = 255 * sa + da * invA;
|
|
1343
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1219
1344
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1220
1345
|
};
|
|
1221
1346
|
var dividePerfect = (src, dst) => {
|
|
@@ -1228,10 +1353,15 @@ var dividePerfect = (src, dst) => {
|
|
|
1228
1353
|
const bb = sb === 0 ? 255 : Math.min(255, db * 255 / sb | 0);
|
|
1229
1354
|
if (sa === 255) return (4278190080 | bb << 16 | bg << 8 | br) >>> 0;
|
|
1230
1355
|
const invA = 255 - sa;
|
|
1231
|
-
const
|
|
1232
|
-
const
|
|
1233
|
-
const
|
|
1234
|
-
const
|
|
1356
|
+
const da = dst >>> 24 & 255;
|
|
1357
|
+
const tR = br * sa + dr * invA;
|
|
1358
|
+
const r = tR + 1 + (tR >> 8) >> 8;
|
|
1359
|
+
const tG = bg * sa + dg * invA;
|
|
1360
|
+
const g = tG + 1 + (tG >> 8) >> 8;
|
|
1361
|
+
const tB = bb * sa + db * invA;
|
|
1362
|
+
const b = tB + 1 + (tB >> 8) >> 8;
|
|
1363
|
+
const tA = 255 * sa + da * invA;
|
|
1364
|
+
const a = tA + 1 + (tA >> 8) >> 8;
|
|
1235
1365
|
return (a << 24 | b << 16 | g << 8 | r) >>> 0;
|
|
1236
1366
|
};
|
|
1237
1367
|
var BASE_PERFECT_BLEND_MODE_FUNCTIONS = {
|
|
@@ -1376,279 +1506,1126 @@ async function writeImageDataToClipboard(imageData) {
|
|
|
1376
1506
|
return writeImgBlobToClipboard(blob);
|
|
1377
1507
|
}
|
|
1378
1508
|
|
|
1379
|
-
// src/
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1509
|
+
// src/History/PixelPatchTiles.ts
|
|
1510
|
+
var PixelTile = class {
|
|
1511
|
+
constructor(id, tx, ty, tileArea) {
|
|
1512
|
+
this.id = id;
|
|
1513
|
+
this.tx = tx;
|
|
1514
|
+
this.ty = ty;
|
|
1515
|
+
this.data32 = new Uint32Array(tileArea);
|
|
1516
|
+
}
|
|
1517
|
+
data32;
|
|
1518
|
+
};
|
|
1519
|
+
function applyPatchTiles(target, tiles, tileSize = 256) {
|
|
1520
|
+
for (let i = 0; i < tiles.length; i++) {
|
|
1521
|
+
const tile = tiles[i];
|
|
1522
|
+
if (!tile) continue;
|
|
1523
|
+
const dst = target.data32;
|
|
1524
|
+
const src = tile.data32;
|
|
1525
|
+
const dstWidth = target.width;
|
|
1526
|
+
const dstHeight = target.height;
|
|
1527
|
+
const startX = tile.tx * tileSize;
|
|
1528
|
+
const startY = tile.ty * tileSize;
|
|
1529
|
+
const copyWidth = Math.max(0, Math.min(tileSize, dstWidth - startX));
|
|
1530
|
+
if (copyWidth <= 0) return;
|
|
1531
|
+
for (let ly = 0; ly < tileSize; ly++) {
|
|
1532
|
+
const globalY = startY + ly;
|
|
1533
|
+
if (globalY >= dstHeight) break;
|
|
1534
|
+
const dstIndex = globalY * dstWidth + startX;
|
|
1535
|
+
const srcIndex = ly * tileSize;
|
|
1536
|
+
const rowData = src.subarray(srcIndex, srcIndex + copyWidth);
|
|
1537
|
+
dst.set(rowData, dstIndex);
|
|
1390
1538
|
}
|
|
1391
|
-
return imageData;
|
|
1392
|
-
};
|
|
1393
|
-
}
|
|
1394
|
-
|
|
1395
|
-
// src/ImageData/copyImageData.ts
|
|
1396
|
-
function copyImageData({ data, width, height }) {
|
|
1397
|
-
return new ImageData(data.slice(), width, height);
|
|
1398
|
-
}
|
|
1399
|
-
function copyImageDataLike({ data, width, height }) {
|
|
1400
|
-
return {
|
|
1401
|
-
data: data.slice(),
|
|
1402
|
-
width,
|
|
1403
|
-
height
|
|
1404
|
-
};
|
|
1405
|
-
}
|
|
1406
|
-
|
|
1407
|
-
// src/PixelData/pixelDataToAlphaMask.ts
|
|
1408
|
-
function pixelDataToAlphaMask(pixelData) {
|
|
1409
|
-
const {
|
|
1410
|
-
data32,
|
|
1411
|
-
width,
|
|
1412
|
-
height
|
|
1413
|
-
} = pixelData;
|
|
1414
|
-
const len = data32.length;
|
|
1415
|
-
const mask = new Uint8Array(width * height);
|
|
1416
|
-
for (let i = 0; i < len; i++) {
|
|
1417
|
-
const val = data32[i];
|
|
1418
|
-
mask[i] = val >>> 24 & 255;
|
|
1419
1539
|
}
|
|
1420
|
-
return mask;
|
|
1421
1540
|
}
|
|
1422
1541
|
|
|
1423
|
-
// src/
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1542
|
+
// src/History/PixelAccumulator.ts
|
|
1543
|
+
var PixelAccumulator = class {
|
|
1544
|
+
constructor(target, config) {
|
|
1545
|
+
this.target = target;
|
|
1546
|
+
this.config = config;
|
|
1547
|
+
this.lookup = [];
|
|
1548
|
+
this.beforeTiles = [];
|
|
1549
|
+
this.pool = [];
|
|
1550
|
+
}
|
|
1551
|
+
lookup;
|
|
1552
|
+
beforeTiles;
|
|
1553
|
+
pool;
|
|
1554
|
+
getTile(id, tx, ty) {
|
|
1555
|
+
let tile = this.pool.pop();
|
|
1556
|
+
if (tile) {
|
|
1557
|
+
tile.id = id;
|
|
1558
|
+
tile.tx = tx;
|
|
1559
|
+
tile.ty = ty;
|
|
1560
|
+
return tile;
|
|
1561
|
+
}
|
|
1562
|
+
return new PixelTile(
|
|
1563
|
+
id,
|
|
1564
|
+
tx,
|
|
1565
|
+
ty,
|
|
1566
|
+
this.config.tileArea
|
|
1567
|
+
);
|
|
1440
1568
|
}
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1569
|
+
recyclePatch(patch) {
|
|
1570
|
+
const before = patch.beforeTiles;
|
|
1571
|
+
for (let i = 0; i < before.length; i++) {
|
|
1572
|
+
let tile = before[i];
|
|
1573
|
+
if (tile) {
|
|
1574
|
+
this.pool.push(tile);
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
const after = patch.afterTiles;
|
|
1578
|
+
for (let i = 0; i < after.length; i++) {
|
|
1579
|
+
let tile = after[i];
|
|
1580
|
+
if (tile) {
|
|
1581
|
+
this.pool.push(tile);
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
/**
|
|
1586
|
+
* @param x pixel x coordinate
|
|
1587
|
+
* @param y pixel y coordinate
|
|
1588
|
+
*/
|
|
1589
|
+
storeTileBeforeState(x, y) {
|
|
1590
|
+
let target = this.target;
|
|
1591
|
+
let shift = this.config.tileShift;
|
|
1592
|
+
let columns = target.width + this.config.tileMask >> shift;
|
|
1593
|
+
let tx = x >> shift;
|
|
1594
|
+
let ty = y >> shift;
|
|
1595
|
+
let id = ty * columns + tx;
|
|
1596
|
+
let tile = this.lookup[id];
|
|
1597
|
+
if (!tile) {
|
|
1598
|
+
tile = this.getTile(
|
|
1599
|
+
id,
|
|
1600
|
+
tx,
|
|
1601
|
+
ty
|
|
1602
|
+
);
|
|
1603
|
+
this.extractState(tile);
|
|
1604
|
+
this.lookup[id] = tile;
|
|
1605
|
+
this.beforeTiles.push(tile);
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
/**
|
|
1609
|
+
*
|
|
1610
|
+
* @param x pixel x coordinate
|
|
1611
|
+
* @param y pixel y coordinate
|
|
1612
|
+
* @param w pixel width
|
|
1613
|
+
* @param h pixel height
|
|
1614
|
+
*/
|
|
1615
|
+
storeRegionBeforeState(x, y, w, h) {
|
|
1616
|
+
let target = this.target;
|
|
1617
|
+
let shift = this.config.tileShift;
|
|
1618
|
+
let columns = target.width + this.config.tileMask >> shift;
|
|
1619
|
+
let startX = x >> shift;
|
|
1620
|
+
let startY = y >> shift;
|
|
1621
|
+
let endX = x + w - 1 >> shift;
|
|
1622
|
+
let endY = y + h - 1 >> shift;
|
|
1623
|
+
for (let ty = startY; ty <= endY; ty++) {
|
|
1624
|
+
for (let tx = startX; tx <= endX; tx++) {
|
|
1625
|
+
let id = ty * columns + tx;
|
|
1626
|
+
let tile = this.lookup[id];
|
|
1627
|
+
if (!tile) {
|
|
1628
|
+
tile = this.getTile(
|
|
1629
|
+
id,
|
|
1630
|
+
tx,
|
|
1631
|
+
ty
|
|
1632
|
+
);
|
|
1633
|
+
this.extractState(tile);
|
|
1634
|
+
this.lookup[id] = tile;
|
|
1635
|
+
this.beforeTiles.push(tile);
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
extractState(tile) {
|
|
1641
|
+
let target = this.target;
|
|
1642
|
+
let TILE_SIZE = this.config.tileSize;
|
|
1643
|
+
let dst = tile.data32;
|
|
1644
|
+
let src = target.data32;
|
|
1645
|
+
let startX = tile.tx * TILE_SIZE;
|
|
1646
|
+
let startY = tile.ty * TILE_SIZE;
|
|
1647
|
+
let targetWidth = target.width;
|
|
1648
|
+
let targetHeight = target.height;
|
|
1649
|
+
let copyWidth = Math.max(0, Math.min(TILE_SIZE, targetWidth - startX));
|
|
1650
|
+
for (let ly = 0; ly < TILE_SIZE; ly++) {
|
|
1651
|
+
let globalY = startY + ly;
|
|
1652
|
+
let dstIndex = ly * TILE_SIZE;
|
|
1653
|
+
if (globalY < 0 || globalY >= targetHeight || copyWidth === 0) {
|
|
1654
|
+
dst.fill(0, dstIndex, dstIndex + TILE_SIZE);
|
|
1655
|
+
continue;
|
|
1656
|
+
}
|
|
1657
|
+
let srcIndex = globalY * targetWidth + startX;
|
|
1658
|
+
let rowData = src.subarray(srcIndex, srcIndex + copyWidth);
|
|
1659
|
+
dst.set(rowData, dstIndex);
|
|
1660
|
+
if (copyWidth < TILE_SIZE) {
|
|
1661
|
+
dst.fill(0, dstIndex + copyWidth, dstIndex + TILE_SIZE);
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
extractAfterTiles() {
|
|
1666
|
+
let afterTiles = [];
|
|
1667
|
+
let length = this.beforeTiles.length;
|
|
1668
|
+
for (let i = 0; i < length; i++) {
|
|
1669
|
+
let beforeTile = this.beforeTiles[i];
|
|
1670
|
+
if (beforeTile) {
|
|
1671
|
+
let afterTile = this.getTile(
|
|
1672
|
+
beforeTile.id,
|
|
1673
|
+
beforeTile.tx,
|
|
1674
|
+
beforeTile.ty
|
|
1675
|
+
);
|
|
1676
|
+
this.extractState(afterTile);
|
|
1677
|
+
afterTiles.push(afterTile);
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
return afterTiles;
|
|
1681
|
+
}
|
|
1682
|
+
reset() {
|
|
1683
|
+
this.lookup = [];
|
|
1684
|
+
this.beforeTiles = [];
|
|
1471
1685
|
}
|
|
1472
|
-
return imageData;
|
|
1473
|
-
}
|
|
1474
|
-
|
|
1475
|
-
// src/Internal/resample32.ts
|
|
1476
|
-
var resample32Scratch = {
|
|
1477
|
-
data: null,
|
|
1478
|
-
width: 0,
|
|
1479
|
-
height: 0
|
|
1480
1686
|
};
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1687
|
+
|
|
1688
|
+
// src/History/HistoryManager.ts
|
|
1689
|
+
var HistoryManager = class {
|
|
1690
|
+
constructor(maxSteps = 50) {
|
|
1691
|
+
this.maxSteps = maxSteps;
|
|
1692
|
+
this.undoStack = [];
|
|
1693
|
+
this.redoStack = [];
|
|
1694
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
1695
|
+
}
|
|
1696
|
+
undoStack;
|
|
1697
|
+
redoStack;
|
|
1698
|
+
listeners;
|
|
1699
|
+
get canUndo() {
|
|
1700
|
+
return this.undoStack.length > 0;
|
|
1701
|
+
}
|
|
1702
|
+
get canRedo() {
|
|
1703
|
+
return this.redoStack.length > 0;
|
|
1704
|
+
}
|
|
1705
|
+
subscribe(fn) {
|
|
1706
|
+
this.listeners.add(fn);
|
|
1707
|
+
return () => this.listeners.delete(fn);
|
|
1708
|
+
}
|
|
1709
|
+
notify() {
|
|
1710
|
+
this.listeners.forEach((fn) => fn());
|
|
1711
|
+
}
|
|
1712
|
+
commit(action) {
|
|
1713
|
+
this.undoStack.push(action);
|
|
1714
|
+
this.clearRedoStack();
|
|
1715
|
+
if (this.undoStack.length > this.maxSteps) {
|
|
1716
|
+
this.undoStack.shift()?.dispose?.();
|
|
1717
|
+
}
|
|
1718
|
+
this.notify();
|
|
1719
|
+
}
|
|
1720
|
+
undo() {
|
|
1721
|
+
let action = this.undoStack.pop();
|
|
1722
|
+
if (!action) return;
|
|
1723
|
+
this.redoStack.push(action);
|
|
1724
|
+
action.undo();
|
|
1725
|
+
this.notify();
|
|
1726
|
+
}
|
|
1727
|
+
redo() {
|
|
1728
|
+
let action = this.redoStack.pop();
|
|
1729
|
+
if (!action) return;
|
|
1730
|
+
this.undoStack.push(action);
|
|
1731
|
+
action.redo();
|
|
1732
|
+
this.notify();
|
|
1733
|
+
}
|
|
1734
|
+
clearRedoStack() {
|
|
1735
|
+
let length = this.redoStack.length;
|
|
1736
|
+
for (let i = 0; i < length; i++) {
|
|
1737
|
+
let action = this.redoStack[i];
|
|
1738
|
+
if (action) {
|
|
1739
|
+
action.dispose?.();
|
|
1740
|
+
}
|
|
1494
1741
|
}
|
|
1742
|
+
this.redoStack.length = 0;
|
|
1495
1743
|
}
|
|
1496
|
-
|
|
1497
|
-
resample32Scratch.width = dstW;
|
|
1498
|
-
resample32Scratch.height = dstH;
|
|
1499
|
-
return resample32Scratch;
|
|
1500
|
-
}
|
|
1744
|
+
};
|
|
1501
1745
|
|
|
1502
|
-
// src/
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1746
|
+
// src/History/PixelEngineConfig.ts
|
|
1747
|
+
var PixelEngineConfig = class {
|
|
1748
|
+
tileSize;
|
|
1749
|
+
tileShift;
|
|
1750
|
+
tileMask;
|
|
1751
|
+
tileArea;
|
|
1752
|
+
constructor(tileSize = 256) {
|
|
1753
|
+
if ((tileSize & tileSize - 1) !== 0) {
|
|
1754
|
+
throw new Error("tileSize must be a power of 2");
|
|
1755
|
+
}
|
|
1756
|
+
this.tileSize = tileSize;
|
|
1757
|
+
this.tileShift = Math.log2(tileSize);
|
|
1758
|
+
this.tileMask = tileSize - 1;
|
|
1759
|
+
this.tileArea = tileSize * tileSize;
|
|
1760
|
+
}
|
|
1761
|
+
};
|
|
1509
1762
|
|
|
1510
|
-
// src/
|
|
1511
|
-
function
|
|
1512
|
-
const result = new ImageData(newWidth, newHeight);
|
|
1763
|
+
// src/PixelData/applyMaskToPixelData.ts
|
|
1764
|
+
function applyMaskToPixelData(dst, mask, opts = {}) {
|
|
1513
1765
|
const {
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1766
|
+
x: targetX = 0,
|
|
1767
|
+
y: targetY = 0,
|
|
1768
|
+
w: width = dst.width,
|
|
1769
|
+
h: height = dst.height,
|
|
1770
|
+
alpha: globalAlpha = 255,
|
|
1771
|
+
maskType = 0 /* ALPHA */,
|
|
1772
|
+
mw,
|
|
1773
|
+
mx = 0,
|
|
1774
|
+
my = 0,
|
|
1775
|
+
invertMask = false
|
|
1776
|
+
} = opts;
|
|
1777
|
+
let x = targetX;
|
|
1778
|
+
let y = targetY;
|
|
1779
|
+
let w = width;
|
|
1780
|
+
let h = height;
|
|
1781
|
+
if (x < 0) {
|
|
1782
|
+
w += x;
|
|
1783
|
+
x = 0;
|
|
1525
1784
|
}
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1785
|
+
if (y < 0) {
|
|
1786
|
+
h += y;
|
|
1787
|
+
y = 0;
|
|
1788
|
+
}
|
|
1789
|
+
const actualW = Math.min(w, dst.width - x);
|
|
1790
|
+
const actualH = Math.min(h, dst.height - y);
|
|
1791
|
+
if (actualW <= 0 || actualH <= 0 || globalAlpha === 0) {
|
|
1792
|
+
return;
|
|
1793
|
+
}
|
|
1794
|
+
const dst32 = dst.data32;
|
|
1795
|
+
const dw = dst.width;
|
|
1796
|
+
const mPitch = mw ?? width;
|
|
1797
|
+
const isAlpha = maskType === 0 /* ALPHA */;
|
|
1798
|
+
const dx = x - targetX;
|
|
1799
|
+
const dy = y - targetY;
|
|
1800
|
+
let dIdx = y * dw + x;
|
|
1801
|
+
let mIdx = (my + dy) * mPitch + (mx + dx);
|
|
1802
|
+
const dStride = dw - actualW;
|
|
1803
|
+
const mStride = mPitch - actualW;
|
|
1804
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
1805
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
1806
|
+
const mVal = mask[mIdx];
|
|
1807
|
+
let weight = globalAlpha;
|
|
1808
|
+
if (isAlpha) {
|
|
1809
|
+
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
1810
|
+
if (effectiveM === 0) {
|
|
1811
|
+
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
1812
|
+
dIdx++;
|
|
1813
|
+
mIdx++;
|
|
1814
|
+
continue;
|
|
1815
|
+
}
|
|
1816
|
+
weight = globalAlpha === 255 ? effectiveM : effectiveM * globalAlpha + 128 >> 8;
|
|
1817
|
+
} else {
|
|
1818
|
+
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
1819
|
+
if (!isHit) {
|
|
1820
|
+
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
1821
|
+
dIdx++;
|
|
1822
|
+
mIdx++;
|
|
1823
|
+
continue;
|
|
1824
|
+
}
|
|
1825
|
+
weight = globalAlpha;
|
|
1826
|
+
}
|
|
1827
|
+
if (weight === 0) {
|
|
1828
|
+
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
1829
|
+
} else {
|
|
1830
|
+
const d = dst32[dIdx];
|
|
1831
|
+
const da = d >>> 24;
|
|
1832
|
+
let finalAlpha = da;
|
|
1833
|
+
if (da === 0) {
|
|
1834
|
+
} else if (weight === 255) {
|
|
1835
|
+
} else if (da === 255) {
|
|
1836
|
+
finalAlpha = weight;
|
|
1837
|
+
} else {
|
|
1838
|
+
finalAlpha = da * weight + 128 >> 8;
|
|
1839
|
+
}
|
|
1840
|
+
dst32[dIdx] = (d & 16777215 | finalAlpha << 24) >>> 0;
|
|
1841
|
+
}
|
|
1842
|
+
dIdx++;
|
|
1843
|
+
mIdx++;
|
|
1844
|
+
}
|
|
1845
|
+
dIdx += dStride;
|
|
1846
|
+
mIdx += mStride;
|
|
1538
1847
|
}
|
|
1539
|
-
return result;
|
|
1540
1848
|
}
|
|
1541
1849
|
|
|
1542
|
-
// src/
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1850
|
+
// src/History/PixelWriter.ts
|
|
1851
|
+
var PixelWriter = class {
|
|
1852
|
+
target;
|
|
1853
|
+
historyManager;
|
|
1854
|
+
accumulator;
|
|
1855
|
+
config;
|
|
1856
|
+
mutator;
|
|
1857
|
+
constructor(target, mutatorFactory, {
|
|
1858
|
+
tileSize = 256,
|
|
1859
|
+
maxHistorySteps = 50,
|
|
1860
|
+
historyManager = new HistoryManager(maxHistorySteps)
|
|
1861
|
+
} = {}) {
|
|
1862
|
+
this.target = target;
|
|
1863
|
+
this.config = new PixelEngineConfig(tileSize);
|
|
1864
|
+
this.historyManager = historyManager;
|
|
1865
|
+
this.accumulator = new PixelAccumulator(target, this.config);
|
|
1866
|
+
this.mutator = mutatorFactory(this);
|
|
1867
|
+
}
|
|
1868
|
+
withHistory(cb) {
|
|
1869
|
+
cb(this.mutator);
|
|
1870
|
+
const beforeTiles = this.accumulator.beforeTiles;
|
|
1871
|
+
if (beforeTiles.length === 0) return;
|
|
1872
|
+
const afterTiles = this.accumulator.extractAfterTiles();
|
|
1873
|
+
const patch = {
|
|
1874
|
+
beforeTiles,
|
|
1875
|
+
afterTiles
|
|
1876
|
+
};
|
|
1877
|
+
const target = this.target;
|
|
1878
|
+
const tileSize = this.config.tileSize;
|
|
1879
|
+
const accumulator = this.accumulator;
|
|
1880
|
+
const action = {
|
|
1881
|
+
undo: () => applyPatchTiles(target, patch.beforeTiles, tileSize),
|
|
1882
|
+
redo: () => applyPatchTiles(target, patch.afterTiles, tileSize),
|
|
1883
|
+
dispose: () => accumulator.recyclePatch(patch)
|
|
1884
|
+
};
|
|
1885
|
+
this.historyManager.commit(action);
|
|
1886
|
+
this.accumulator.reset();
|
|
1554
1887
|
}
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
width: imageData.width,
|
|
1560
|
-
height: imageData.height,
|
|
1561
|
-
data: base64EncodeArrayBuffer(imageData.data.buffer)
|
|
1562
|
-
};
|
|
1563
|
-
}
|
|
1564
|
-
function serializeNullableImageData(imageData) {
|
|
1565
|
-
if (!imageData) return null;
|
|
1566
|
-
return serializeImageData(imageData);
|
|
1567
|
-
}
|
|
1568
|
-
function deserializeRawImageData(serialized) {
|
|
1888
|
+
};
|
|
1889
|
+
|
|
1890
|
+
// src/History/PixelMutator/mutatorApplyMask.ts
|
|
1891
|
+
function mutatorApplyMask(writer) {
|
|
1569
1892
|
return {
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1893
|
+
applyMask: (mask, opts = {}) => {
|
|
1894
|
+
let target = writer.target;
|
|
1895
|
+
const {
|
|
1896
|
+
x = 0,
|
|
1897
|
+
y = 0,
|
|
1898
|
+
w = writer.target.width,
|
|
1899
|
+
h = writer.target.height
|
|
1900
|
+
} = opts;
|
|
1901
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
1902
|
+
applyMaskToPixelData(target, mask, opts);
|
|
1903
|
+
}
|
|
1573
1904
|
};
|
|
1574
1905
|
}
|
|
1575
|
-
function deserializeImageData(serialized) {
|
|
1576
|
-
const data = base64DecodeArrayBuffer(serialized.data);
|
|
1577
|
-
return new ImageData(data, serialized.width, serialized.height);
|
|
1578
|
-
}
|
|
1579
|
-
function deserializeNullableImageData(serialized) {
|
|
1580
|
-
if (!serialized) return null;
|
|
1581
|
-
return deserializeImageData(serialized);
|
|
1582
|
-
}
|
|
1583
1906
|
|
|
1584
|
-
// src/
|
|
1585
|
-
function
|
|
1586
|
-
const
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1907
|
+
// src/PixelData/blendColorPixelData.ts
|
|
1908
|
+
function blendColorPixelData(dst, color, opts = {}) {
|
|
1909
|
+
const {
|
|
1910
|
+
x: targetX = 0,
|
|
1911
|
+
y: targetY = 0,
|
|
1912
|
+
w: width = dst.width,
|
|
1913
|
+
h: height = dst.height,
|
|
1914
|
+
alpha: globalAlpha = 255,
|
|
1915
|
+
blendFn = sourceOverFast,
|
|
1916
|
+
mask,
|
|
1917
|
+
maskType = 0 /* ALPHA */,
|
|
1918
|
+
mw,
|
|
1919
|
+
mx = 0,
|
|
1920
|
+
my = 0,
|
|
1921
|
+
invertMask = false
|
|
1922
|
+
} = opts;
|
|
1923
|
+
if (globalAlpha === 0) return;
|
|
1924
|
+
const baseSrcAlpha = color >>> 24;
|
|
1925
|
+
const isOverwrite = blendFn.isOverwrite;
|
|
1926
|
+
if (baseSrcAlpha === 0 && !isOverwrite) return;
|
|
1927
|
+
let x = targetX;
|
|
1928
|
+
let y = targetY;
|
|
1929
|
+
let w = width;
|
|
1930
|
+
let h = height;
|
|
1931
|
+
if (x < 0) {
|
|
1932
|
+
w += x;
|
|
1933
|
+
x = 0;
|
|
1597
1934
|
}
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1935
|
+
if (y < 0) {
|
|
1936
|
+
h += y;
|
|
1937
|
+
y = 0;
|
|
1938
|
+
}
|
|
1939
|
+
const actualW = Math.min(w, dst.width - x);
|
|
1940
|
+
const actualH = Math.min(h, dst.height - y);
|
|
1941
|
+
if (actualW <= 0 || actualH <= 0) return;
|
|
1942
|
+
const dst32 = dst.data32;
|
|
1943
|
+
const dw = dst.width;
|
|
1944
|
+
const mPitch = mw ?? width;
|
|
1945
|
+
const isAlphaMask = maskType === 0 /* ALPHA */;
|
|
1946
|
+
const dx = x - targetX;
|
|
1947
|
+
const dy = y - targetY;
|
|
1948
|
+
let dIdx = y * dw + x;
|
|
1949
|
+
let mIdx = (my + dy) * mPitch + (mx + dx);
|
|
1950
|
+
const dStride = dw - actualW;
|
|
1951
|
+
const mStride = mPitch - actualW;
|
|
1952
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
1953
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
1954
|
+
let weight = globalAlpha;
|
|
1955
|
+
if (mask) {
|
|
1956
|
+
const mVal = mask[mIdx];
|
|
1957
|
+
if (isAlphaMask) {
|
|
1958
|
+
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
1959
|
+
if (effectiveM === 0) {
|
|
1960
|
+
dIdx++;
|
|
1961
|
+
mIdx++;
|
|
1962
|
+
continue;
|
|
1963
|
+
}
|
|
1964
|
+
if (globalAlpha === 255) {
|
|
1965
|
+
weight = effectiveM;
|
|
1966
|
+
} else if (effectiveM === 255) {
|
|
1967
|
+
weight = globalAlpha;
|
|
1968
|
+
} else {
|
|
1969
|
+
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
1970
|
+
}
|
|
1971
|
+
} else {
|
|
1972
|
+
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
1973
|
+
if (!isHit) {
|
|
1974
|
+
dIdx++;
|
|
1975
|
+
mIdx++;
|
|
1976
|
+
continue;
|
|
1977
|
+
}
|
|
1978
|
+
weight = globalAlpha;
|
|
1979
|
+
}
|
|
1980
|
+
if (weight === 0) {
|
|
1981
|
+
dIdx++;
|
|
1982
|
+
mIdx++;
|
|
1612
1983
|
continue;
|
|
1613
1984
|
}
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
dstData[di + 3] = srcData[si + 3];
|
|
1985
|
+
}
|
|
1986
|
+
let currentSrcColor = color;
|
|
1987
|
+
if (weight < 255) {
|
|
1988
|
+
let currentSrcAlpha = baseSrcAlpha;
|
|
1989
|
+
if (baseSrcAlpha === 255) {
|
|
1990
|
+
currentSrcAlpha = weight;
|
|
1621
1991
|
} else {
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1992
|
+
currentSrcAlpha = baseSrcAlpha * weight + 128 >> 8;
|
|
1993
|
+
}
|
|
1994
|
+
if (!isOverwrite && currentSrcAlpha === 0) {
|
|
1995
|
+
dIdx++;
|
|
1996
|
+
mIdx++;
|
|
1997
|
+
continue;
|
|
1628
1998
|
}
|
|
1999
|
+
currentSrcColor = (color & 16777215 | currentSrcAlpha << 24) >>> 0;
|
|
1629
2000
|
}
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
dstData.set(sub, dstStart);
|
|
2001
|
+
dst32[dIdx] = blendFn(currentSrcColor, dst32[dIdx]);
|
|
2002
|
+
dIdx++;
|
|
2003
|
+
mIdx++;
|
|
1634
2004
|
}
|
|
2005
|
+
dIdx += dStride;
|
|
2006
|
+
mIdx += mStride;
|
|
1635
2007
|
}
|
|
1636
2008
|
}
|
|
1637
2009
|
|
|
1638
|
-
// src/
|
|
1639
|
-
function
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
2010
|
+
// src/History/PixelMutator/mutatorBlendColor.ts
|
|
2011
|
+
function mutatorBlendColor(writer) {
|
|
2012
|
+
return {
|
|
2013
|
+
blendColor(color, opts = {}) {
|
|
2014
|
+
const {
|
|
2015
|
+
x = 0,
|
|
2016
|
+
y = 0,
|
|
2017
|
+
w = writer.target.width,
|
|
2018
|
+
h = writer.target.height
|
|
2019
|
+
} = opts;
|
|
2020
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2021
|
+
blendColorPixelData(writer.target, color, opts);
|
|
2022
|
+
}
|
|
2023
|
+
};
|
|
2024
|
+
}
|
|
2025
|
+
|
|
2026
|
+
// src/History/PixelMutator/mutatorBlendPixel.ts
|
|
2027
|
+
function mutatorBlendPixel(writer) {
|
|
2028
|
+
return {
|
|
2029
|
+
blendPixel(x, y, color, alpha = 255, blendFn = overwriteFast) {
|
|
2030
|
+
let target = writer.target;
|
|
2031
|
+
let width = target.width;
|
|
2032
|
+
let height = target.height;
|
|
2033
|
+
if (x < 0 || x >= width || y < 0 || y >= height) return;
|
|
2034
|
+
writer.accumulator.storeTileBeforeState(x, y);
|
|
2035
|
+
let index = y * width + x;
|
|
2036
|
+
let bg = target.data32[index];
|
|
2037
|
+
let finalColor = color;
|
|
2038
|
+
if (alpha < 255) {
|
|
2039
|
+
let baseSrcAlpha = color >>> 24;
|
|
2040
|
+
let finalAlpha = baseSrcAlpha * alpha + 128 >> 8;
|
|
2041
|
+
finalColor = (color & 16777215 | finalAlpha << 24) >>> 0;
|
|
2042
|
+
}
|
|
2043
|
+
target.data32[index] = blendFn(finalColor, bg);
|
|
2044
|
+
}
|
|
2045
|
+
};
|
|
2046
|
+
}
|
|
2047
|
+
|
|
2048
|
+
// src/PixelData/blendPixelData.ts
|
|
2049
|
+
function blendPixelData(dst, src, opts) {
|
|
2050
|
+
const {
|
|
2051
|
+
x: targetX = 0,
|
|
2052
|
+
y: targetY = 0,
|
|
2053
|
+
sx: sourceX = 0,
|
|
2054
|
+
sy: sourceY = 0,
|
|
2055
|
+
w: width = src.width,
|
|
2056
|
+
h: height = src.height,
|
|
2057
|
+
alpha: globalAlpha = 255,
|
|
2058
|
+
blendFn = sourceOverFast,
|
|
2059
|
+
mask,
|
|
2060
|
+
maskType = 0 /* ALPHA */,
|
|
2061
|
+
mw,
|
|
2062
|
+
mx = 0,
|
|
2063
|
+
my = 0,
|
|
2064
|
+
invertMask = false
|
|
2065
|
+
} = opts;
|
|
2066
|
+
if (globalAlpha === 0) return;
|
|
2067
|
+
let x = targetX;
|
|
2068
|
+
let y = targetY;
|
|
2069
|
+
let sx = sourceX;
|
|
2070
|
+
let sy = sourceY;
|
|
2071
|
+
let w = width;
|
|
2072
|
+
let h = height;
|
|
2073
|
+
if (sx < 0) {
|
|
2074
|
+
x -= sx;
|
|
2075
|
+
w += sx;
|
|
2076
|
+
sx = 0;
|
|
2077
|
+
}
|
|
2078
|
+
if (sy < 0) {
|
|
2079
|
+
y -= sy;
|
|
2080
|
+
h += sy;
|
|
2081
|
+
sy = 0;
|
|
2082
|
+
}
|
|
2083
|
+
w = Math.min(w, src.width - sx);
|
|
2084
|
+
h = Math.min(h, src.height - sy);
|
|
2085
|
+
if (x < 0) {
|
|
2086
|
+
sx -= x;
|
|
2087
|
+
w += x;
|
|
2088
|
+
x = 0;
|
|
2089
|
+
}
|
|
2090
|
+
if (y < 0) {
|
|
2091
|
+
sy -= y;
|
|
2092
|
+
h += y;
|
|
2093
|
+
y = 0;
|
|
2094
|
+
}
|
|
2095
|
+
const actualW = Math.min(w, dst.width - x);
|
|
2096
|
+
const actualH = Math.min(h, dst.height - y);
|
|
2097
|
+
if (actualW <= 0 || actualH <= 0) return;
|
|
2098
|
+
const dst32 = dst.data32;
|
|
2099
|
+
const src32 = src.data32;
|
|
2100
|
+
const dw = dst.width;
|
|
2101
|
+
const sw = src.width;
|
|
2102
|
+
const mPitch = mw ?? width;
|
|
2103
|
+
const isAlphaMask = maskType === 0 /* ALPHA */;
|
|
2104
|
+
const dx = x - targetX;
|
|
2105
|
+
const dy = y - targetY;
|
|
2106
|
+
let dIdx = y * dw + x;
|
|
2107
|
+
let sIdx = sy * sw + sx;
|
|
2108
|
+
let mIdx = (my + dy) * mPitch + (mx + dx);
|
|
2109
|
+
const dStride = dw - actualW;
|
|
2110
|
+
const sStride = sw - actualW;
|
|
2111
|
+
const mStride = mPitch - actualW;
|
|
2112
|
+
const isOverwrite = blendFn.isOverwrite;
|
|
2113
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2114
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
2115
|
+
const baseSrcColor = src32[sIdx];
|
|
2116
|
+
const baseSrcAlpha = baseSrcColor >>> 24;
|
|
2117
|
+
if (baseSrcAlpha === 0 && !isOverwrite) {
|
|
2118
|
+
dIdx++;
|
|
2119
|
+
sIdx++;
|
|
2120
|
+
mIdx++;
|
|
2121
|
+
continue;
|
|
2122
|
+
}
|
|
2123
|
+
let weight = globalAlpha;
|
|
2124
|
+
if (mask) {
|
|
2125
|
+
const mVal = mask[mIdx];
|
|
2126
|
+
if (isAlphaMask) {
|
|
2127
|
+
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
2128
|
+
if (effectiveM === 0) {
|
|
2129
|
+
dIdx++;
|
|
2130
|
+
sIdx++;
|
|
2131
|
+
mIdx++;
|
|
2132
|
+
continue;
|
|
2133
|
+
}
|
|
2134
|
+
if (globalAlpha === 255) {
|
|
2135
|
+
weight = effectiveM;
|
|
2136
|
+
} else if (effectiveM === 255) {
|
|
2137
|
+
weight = globalAlpha;
|
|
2138
|
+
} else {
|
|
2139
|
+
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
2140
|
+
}
|
|
2141
|
+
} else {
|
|
2142
|
+
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
2143
|
+
if (!isHit) {
|
|
2144
|
+
dIdx++;
|
|
2145
|
+
sIdx++;
|
|
2146
|
+
mIdx++;
|
|
2147
|
+
continue;
|
|
2148
|
+
}
|
|
2149
|
+
weight = globalAlpha;
|
|
2150
|
+
}
|
|
2151
|
+
if (weight === 0) {
|
|
2152
|
+
dIdx++;
|
|
2153
|
+
sIdx++;
|
|
2154
|
+
mIdx++;
|
|
2155
|
+
continue;
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
let currentSrcColor = baseSrcColor;
|
|
2159
|
+
if (weight < 255) {
|
|
2160
|
+
let currentSrcAlpha = baseSrcAlpha;
|
|
2161
|
+
if (baseSrcAlpha === 255) {
|
|
2162
|
+
currentSrcAlpha = weight;
|
|
2163
|
+
} else {
|
|
2164
|
+
currentSrcAlpha = baseSrcAlpha * weight + 128 >> 8;
|
|
2165
|
+
}
|
|
2166
|
+
if (!isOverwrite && currentSrcAlpha === 0) {
|
|
2167
|
+
dIdx++;
|
|
2168
|
+
sIdx++;
|
|
2169
|
+
mIdx++;
|
|
2170
|
+
continue;
|
|
2171
|
+
}
|
|
2172
|
+
currentSrcColor = (baseSrcColor & 16777215 | currentSrcAlpha << 24) >>> 0;
|
|
2173
|
+
}
|
|
2174
|
+
dst32[dIdx] = blendFn(currentSrcColor, dst32[dIdx]);
|
|
2175
|
+
dIdx++;
|
|
2176
|
+
sIdx++;
|
|
2177
|
+
mIdx++;
|
|
2178
|
+
}
|
|
2179
|
+
dIdx += dStride;
|
|
2180
|
+
sIdx += sStride;
|
|
2181
|
+
mIdx += mStride;
|
|
2182
|
+
}
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
// src/History/PixelMutator/mutatorBlendPixelData.ts
|
|
2186
|
+
function mutatorBlendPixelData(writer) {
|
|
2187
|
+
return {
|
|
2188
|
+
blendPixelData(src, opts) {
|
|
2189
|
+
const {
|
|
2190
|
+
x = 0,
|
|
2191
|
+
y = 0,
|
|
2192
|
+
w = src.width,
|
|
2193
|
+
h = src.height
|
|
2194
|
+
} = opts;
|
|
2195
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2196
|
+
blendPixelData(writer.target, src, opts);
|
|
2197
|
+
}
|
|
2198
|
+
};
|
|
2199
|
+
}
|
|
2200
|
+
|
|
2201
|
+
// src/PixelData/fillPixelData.ts
|
|
2202
|
+
function fillPixelData(dst, color, _x, _y, _w, _h) {
|
|
2203
|
+
let x;
|
|
2204
|
+
let y;
|
|
2205
|
+
let w;
|
|
2206
|
+
let h;
|
|
2207
|
+
if (typeof _x === "object") {
|
|
2208
|
+
x = _x.x ?? 0;
|
|
2209
|
+
y = _x.y ?? 0;
|
|
2210
|
+
w = _x.w ?? dst.width;
|
|
2211
|
+
h = _x.h ?? dst.height;
|
|
2212
|
+
} else if (typeof _x === "number") {
|
|
2213
|
+
x = _x;
|
|
2214
|
+
y = _y;
|
|
2215
|
+
w = _w;
|
|
2216
|
+
h = _h;
|
|
2217
|
+
} else {
|
|
2218
|
+
x = 0;
|
|
2219
|
+
y = 0;
|
|
2220
|
+
w = dst.width;
|
|
2221
|
+
h = dst.height;
|
|
2222
|
+
}
|
|
2223
|
+
if (x < 0) {
|
|
2224
|
+
w += x;
|
|
2225
|
+
x = 0;
|
|
2226
|
+
}
|
|
2227
|
+
if (y < 0) {
|
|
2228
|
+
h += y;
|
|
2229
|
+
y = 0;
|
|
2230
|
+
}
|
|
2231
|
+
const actualW = Math.min(w, dst.width - x);
|
|
2232
|
+
const actualH = Math.min(h, dst.height - y);
|
|
2233
|
+
if (actualW <= 0 || actualH <= 0) {
|
|
2234
|
+
return;
|
|
2235
|
+
}
|
|
2236
|
+
const dst32 = dst.data32;
|
|
2237
|
+
const dw = dst.width;
|
|
2238
|
+
if (actualW === dw && actualH === dst.height && x === 0 && y === 0) {
|
|
2239
|
+
dst32.fill(color);
|
|
2240
|
+
return;
|
|
2241
|
+
}
|
|
2242
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2243
|
+
const start = (y + iy) * dw + x;
|
|
2244
|
+
const end = start + actualW;
|
|
2245
|
+
dst32.fill(color, start, end);
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
|
|
2249
|
+
// src/History/PixelMutator/mutatorFillPixelData.ts
|
|
2250
|
+
function mutatorFill(writer) {
|
|
2251
|
+
return {
|
|
2252
|
+
fill(color, rect = {}) {
|
|
2253
|
+
const {
|
|
2254
|
+
x = 0,
|
|
2255
|
+
y = 0,
|
|
2256
|
+
w = writer.target.width,
|
|
2257
|
+
h = writer.target.height
|
|
2258
|
+
} = rect;
|
|
2259
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2260
|
+
fillPixelData(writer.target, color, x, y, w, h);
|
|
2261
|
+
}
|
|
2262
|
+
};
|
|
2263
|
+
}
|
|
2264
|
+
|
|
2265
|
+
// src/PixelData/invertPixelData.ts
|
|
2266
|
+
function invertPixelData(pixelData, opts = {}) {
|
|
2267
|
+
const dst = pixelData;
|
|
2268
|
+
const {
|
|
2269
|
+
x: targetX = 0,
|
|
2270
|
+
y: targetY = 0,
|
|
2271
|
+
w: width = pixelData.width,
|
|
2272
|
+
h: height = pixelData.height,
|
|
2273
|
+
mask,
|
|
2274
|
+
mw,
|
|
2275
|
+
mx = 0,
|
|
2276
|
+
my = 0,
|
|
2277
|
+
invertMask = false
|
|
2278
|
+
} = opts;
|
|
2279
|
+
let x = targetX;
|
|
2280
|
+
let y = targetY;
|
|
2281
|
+
let w = width;
|
|
2282
|
+
let h = height;
|
|
2283
|
+
if (x < 0) {
|
|
2284
|
+
w += x;
|
|
2285
|
+
x = 0;
|
|
2286
|
+
}
|
|
2287
|
+
if (y < 0) {
|
|
2288
|
+
h += y;
|
|
2289
|
+
y = 0;
|
|
2290
|
+
}
|
|
2291
|
+
const actualW = Math.min(w, dst.width - x);
|
|
2292
|
+
const actualH = Math.min(h, dst.height - y);
|
|
2293
|
+
if (actualW <= 0 || actualH <= 0) return;
|
|
2294
|
+
const dst32 = dst.data32;
|
|
2295
|
+
const dw = dst.width;
|
|
2296
|
+
const mPitch = mw ?? width;
|
|
2297
|
+
const dx = x - targetX;
|
|
2298
|
+
const dy = y - targetY;
|
|
2299
|
+
let dIdx = y * dw + x;
|
|
2300
|
+
let mIdx = (my + dy) * mPitch + (mx + dx);
|
|
2301
|
+
const dStride = dw - actualW;
|
|
2302
|
+
const mStride = mPitch - actualW;
|
|
2303
|
+
if (mask) {
|
|
2304
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2305
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
2306
|
+
const mVal = mask[mIdx];
|
|
2307
|
+
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
2308
|
+
if (isHit) {
|
|
2309
|
+
dst32[dIdx] = dst32[dIdx] ^ 16777215;
|
|
2310
|
+
}
|
|
2311
|
+
dIdx++;
|
|
2312
|
+
mIdx++;
|
|
2313
|
+
}
|
|
2314
|
+
dIdx += dStride;
|
|
2315
|
+
mIdx += mStride;
|
|
2316
|
+
}
|
|
2317
|
+
} else {
|
|
2318
|
+
for (let iy = 0; iy < actualH; iy++) {
|
|
2319
|
+
for (let ix = 0; ix < actualW; ix++) {
|
|
2320
|
+
dst32[dIdx] = dst32[dIdx] ^ 16777215;
|
|
2321
|
+
dIdx++;
|
|
2322
|
+
}
|
|
2323
|
+
dIdx += dStride;
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2326
|
+
}
|
|
2327
|
+
|
|
2328
|
+
// src/History/PixelMutator/mutatorInvert.ts
|
|
2329
|
+
function mutatorInvert(writer) {
|
|
2330
|
+
return {
|
|
2331
|
+
invert(opts = {}) {
|
|
2332
|
+
const {
|
|
2333
|
+
x = 0,
|
|
2334
|
+
y = 0,
|
|
2335
|
+
w = writer.target.width,
|
|
2336
|
+
h = writer.target.height
|
|
2337
|
+
} = opts;
|
|
2338
|
+
writer.accumulator.storeRegionBeforeState(x, y, w, h);
|
|
2339
|
+
invertPixelData(writer.target, opts);
|
|
2340
|
+
}
|
|
2341
|
+
};
|
|
2342
|
+
}
|
|
2343
|
+
|
|
2344
|
+
// src/History/PixelMutator.ts
|
|
2345
|
+
function makeFullPixelMutator(writer) {
|
|
2346
|
+
return {
|
|
2347
|
+
...mutatorApplyMask(writer),
|
|
2348
|
+
...mutatorBlendPixelData(writer),
|
|
2349
|
+
...mutatorBlendColor(writer),
|
|
2350
|
+
...mutatorBlendPixel(writer),
|
|
2351
|
+
...mutatorFill(writer),
|
|
2352
|
+
...mutatorInvert(writer)
|
|
2353
|
+
};
|
|
2354
|
+
}
|
|
2355
|
+
|
|
2356
|
+
// src/ImageData/ReusableImageData.ts
|
|
2357
|
+
function makeReusableImageData() {
|
|
2358
|
+
let imageData = null;
|
|
2359
|
+
let buffer = null;
|
|
2360
|
+
return function getReusableImageData(width, height) {
|
|
2361
|
+
const hasInstance = !!imageData;
|
|
2362
|
+
const widthMatches = hasInstance && imageData.width === width;
|
|
2363
|
+
const heightMatches = hasInstance && imageData.height === height;
|
|
2364
|
+
if (!widthMatches || !heightMatches) {
|
|
2365
|
+
const buffer2 = new Uint8ClampedArray(width * height * 4);
|
|
2366
|
+
imageData = new ImageData(buffer2, width, height);
|
|
2367
|
+
}
|
|
2368
|
+
return imageData;
|
|
2369
|
+
};
|
|
2370
|
+
}
|
|
2371
|
+
|
|
2372
|
+
// src/ImageData/copyImageData.ts
|
|
2373
|
+
function copyImageData({ data, width, height }) {
|
|
2374
|
+
return new ImageData(data.slice(), width, height);
|
|
2375
|
+
}
|
|
2376
|
+
function copyImageDataLike({ data, width, height }) {
|
|
2377
|
+
return {
|
|
2378
|
+
data: data.slice(),
|
|
2379
|
+
width,
|
|
2380
|
+
height
|
|
2381
|
+
};
|
|
2382
|
+
}
|
|
2383
|
+
|
|
2384
|
+
// src/PixelData/pixelDataToAlphaMask.ts
|
|
2385
|
+
function pixelDataToAlphaMask(pixelData) {
|
|
2386
|
+
const {
|
|
2387
|
+
data32,
|
|
2388
|
+
width,
|
|
2389
|
+
height
|
|
2390
|
+
} = pixelData;
|
|
2391
|
+
const len = data32.length;
|
|
2392
|
+
const mask = new Uint8Array(width * height);
|
|
2393
|
+
for (let i = 0; i < len; i++) {
|
|
2394
|
+
const val = data32[i];
|
|
2395
|
+
mask[i] = val >>> 24 & 255;
|
|
2396
|
+
}
|
|
2397
|
+
return mask;
|
|
2398
|
+
}
|
|
2399
|
+
|
|
2400
|
+
// src/ImageData/imageDataToAlphaMask.ts
|
|
2401
|
+
function imageDataToAlphaMask(imageData) {
|
|
2402
|
+
const {
|
|
2403
|
+
width,
|
|
2404
|
+
height,
|
|
2405
|
+
data
|
|
2406
|
+
} = imageData;
|
|
2407
|
+
const data32 = new Uint32Array(
|
|
2408
|
+
data.buffer,
|
|
2409
|
+
data.byteOffset,
|
|
2410
|
+
data.byteLength >> 2
|
|
2411
|
+
);
|
|
2412
|
+
const len = data32.length;
|
|
2413
|
+
const mask = new Uint8Array(width * height);
|
|
2414
|
+
for (let i = 0; i < len; i++) {
|
|
2415
|
+
const val = data32[i];
|
|
2416
|
+
mask[i] = val >>> 24 & 255;
|
|
2417
|
+
}
|
|
2418
|
+
return mask;
|
|
2419
|
+
}
|
|
2420
|
+
|
|
2421
|
+
// src/ImageData/imageDataToDataUrl.ts
|
|
2422
|
+
var get = makeReusableCanvas();
|
|
2423
|
+
function imageDataToDataUrl(imageData) {
|
|
2424
|
+
const { canvas, ctx } = get(imageData.width, imageData.height);
|
|
2425
|
+
ctx.putImageData(imageData, 0, 0);
|
|
2426
|
+
return canvas.toDataURL();
|
|
2427
|
+
}
|
|
2428
|
+
imageDataToDataUrl.reset = get.reset;
|
|
2429
|
+
|
|
2430
|
+
// src/ImageData/imageDataToUInt32Array.ts
|
|
2431
|
+
function imageDataToUInt32Array(imageData) {
|
|
2432
|
+
return new Uint32Array(
|
|
2433
|
+
imageData.data.buffer,
|
|
2434
|
+
imageData.data.byteOffset,
|
|
2435
|
+
// Shift right by 2 is a fast bitwise division by 4.
|
|
2436
|
+
imageData.data.byteLength >> 2
|
|
2437
|
+
);
|
|
2438
|
+
}
|
|
2439
|
+
|
|
2440
|
+
// src/ImageData/invertImageData.ts
|
|
2441
|
+
function invertImageData(imageData) {
|
|
2442
|
+
const data = imageData.data;
|
|
2443
|
+
let length = data.length;
|
|
2444
|
+
for (let i = 0; i < length; i += 4) {
|
|
2445
|
+
data[i] = 255 - data[i];
|
|
2446
|
+
data[i + 1] = 255 - data[i + 1];
|
|
2447
|
+
data[i + 2] = 255 - data[i + 2];
|
|
2448
|
+
}
|
|
2449
|
+
return imageData;
|
|
2450
|
+
}
|
|
2451
|
+
|
|
2452
|
+
// src/Internal/resample32.ts
|
|
2453
|
+
var resample32Scratch = {
|
|
2454
|
+
data: null,
|
|
2455
|
+
width: 0,
|
|
2456
|
+
height: 0
|
|
2457
|
+
};
|
|
2458
|
+
function resample32(srcData32, srcW, srcH, factor) {
|
|
2459
|
+
const dstW = Math.max(1, srcW * factor | 0);
|
|
2460
|
+
const dstH = Math.max(1, srcH * factor | 0);
|
|
2461
|
+
const dstData = new Int32Array(dstW * dstH);
|
|
2462
|
+
const scaleX = srcW / dstW;
|
|
2463
|
+
const scaleY = srcH / dstH;
|
|
2464
|
+
for (let y = 0; y < dstH; y++) {
|
|
2465
|
+
const srcY = Math.min(srcH - 1, y * scaleY | 0);
|
|
2466
|
+
const srcRowOffset = srcY * srcW;
|
|
2467
|
+
const dstRowOffset = y * dstW;
|
|
2468
|
+
for (let x = 0; x < dstW; x++) {
|
|
2469
|
+
const srcX = Math.min(srcW - 1, x * scaleX | 0);
|
|
2470
|
+
dstData[dstRowOffset + x] = srcData32[srcRowOffset + srcX];
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
resample32Scratch.data = dstData;
|
|
2474
|
+
resample32Scratch.width = dstW;
|
|
2475
|
+
resample32Scratch.height = dstH;
|
|
2476
|
+
return resample32Scratch;
|
|
2477
|
+
}
|
|
2478
|
+
|
|
2479
|
+
// src/ImageData/resampleImageData.ts
|
|
2480
|
+
function resampleImageData(source, factor) {
|
|
2481
|
+
const src32 = new Uint32Array(source.data.buffer);
|
|
2482
|
+
const { data, width, height } = resample32(src32, source.width, source.height, factor);
|
|
2483
|
+
const uint8ClampedArray = new Uint8ClampedArray(data.buffer);
|
|
2484
|
+
return new ImageData(uint8ClampedArray, width, height);
|
|
2485
|
+
}
|
|
2486
|
+
|
|
2487
|
+
// src/ImageData/resizeImageData.ts
|
|
2488
|
+
function resizeImageData(current, newWidth, newHeight, offsetX = 0, offsetY = 0) {
|
|
2489
|
+
const result = new ImageData(newWidth, newHeight);
|
|
2490
|
+
const {
|
|
2491
|
+
width: oldW,
|
|
2492
|
+
height: oldH,
|
|
2493
|
+
data: oldData
|
|
2494
|
+
} = current;
|
|
2495
|
+
const newData = result.data;
|
|
2496
|
+
const x0 = Math.max(0, offsetX);
|
|
2497
|
+
const y0 = Math.max(0, offsetY);
|
|
2498
|
+
const x1 = Math.min(newWidth, offsetX + oldW);
|
|
2499
|
+
const y1 = Math.min(newHeight, offsetY + oldH);
|
|
2500
|
+
if (x1 <= x0 || y1 <= y0) {
|
|
2501
|
+
return result;
|
|
2502
|
+
}
|
|
2503
|
+
const rowCount = y1 - y0;
|
|
2504
|
+
const rowLen = (x1 - x0) * 4;
|
|
2505
|
+
for (let row = 0; row < rowCount; row++) {
|
|
2506
|
+
const dstY = y0 + row;
|
|
2507
|
+
const srcY = dstY - offsetY;
|
|
2508
|
+
const srcX = x0 - offsetX;
|
|
2509
|
+
const dstStart = (dstY * newWidth + x0) * 4;
|
|
2510
|
+
const srcStart = (srcY * oldW + srcX) * 4;
|
|
2511
|
+
newData.set(
|
|
2512
|
+
oldData.subarray(srcStart, srcStart + rowLen),
|
|
2513
|
+
dstStart
|
|
2514
|
+
);
|
|
2515
|
+
}
|
|
2516
|
+
return result;
|
|
2517
|
+
}
|
|
2518
|
+
|
|
2519
|
+
// src/ImageData/serialization.ts
|
|
2520
|
+
function base64EncodeArrayBuffer(buffer) {
|
|
2521
|
+
const uint8 = new Uint8Array(buffer);
|
|
2522
|
+
const decoder = new TextDecoder("latin1");
|
|
2523
|
+
const binary = decoder.decode(uint8);
|
|
2524
|
+
return btoa(binary);
|
|
2525
|
+
}
|
|
2526
|
+
function base64DecodeArrayBuffer(encoded) {
|
|
2527
|
+
const binary = atob(encoded);
|
|
2528
|
+
const bytes = new Uint8ClampedArray(binary.length);
|
|
2529
|
+
for (let i = 0; i < binary.length; i++) {
|
|
2530
|
+
bytes[i] = binary.charCodeAt(i);
|
|
2531
|
+
}
|
|
2532
|
+
return bytes;
|
|
2533
|
+
}
|
|
2534
|
+
function serializeImageData(imageData) {
|
|
2535
|
+
return {
|
|
2536
|
+
width: imageData.width,
|
|
2537
|
+
height: imageData.height,
|
|
2538
|
+
data: base64EncodeArrayBuffer(imageData.data.buffer)
|
|
2539
|
+
};
|
|
2540
|
+
}
|
|
2541
|
+
function serializeNullableImageData(imageData) {
|
|
2542
|
+
if (!imageData) return null;
|
|
2543
|
+
return serializeImageData(imageData);
|
|
2544
|
+
}
|
|
2545
|
+
function deserializeRawImageData(serialized) {
|
|
2546
|
+
return {
|
|
2547
|
+
width: serialized.width,
|
|
2548
|
+
height: serialized.height,
|
|
2549
|
+
data: base64DecodeArrayBuffer(serialized.data)
|
|
2550
|
+
};
|
|
2551
|
+
}
|
|
2552
|
+
function deserializeImageData(serialized) {
|
|
2553
|
+
const data = base64DecodeArrayBuffer(serialized.data);
|
|
2554
|
+
return new ImageData(data, serialized.width, serialized.height);
|
|
2555
|
+
}
|
|
2556
|
+
function deserializeNullableImageData(serialized) {
|
|
2557
|
+
if (!serialized) return null;
|
|
2558
|
+
return deserializeImageData(serialized);
|
|
2559
|
+
}
|
|
2560
|
+
|
|
2561
|
+
// src/ImageData/writeImageData.ts
|
|
2562
|
+
function writeImageData(target, source, x, y, sx = 0, sy = 0, sw = source.width, sh = source.height, mask = null, maskType = 1 /* BINARY */) {
|
|
2563
|
+
const dstW = target.width;
|
|
2564
|
+
const dstH = target.height;
|
|
2565
|
+
const dstData = target.data;
|
|
2566
|
+
const srcW = source.width;
|
|
2567
|
+
const srcData = source.data;
|
|
2568
|
+
const x0 = Math.max(0, x);
|
|
2569
|
+
const y0 = Math.max(0, y);
|
|
2570
|
+
const x1 = Math.min(dstW, x + sw);
|
|
2571
|
+
const y1 = Math.min(dstH, y + sh);
|
|
2572
|
+
if (x1 <= x0 || y1 <= y0) {
|
|
2573
|
+
return;
|
|
2574
|
+
}
|
|
2575
|
+
const useMask = !!mask;
|
|
2576
|
+
const rowCount = y1 - y0;
|
|
2577
|
+
const rowLenPixels = x1 - x0;
|
|
2578
|
+
for (let row = 0; row < rowCount; row++) {
|
|
2579
|
+
const dstY = y0 + row;
|
|
2580
|
+
const srcY = sy + (dstY - y);
|
|
2581
|
+
const srcXBase = sx + (x0 - x);
|
|
2582
|
+
const dstStart = (dstY * dstW + x0) * 4;
|
|
2583
|
+
const srcStart = (srcY * srcW + srcXBase) * 4;
|
|
2584
|
+
if (useMask && mask) {
|
|
2585
|
+
for (let ix = 0; ix < rowLenPixels; ix++) {
|
|
2586
|
+
const mi = srcY * srcW + (srcXBase + ix);
|
|
2587
|
+
const alpha = mask[mi];
|
|
2588
|
+
if (alpha === 0) {
|
|
2589
|
+
continue;
|
|
2590
|
+
}
|
|
2591
|
+
const di = dstStart + ix * 4;
|
|
2592
|
+
const si = srcStart + ix * 4;
|
|
2593
|
+
if (maskType === 1 /* BINARY */ || alpha === 255) {
|
|
2594
|
+
dstData[di] = srcData[si];
|
|
2595
|
+
dstData[di + 1] = srcData[si + 1];
|
|
2596
|
+
dstData[di + 2] = srcData[si + 2];
|
|
2597
|
+
dstData[di + 3] = srcData[si + 3];
|
|
2598
|
+
} else {
|
|
2599
|
+
const a = alpha / 255;
|
|
2600
|
+
const invA = 1 - a;
|
|
2601
|
+
dstData[di] = srcData[si] * a + dstData[di] * invA;
|
|
2602
|
+
dstData[di + 1] = srcData[si + 1] * a + dstData[di + 1] * invA;
|
|
2603
|
+
dstData[di + 2] = srcData[si + 2] * a + dstData[di + 2] * invA;
|
|
2604
|
+
dstData[di + 3] = srcData[si + 3] * a + dstData[di + 3] * invA;
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2607
|
+
} else {
|
|
2608
|
+
const byteLen = rowLenPixels * 4;
|
|
2609
|
+
const sub = srcData.subarray(srcStart, srcStart + byteLen);
|
|
2610
|
+
dstData.set(sub, dstStart);
|
|
2611
|
+
}
|
|
2612
|
+
}
|
|
2613
|
+
}
|
|
2614
|
+
|
|
2615
|
+
// src/ImageData/writeImageDataBuffer.ts
|
|
2616
|
+
function writeImageDataBuffer(imageData, data, _x, _y, _w, _h) {
|
|
2617
|
+
const { x, y, w, h } = typeof _x === "object" ? _x : { x: _x, y: _y, w: _w, h: _h };
|
|
2618
|
+
const { width: dstW, height: dstH, data: dst } = imageData;
|
|
2619
|
+
const x0 = Math.max(0, x);
|
|
2620
|
+
const y0 = Math.max(0, y);
|
|
2621
|
+
const x1 = Math.min(dstW, x + w);
|
|
2622
|
+
const y1 = Math.min(dstH, y + h);
|
|
2623
|
+
if (x1 <= x0 || y1 <= y0) return;
|
|
2624
|
+
const rowLen = (x1 - x0) * 4;
|
|
2625
|
+
const srcCol = x0 - x;
|
|
2626
|
+
const srcYOffset = y0 - y;
|
|
2627
|
+
const actualH = y1 - y0;
|
|
2628
|
+
for (let row = 0; row < actualH; row++) {
|
|
1652
2629
|
const dstStart = ((y0 + row) * dstW + x0) * 4;
|
|
1653
2630
|
const srcRow = srcYOffset + row;
|
|
1654
2631
|
const o = (srcRow * w + srcCol) * 4;
|
|
@@ -1853,553 +2830,262 @@ async function fileToImageData(file) {
|
|
|
1853
2830
|
);
|
|
1854
2831
|
const ctx = canvas.getContext("2d");
|
|
1855
2832
|
if (!ctx) throw new Error(OFFSCREEN_CANVAS_CTX_FAILED);
|
|
1856
|
-
ctx.drawImage(
|
|
1857
|
-
bitmap,
|
|
1858
|
-
0,
|
|
1859
|
-
0
|
|
1860
|
-
);
|
|
1861
|
-
return ctx.getImageData(
|
|
1862
|
-
0,
|
|
1863
|
-
0,
|
|
1864
|
-
bitmap.width,
|
|
1865
|
-
bitmap.height
|
|
1866
|
-
);
|
|
1867
|
-
} finally {
|
|
1868
|
-
bitmap?.close();
|
|
1869
|
-
}
|
|
1870
|
-
}
|
|
1871
|
-
|
|
1872
|
-
// src/Input/getSupportedRasterFormats.ts
|
|
1873
|
-
var formatsPromise = null;
|
|
1874
|
-
var defaultRasterMimes = [
|
|
1875
|
-
"image/png",
|
|
1876
|
-
"image/jpeg",
|
|
1877
|
-
"image/webp",
|
|
1878
|
-
"image/avif",
|
|
1879
|
-
"image/gif",
|
|
1880
|
-
"image/bmp"
|
|
1881
|
-
];
|
|
1882
|
-
async function getSupportedPixelFormats(rasterMimes = defaultRasterMimes) {
|
|
1883
|
-
if (formatsPromise) {
|
|
1884
|
-
return formatsPromise;
|
|
1885
|
-
}
|
|
1886
|
-
const probeCanvas = async () => {
|
|
1887
|
-
const canvas = new OffscreenCanvas(1, 1);
|
|
1888
|
-
const results = await Promise.all(
|
|
1889
|
-
rasterMimes.map(async (mime) => {
|
|
1890
|
-
try {
|
|
1891
|
-
const blob = await canvas.convertToBlob({
|
|
1892
|
-
type: mime
|
|
1893
|
-
});
|
|
1894
|
-
return blob.type === mime ? mime : null;
|
|
1895
|
-
} catch {
|
|
1896
|
-
return null;
|
|
1897
|
-
}
|
|
1898
|
-
})
|
|
1899
|
-
);
|
|
1900
|
-
return results.filter((type) => {
|
|
1901
|
-
return type !== null;
|
|
1902
|
-
});
|
|
1903
|
-
};
|
|
1904
|
-
formatsPromise = probeCanvas().catch((error) => {
|
|
1905
|
-
formatsPromise = null;
|
|
1906
|
-
throw error;
|
|
1907
|
-
});
|
|
1908
|
-
return formatsPromise;
|
|
1909
|
-
}
|
|
1910
|
-
|
|
1911
|
-
// src/Mask/copyMask.ts
|
|
1912
|
-
function copyMask(src) {
|
|
1913
|
-
return src.slice();
|
|
1914
|
-
}
|
|
1915
|
-
|
|
1916
|
-
// src/Mask/invertMask.ts
|
|
1917
|
-
function invertBinaryMask(dst) {
|
|
1918
|
-
const len = dst.length;
|
|
1919
|
-
for (let i = 0; i < len; i++) {
|
|
1920
|
-
dst[i] = dst[i] === 0 ? 1 : 0;
|
|
1921
|
-
}
|
|
1922
|
-
}
|
|
1923
|
-
function invertAlphaMask(dst) {
|
|
1924
|
-
const len = dst.length;
|
|
1925
|
-
for (let i = 0; i < len; i++) {
|
|
1926
|
-
dst[i] = 255 - dst[i];
|
|
1927
|
-
}
|
|
1928
|
-
}
|
|
1929
|
-
|
|
1930
|
-
// src/Mask/mergeMasks.ts
|
|
1931
|
-
function mergeMasks(dst, dstWidth, src, opts) {
|
|
1932
|
-
const {
|
|
1933
|
-
x: targetX = 0,
|
|
1934
|
-
y: targetY = 0,
|
|
1935
|
-
w: width = 0,
|
|
1936
|
-
h: height = 0,
|
|
1937
|
-
alpha: globalAlpha = 255,
|
|
1938
|
-
maskType = 0 /* ALPHA */,
|
|
1939
|
-
mw,
|
|
1940
|
-
mx = 0,
|
|
1941
|
-
my = 0,
|
|
1942
|
-
invertMask = false
|
|
1943
|
-
} = opts;
|
|
1944
|
-
if (width <= 0 || height <= 0 || globalAlpha === 0) {
|
|
1945
|
-
return;
|
|
1946
|
-
}
|
|
1947
|
-
const sPitch = mw ?? width;
|
|
1948
|
-
const isAlpha = maskType === 0 /* ALPHA */;
|
|
1949
|
-
for (let iy = 0; iy < height; iy++) {
|
|
1950
|
-
const dy = targetY + iy;
|
|
1951
|
-
const sy = my + iy;
|
|
1952
|
-
if (dy < 0 || sy < 0) {
|
|
1953
|
-
continue;
|
|
1954
|
-
}
|
|
1955
|
-
for (let ix = 0; ix < width; ix++) {
|
|
1956
|
-
const dx = targetX + ix;
|
|
1957
|
-
const sx = mx + ix;
|
|
1958
|
-
if (dx < 0 || dx >= dstWidth || sx < 0 || sx >= sPitch) {
|
|
1959
|
-
continue;
|
|
1960
|
-
}
|
|
1961
|
-
const dIdx = dy * dstWidth + dx;
|
|
1962
|
-
const sIdx = sy * sPitch + sx;
|
|
1963
|
-
const mVal = src[sIdx];
|
|
1964
|
-
let weight = globalAlpha;
|
|
1965
|
-
if (isAlpha) {
|
|
1966
|
-
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
1967
|
-
if (effectiveM === 0) {
|
|
1968
|
-
dst[dIdx] = 0;
|
|
1969
|
-
continue;
|
|
1970
|
-
}
|
|
1971
|
-
weight = globalAlpha === 255 ? effectiveM : effectiveM * globalAlpha + 128 >> 8;
|
|
1972
|
-
} else {
|
|
1973
|
-
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
1974
|
-
if (!isHit) {
|
|
1975
|
-
dst[dIdx] = 0;
|
|
1976
|
-
continue;
|
|
1977
|
-
}
|
|
1978
|
-
weight = globalAlpha;
|
|
1979
|
-
}
|
|
1980
|
-
if (weight === 0) {
|
|
1981
|
-
dst[dIdx] = 0;
|
|
1982
|
-
continue;
|
|
1983
|
-
}
|
|
1984
|
-
const da = dst[dIdx];
|
|
1985
|
-
if (da === 0) {
|
|
1986
|
-
} else if (weight === 255) {
|
|
1987
|
-
} else if (da === 255) {
|
|
1988
|
-
dst[dIdx] = weight;
|
|
1989
|
-
} else {
|
|
1990
|
-
dst[dIdx] = da * weight + 128 >> 8;
|
|
1991
|
-
}
|
|
1992
|
-
}
|
|
1993
|
-
}
|
|
1994
|
-
}
|
|
1995
|
-
|
|
1996
|
-
// src/PixelData/PixelData.ts
|
|
1997
|
-
var PixelData = class _PixelData {
|
|
1998
|
-
data32;
|
|
1999
|
-
imageData;
|
|
2000
|
-
get width() {
|
|
2001
|
-
return this.imageData.width;
|
|
2002
|
-
}
|
|
2003
|
-
get height() {
|
|
2004
|
-
return this.imageData.height;
|
|
2005
|
-
}
|
|
2006
|
-
constructor(imageData) {
|
|
2007
|
-
this.data32 = imageDataToUInt32Array(imageData);
|
|
2008
|
-
this.imageData = imageData;
|
|
2009
|
-
}
|
|
2010
|
-
set(imageData) {
|
|
2011
|
-
this.imageData = imageData;
|
|
2012
|
-
this.data32 = imageDataToUInt32Array(imageData);
|
|
2013
|
-
}
|
|
2014
|
-
/**
|
|
2015
|
-
* Creates a deep copy of the PixelData using the environment's ImageData constructor.
|
|
2016
|
-
*/
|
|
2017
|
-
copy() {
|
|
2018
|
-
const buffer = new Uint8ClampedArray(this.imageData.data);
|
|
2019
|
-
const ImageConstructor = typeof ImageData !== "undefined" ? ImageData : this.imageData.constructor;
|
|
2020
|
-
const newImageData = new ImageConstructor(
|
|
2021
|
-
buffer,
|
|
2022
|
-
this.width,
|
|
2023
|
-
this.height
|
|
2833
|
+
ctx.drawImage(
|
|
2834
|
+
bitmap,
|
|
2835
|
+
0,
|
|
2836
|
+
0
|
|
2024
2837
|
);
|
|
2025
|
-
return
|
|
2838
|
+
return ctx.getImageData(
|
|
2839
|
+
0,
|
|
2840
|
+
0,
|
|
2841
|
+
bitmap.width,
|
|
2842
|
+
bitmap.height
|
|
2843
|
+
);
|
|
2844
|
+
} finally {
|
|
2845
|
+
bitmap?.close();
|
|
2026
2846
|
}
|
|
2027
|
-
}
|
|
2847
|
+
}
|
|
2028
2848
|
|
|
2029
|
-
// src/
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
} = opts;
|
|
2043
|
-
let x = targetX;
|
|
2044
|
-
let y = targetY;
|
|
2045
|
-
let w = width;
|
|
2046
|
-
let h = height;
|
|
2047
|
-
if (x < 0) {
|
|
2048
|
-
w += x;
|
|
2049
|
-
x = 0;
|
|
2050
|
-
}
|
|
2051
|
-
if (y < 0) {
|
|
2052
|
-
h += y;
|
|
2053
|
-
y = 0;
|
|
2054
|
-
}
|
|
2055
|
-
const actualW = Math.min(w, dst.width - x);
|
|
2056
|
-
const actualH = Math.min(h, dst.height - y);
|
|
2057
|
-
if (actualW <= 0 || actualH <= 0 || globalAlpha === 0) {
|
|
2058
|
-
return;
|
|
2849
|
+
// src/Input/getSupportedRasterFormats.ts
|
|
2850
|
+
var formatsPromise = null;
|
|
2851
|
+
var defaultRasterMimes = [
|
|
2852
|
+
"image/png",
|
|
2853
|
+
"image/jpeg",
|
|
2854
|
+
"image/webp",
|
|
2855
|
+
"image/avif",
|
|
2856
|
+
"image/gif",
|
|
2857
|
+
"image/bmp"
|
|
2858
|
+
];
|
|
2859
|
+
async function getSupportedPixelFormats(rasterMimes = defaultRasterMimes) {
|
|
2860
|
+
if (formatsPromise) {
|
|
2861
|
+
return formatsPromise;
|
|
2059
2862
|
}
|
|
2060
|
-
const
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
for (let ix = 0; ix < actualW; ix++) {
|
|
2072
|
-
const mVal = mask[mIdx];
|
|
2073
|
-
let weight = globalAlpha;
|
|
2074
|
-
if (isAlpha) {
|
|
2075
|
-
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
2076
|
-
if (effectiveM === 0) {
|
|
2077
|
-
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
2078
|
-
dIdx++;
|
|
2079
|
-
mIdx++;
|
|
2080
|
-
continue;
|
|
2081
|
-
}
|
|
2082
|
-
weight = globalAlpha === 255 ? effectiveM : effectiveM * globalAlpha + 128 >> 8;
|
|
2083
|
-
} else {
|
|
2084
|
-
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
2085
|
-
if (!isHit) {
|
|
2086
|
-
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
2087
|
-
dIdx++;
|
|
2088
|
-
mIdx++;
|
|
2089
|
-
continue;
|
|
2090
|
-
}
|
|
2091
|
-
weight = globalAlpha;
|
|
2092
|
-
}
|
|
2093
|
-
if (weight === 0) {
|
|
2094
|
-
dst32[dIdx] = (dst32[dIdx] & 16777215) >>> 0;
|
|
2095
|
-
} else {
|
|
2096
|
-
const d = dst32[dIdx];
|
|
2097
|
-
const da = d >>> 24;
|
|
2098
|
-
let finalAlpha = da;
|
|
2099
|
-
if (da === 0) {
|
|
2100
|
-
} else if (weight === 255) {
|
|
2101
|
-
} else if (da === 255) {
|
|
2102
|
-
finalAlpha = weight;
|
|
2103
|
-
} else {
|
|
2104
|
-
finalAlpha = da * weight + 128 >> 8;
|
|
2863
|
+
const probeCanvas = async () => {
|
|
2864
|
+
const canvas = new OffscreenCanvas(1, 1);
|
|
2865
|
+
const results = await Promise.all(
|
|
2866
|
+
rasterMimes.map(async (mime) => {
|
|
2867
|
+
try {
|
|
2868
|
+
const blob = await canvas.convertToBlob({
|
|
2869
|
+
type: mime
|
|
2870
|
+
});
|
|
2871
|
+
return blob.type === mime ? mime : null;
|
|
2872
|
+
} catch {
|
|
2873
|
+
return null;
|
|
2105
2874
|
}
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
}
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2875
|
+
})
|
|
2876
|
+
);
|
|
2877
|
+
return results.filter((type) => {
|
|
2878
|
+
return type !== null;
|
|
2879
|
+
});
|
|
2880
|
+
};
|
|
2881
|
+
formatsPromise = probeCanvas().catch((error) => {
|
|
2882
|
+
formatsPromise = null;
|
|
2883
|
+
throw error;
|
|
2884
|
+
});
|
|
2885
|
+
return formatsPromise;
|
|
2114
2886
|
}
|
|
2115
2887
|
|
|
2116
|
-
// src/
|
|
2117
|
-
function
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
maskType = 0 /* ALPHA */,
|
|
2127
|
-
mw,
|
|
2128
|
-
mx = 0,
|
|
2129
|
-
my = 0,
|
|
2130
|
-
invertMask = false
|
|
2131
|
-
} = opts;
|
|
2132
|
-
if (globalAlpha === 0) return;
|
|
2133
|
-
const baseSrcAlpha = color >>> 24;
|
|
2134
|
-
const isOverwrite = blendFn.isOverwrite;
|
|
2135
|
-
if (baseSrcAlpha === 0 && !isOverwrite) return;
|
|
2136
|
-
let x = targetX;
|
|
2137
|
-
let y = targetY;
|
|
2138
|
-
let w = width;
|
|
2139
|
-
let h = height;
|
|
2140
|
-
if (x < 0) {
|
|
2141
|
-
w += x;
|
|
2142
|
-
x = 0;
|
|
2143
|
-
}
|
|
2144
|
-
if (y < 0) {
|
|
2145
|
-
h += y;
|
|
2146
|
-
y = 0;
|
|
2888
|
+
// src/Mask/copyMask.ts
|
|
2889
|
+
function copyMask(src) {
|
|
2890
|
+
return src.slice();
|
|
2891
|
+
}
|
|
2892
|
+
|
|
2893
|
+
// src/Mask/invertMask.ts
|
|
2894
|
+
function invertBinaryMask(dst) {
|
|
2895
|
+
const len = dst.length;
|
|
2896
|
+
for (let i = 0; i < len; i++) {
|
|
2897
|
+
dst[i] = dst[i] === 0 ? 1 : 0;
|
|
2147
2898
|
}
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
const mPitch = mw ?? width;
|
|
2154
|
-
const isAlphaMask = maskType === 0 /* ALPHA */;
|
|
2155
|
-
const dx = x - targetX;
|
|
2156
|
-
const dy = y - targetY;
|
|
2157
|
-
let dIdx = y * dw + x;
|
|
2158
|
-
let mIdx = (my + dy) * mPitch + (mx + dx);
|
|
2159
|
-
const dStride = dw - actualW;
|
|
2160
|
-
const mStride = mPitch - actualW;
|
|
2161
|
-
for (let iy = 0; iy < actualH; iy++) {
|
|
2162
|
-
for (let ix = 0; ix < actualW; ix++) {
|
|
2163
|
-
let weight = globalAlpha;
|
|
2164
|
-
if (mask) {
|
|
2165
|
-
const mVal = mask[mIdx];
|
|
2166
|
-
if (isAlphaMask) {
|
|
2167
|
-
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
2168
|
-
if (effectiveM === 0) {
|
|
2169
|
-
dIdx++;
|
|
2170
|
-
mIdx++;
|
|
2171
|
-
continue;
|
|
2172
|
-
}
|
|
2173
|
-
if (globalAlpha === 255) {
|
|
2174
|
-
weight = effectiveM;
|
|
2175
|
-
} else if (effectiveM === 255) {
|
|
2176
|
-
weight = globalAlpha;
|
|
2177
|
-
} else {
|
|
2178
|
-
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
2179
|
-
}
|
|
2180
|
-
} else {
|
|
2181
|
-
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
2182
|
-
if (!isHit) {
|
|
2183
|
-
dIdx++;
|
|
2184
|
-
mIdx++;
|
|
2185
|
-
continue;
|
|
2186
|
-
}
|
|
2187
|
-
weight = globalAlpha;
|
|
2188
|
-
}
|
|
2189
|
-
if (weight === 0) {
|
|
2190
|
-
dIdx++;
|
|
2191
|
-
mIdx++;
|
|
2192
|
-
continue;
|
|
2193
|
-
}
|
|
2194
|
-
}
|
|
2195
|
-
let currentSrcColor = color;
|
|
2196
|
-
if (weight < 255) {
|
|
2197
|
-
let currentSrcAlpha = baseSrcAlpha;
|
|
2198
|
-
if (baseSrcAlpha === 255) {
|
|
2199
|
-
currentSrcAlpha = weight;
|
|
2200
|
-
} else {
|
|
2201
|
-
currentSrcAlpha = baseSrcAlpha * weight + 128 >> 8;
|
|
2202
|
-
}
|
|
2203
|
-
if (!isOverwrite && currentSrcAlpha === 0) {
|
|
2204
|
-
dIdx++;
|
|
2205
|
-
mIdx++;
|
|
2206
|
-
continue;
|
|
2207
|
-
}
|
|
2208
|
-
currentSrcColor = (color & 16777215 | currentSrcAlpha << 24) >>> 0;
|
|
2209
|
-
}
|
|
2210
|
-
dst32[dIdx] = blendFn(currentSrcColor, dst32[dIdx]);
|
|
2211
|
-
dIdx++;
|
|
2212
|
-
mIdx++;
|
|
2213
|
-
}
|
|
2214
|
-
dIdx += dStride;
|
|
2215
|
-
mIdx += mStride;
|
|
2899
|
+
}
|
|
2900
|
+
function invertAlphaMask(dst) {
|
|
2901
|
+
const len = dst.length;
|
|
2902
|
+
for (let i = 0; i < len; i++) {
|
|
2903
|
+
dst[i] = 255 - dst[i];
|
|
2216
2904
|
}
|
|
2217
2905
|
}
|
|
2218
2906
|
|
|
2219
|
-
// src/
|
|
2220
|
-
function
|
|
2907
|
+
// src/Mask/mergeMasks.ts
|
|
2908
|
+
function mergeMasks(dst, dstWidth, src, opts) {
|
|
2221
2909
|
const {
|
|
2222
|
-
x: targetX = 0,
|
|
2223
|
-
y: targetY = 0,
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
w: width = src.width,
|
|
2227
|
-
h: height = src.height,
|
|
2910
|
+
x: targetX = 0,
|
|
2911
|
+
y: targetY = 0,
|
|
2912
|
+
w: width = 0,
|
|
2913
|
+
h: height = 0,
|
|
2228
2914
|
alpha: globalAlpha = 255,
|
|
2229
|
-
blendFn = sourceOverFast,
|
|
2230
|
-
mask,
|
|
2231
2915
|
maskType = 0 /* ALPHA */,
|
|
2232
2916
|
mw,
|
|
2233
2917
|
mx = 0,
|
|
2234
2918
|
my = 0,
|
|
2235
2919
|
invertMask = false
|
|
2236
2920
|
} = opts;
|
|
2237
|
-
if (globalAlpha === 0)
|
|
2238
|
-
|
|
2239
|
-
let y = targetY;
|
|
2240
|
-
let sx = sourceX;
|
|
2241
|
-
let sy = sourceY;
|
|
2242
|
-
let w = width;
|
|
2243
|
-
let h = height;
|
|
2244
|
-
if (sx < 0) {
|
|
2245
|
-
x -= sx;
|
|
2246
|
-
w += sx;
|
|
2247
|
-
sx = 0;
|
|
2248
|
-
}
|
|
2249
|
-
if (sy < 0) {
|
|
2250
|
-
y -= sy;
|
|
2251
|
-
h += sy;
|
|
2252
|
-
sy = 0;
|
|
2253
|
-
}
|
|
2254
|
-
w = Math.min(w, src.width - sx);
|
|
2255
|
-
h = Math.min(h, src.height - sy);
|
|
2256
|
-
if (x < 0) {
|
|
2257
|
-
sx -= x;
|
|
2258
|
-
w += x;
|
|
2259
|
-
x = 0;
|
|
2260
|
-
}
|
|
2261
|
-
if (y < 0) {
|
|
2262
|
-
sy -= y;
|
|
2263
|
-
h += y;
|
|
2264
|
-
y = 0;
|
|
2921
|
+
if (width <= 0 || height <= 0 || globalAlpha === 0) {
|
|
2922
|
+
return;
|
|
2265
2923
|
}
|
|
2266
|
-
const
|
|
2267
|
-
const
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
let sIdx = sy * sw + sx;
|
|
2279
|
-
let mIdx = (my + dy) * mPitch + (mx + dx);
|
|
2280
|
-
const dStride = dw - actualW;
|
|
2281
|
-
const sStride = sw - actualW;
|
|
2282
|
-
const mStride = mPitch - actualW;
|
|
2283
|
-
const isOverwrite = blendFn.isOverwrite;
|
|
2284
|
-
for (let iy = 0; iy < actualH; iy++) {
|
|
2285
|
-
for (let ix = 0; ix < actualW; ix++) {
|
|
2286
|
-
const baseSrcColor = src32[sIdx];
|
|
2287
|
-
const baseSrcAlpha = baseSrcColor >>> 24;
|
|
2288
|
-
if (baseSrcAlpha === 0 && !isOverwrite) {
|
|
2289
|
-
dIdx++;
|
|
2290
|
-
sIdx++;
|
|
2291
|
-
mIdx++;
|
|
2924
|
+
const sPitch = mw ?? width;
|
|
2925
|
+
const isAlpha = maskType === 0 /* ALPHA */;
|
|
2926
|
+
for (let iy = 0; iy < height; iy++) {
|
|
2927
|
+
const dy = targetY + iy;
|
|
2928
|
+
const sy = my + iy;
|
|
2929
|
+
if (dy < 0 || sy < 0) {
|
|
2930
|
+
continue;
|
|
2931
|
+
}
|
|
2932
|
+
for (let ix = 0; ix < width; ix++) {
|
|
2933
|
+
const dx = targetX + ix;
|
|
2934
|
+
const sx = mx + ix;
|
|
2935
|
+
if (dx < 0 || dx >= dstWidth || sx < 0 || sx >= sPitch) {
|
|
2292
2936
|
continue;
|
|
2293
2937
|
}
|
|
2938
|
+
const dIdx = dy * dstWidth + dx;
|
|
2939
|
+
const sIdx = sy * sPitch + sx;
|
|
2940
|
+
const mVal = src[sIdx];
|
|
2294
2941
|
let weight = globalAlpha;
|
|
2295
|
-
if (
|
|
2296
|
-
const
|
|
2297
|
-
if (
|
|
2298
|
-
|
|
2299
|
-
if (effectiveM === 0) {
|
|
2300
|
-
dIdx++;
|
|
2301
|
-
sIdx++;
|
|
2302
|
-
mIdx++;
|
|
2303
|
-
continue;
|
|
2304
|
-
}
|
|
2305
|
-
if (globalAlpha === 255) {
|
|
2306
|
-
weight = effectiveM;
|
|
2307
|
-
} else if (effectiveM === 255) {
|
|
2308
|
-
weight = globalAlpha;
|
|
2309
|
-
} else {
|
|
2310
|
-
weight = effectiveM * globalAlpha + 128 >> 8;
|
|
2311
|
-
}
|
|
2312
|
-
} else {
|
|
2313
|
-
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
2314
|
-
if (!isHit) {
|
|
2315
|
-
dIdx++;
|
|
2316
|
-
sIdx++;
|
|
2317
|
-
mIdx++;
|
|
2318
|
-
continue;
|
|
2319
|
-
}
|
|
2320
|
-
weight = globalAlpha;
|
|
2321
|
-
}
|
|
2322
|
-
if (weight === 0) {
|
|
2323
|
-
dIdx++;
|
|
2324
|
-
sIdx++;
|
|
2325
|
-
mIdx++;
|
|
2942
|
+
if (isAlpha) {
|
|
2943
|
+
const effectiveM = invertMask ? 255 - mVal : mVal;
|
|
2944
|
+
if (effectiveM === 0) {
|
|
2945
|
+
dst[dIdx] = 0;
|
|
2326
2946
|
continue;
|
|
2327
2947
|
}
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
currentSrcAlpha = weight;
|
|
2334
|
-
} else {
|
|
2335
|
-
currentSrcAlpha = baseSrcAlpha * weight + 128 >> 8;
|
|
2336
|
-
}
|
|
2337
|
-
if (!isOverwrite && currentSrcAlpha === 0) {
|
|
2338
|
-
dIdx++;
|
|
2339
|
-
sIdx++;
|
|
2340
|
-
mIdx++;
|
|
2948
|
+
weight = globalAlpha === 255 ? effectiveM : effectiveM * globalAlpha + 128 >> 8;
|
|
2949
|
+
} else {
|
|
2950
|
+
const isHit = invertMask ? mVal === 0 : mVal === 1;
|
|
2951
|
+
if (!isHit) {
|
|
2952
|
+
dst[dIdx] = 0;
|
|
2341
2953
|
continue;
|
|
2342
2954
|
}
|
|
2343
|
-
|
|
2955
|
+
weight = globalAlpha;
|
|
2956
|
+
}
|
|
2957
|
+
if (weight === 0) {
|
|
2958
|
+
dst[dIdx] = 0;
|
|
2959
|
+
continue;
|
|
2960
|
+
}
|
|
2961
|
+
const da = dst[dIdx];
|
|
2962
|
+
if (da === 0) {
|
|
2963
|
+
} else if (weight === 255) {
|
|
2964
|
+
} else if (da === 255) {
|
|
2965
|
+
dst[dIdx] = weight;
|
|
2966
|
+
} else {
|
|
2967
|
+
dst[dIdx] = da * weight + 128 >> 8;
|
|
2344
2968
|
}
|
|
2345
|
-
dst32[dIdx] = blendFn(currentSrcColor, dst32[dIdx]);
|
|
2346
|
-
dIdx++;
|
|
2347
|
-
sIdx++;
|
|
2348
|
-
mIdx++;
|
|
2349
2969
|
}
|
|
2350
|
-
dIdx += dStride;
|
|
2351
|
-
sIdx += sStride;
|
|
2352
|
-
mIdx += mStride;
|
|
2353
2970
|
}
|
|
2354
2971
|
}
|
|
2355
2972
|
|
|
2356
|
-
// src/PixelData/
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
if (typeof _x === "object") {
|
|
2363
|
-
x = _x.x ?? 0;
|
|
2364
|
-
y = _x.y ?? 0;
|
|
2365
|
-
w = _x.w ?? dst.width;
|
|
2366
|
-
h = _x.h ?? dst.height;
|
|
2367
|
-
} else if (typeof _x === "number") {
|
|
2368
|
-
x = _x;
|
|
2369
|
-
y = _y;
|
|
2370
|
-
w = _w;
|
|
2371
|
-
h = _h;
|
|
2372
|
-
} else {
|
|
2373
|
-
x = 0;
|
|
2374
|
-
y = 0;
|
|
2375
|
-
w = dst.width;
|
|
2376
|
-
h = dst.height;
|
|
2973
|
+
// src/PixelData/PixelData.ts
|
|
2974
|
+
var PixelData = class _PixelData {
|
|
2975
|
+
data32;
|
|
2976
|
+
imageData;
|
|
2977
|
+
get width() {
|
|
2978
|
+
return this.imageData.width;
|
|
2377
2979
|
}
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
x = 0;
|
|
2980
|
+
get height() {
|
|
2981
|
+
return this.imageData.height;
|
|
2381
2982
|
}
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2983
|
+
constructor(imageData) {
|
|
2984
|
+
this.data32 = imageDataToUInt32Array(imageData);
|
|
2985
|
+
this.imageData = imageData;
|
|
2385
2986
|
}
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
return;
|
|
2987
|
+
set(imageData) {
|
|
2988
|
+
this.imageData = imageData;
|
|
2989
|
+
this.data32 = imageDataToUInt32Array(imageData);
|
|
2390
2990
|
}
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2991
|
+
/**
|
|
2992
|
+
* Creates a deep copy of the PixelData using the environment's ImageData constructor.
|
|
2993
|
+
*/
|
|
2994
|
+
copy() {
|
|
2995
|
+
const buffer = new Uint8ClampedArray(this.imageData.data);
|
|
2996
|
+
const ImageConstructor = typeof ImageData !== "undefined" ? ImageData : this.imageData.constructor;
|
|
2997
|
+
const newImageData = new ImageConstructor(
|
|
2998
|
+
buffer,
|
|
2999
|
+
this.width,
|
|
3000
|
+
this.height
|
|
3001
|
+
);
|
|
3002
|
+
return new _PixelData(newImageData);
|
|
2396
3003
|
}
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
3004
|
+
};
|
|
3005
|
+
|
|
3006
|
+
// src/PixelData/applyCircleBrushToPixelData.ts
|
|
3007
|
+
function applyCircleBrushToPixelData(target, color, centerX, centerY, brushSize, alpha = 255, fallOff, blendFn = sourceOverPerfect) {
|
|
3008
|
+
const r = brushSize / 2;
|
|
3009
|
+
const rSqr = r * r;
|
|
3010
|
+
const centerOffset = brushSize % 2 === 0 ? 0.5 : 0;
|
|
3011
|
+
const xStart = Math.max(0, Math.ceil(centerX - r));
|
|
3012
|
+
const xEnd = Math.min(target.width - 1, Math.floor(centerX + r));
|
|
3013
|
+
const yStart = Math.max(0, Math.ceil(centerY - r));
|
|
3014
|
+
const yEnd = Math.min(target.height - 1, Math.floor(centerY + r));
|
|
3015
|
+
const data32 = target.data32;
|
|
3016
|
+
const targetWidth = target.width;
|
|
3017
|
+
const baseColor = color & 16777215;
|
|
3018
|
+
const invR = 1 / r;
|
|
3019
|
+
const constantSrc = (alpha << 24 | baseColor) >>> 0;
|
|
3020
|
+
for (let cy = yStart; cy <= yEnd; cy++) {
|
|
3021
|
+
const dy = cy - centerY + centerOffset;
|
|
3022
|
+
const dySqr = dy * dy;
|
|
3023
|
+
const rowOffset = cy * targetWidth;
|
|
3024
|
+
for (let cx = xStart; cx <= xEnd; cx++) {
|
|
3025
|
+
const dx = cx - centerX + centerOffset;
|
|
3026
|
+
const dSqr = dx * dx + dySqr;
|
|
3027
|
+
if (dSqr <= rSqr) {
|
|
3028
|
+
const idx = rowOffset + cx;
|
|
3029
|
+
if (fallOff) {
|
|
3030
|
+
const strength = fallOff(Math.sqrt(dSqr) * invR);
|
|
3031
|
+
const fAlpha = alpha * strength & 255;
|
|
3032
|
+
const src = (fAlpha << 24 | baseColor) >>> 0;
|
|
3033
|
+
data32[idx] = blendFn(src, data32[idx]);
|
|
3034
|
+
} else {
|
|
3035
|
+
data32[idx] = blendFn(constantSrc, data32[idx]);
|
|
3036
|
+
}
|
|
3037
|
+
}
|
|
3038
|
+
}
|
|
3039
|
+
}
|
|
3040
|
+
}
|
|
3041
|
+
|
|
3042
|
+
// src/PixelData/applyRectBrushToPixelData.ts
|
|
3043
|
+
function applyRectBrushToPixelData(target, color, centerX, centerY, brushWidth, brushHeight, alpha = 255, fallOff, blendFn = sourceOverPerfect) {
|
|
3044
|
+
const targetWidth = target.width;
|
|
3045
|
+
const targetHeight = target.height;
|
|
3046
|
+
const data32 = target.data32;
|
|
3047
|
+
const rawStartX = Math.floor(centerX - brushWidth / 2);
|
|
3048
|
+
const rawStartY = Math.floor(centerY - brushHeight / 2);
|
|
3049
|
+
const endX = Math.min(targetWidth, rawStartX + brushWidth);
|
|
3050
|
+
const endY = Math.min(targetHeight, rawStartY + brushHeight);
|
|
3051
|
+
const startX = Math.max(0, rawStartX);
|
|
3052
|
+
const startY = Math.max(0, rawStartY);
|
|
3053
|
+
const baseColor = color & 16777215;
|
|
3054
|
+
const constantSrc = (alpha << 24 | baseColor) >>> 0;
|
|
3055
|
+
const invHalfW = 1 / (brushWidth / 2);
|
|
3056
|
+
const invHalfH = 1 / (brushHeight / 2);
|
|
3057
|
+
for (let py = startY; py < endY; py++) {
|
|
3058
|
+
const rowOffset = py * targetWidth;
|
|
3059
|
+
const dy = Math.abs(py + 0.5 - centerY) * invHalfH;
|
|
3060
|
+
for (let px = startX; px < endX; px++) {
|
|
3061
|
+
if (fallOff) {
|
|
3062
|
+
const dx = Math.abs(px + 0.5 - centerX) * invHalfW;
|
|
3063
|
+
const dist = dx > dy ? dx : dy;
|
|
3064
|
+
const fAlpha = alpha * fallOff(dist) | 0;
|
|
3065
|
+
const src = (fAlpha << 24 | baseColor) >>> 0;
|
|
3066
|
+
data32[rowOffset + px] = blendFn(src, data32[rowOffset + px]);
|
|
3067
|
+
} else {
|
|
3068
|
+
data32[rowOffset + px] = blendFn(constantSrc, data32[rowOffset + px]);
|
|
3069
|
+
}
|
|
3070
|
+
}
|
|
2401
3071
|
}
|
|
2402
3072
|
}
|
|
3073
|
+
function getRectBrushBounds(centerX, centerY, brushWidth, brushHeight, targetWidth, targetHeight) {
|
|
3074
|
+
const rawStartX = Math.floor(centerX - brushWidth / 2);
|
|
3075
|
+
const rawStartY = Math.floor(centerY - brushHeight / 2);
|
|
3076
|
+
const rawEndX = rawStartX + brushWidth;
|
|
3077
|
+
const rawEndY = rawStartY + brushHeight;
|
|
3078
|
+
const startX = targetWidth !== void 0 ? Math.max(0, rawStartX) : rawStartX;
|
|
3079
|
+
const startY = targetHeight !== void 0 ? Math.max(0, rawStartY) : rawStartY;
|
|
3080
|
+
const endX = targetWidth !== void 0 ? Math.min(targetWidth, rawEndX) : rawEndX;
|
|
3081
|
+
const endY = targetHeight !== void 0 ? Math.min(targetHeight, rawEndY) : rawEndY;
|
|
3082
|
+
return {
|
|
3083
|
+
x: startX,
|
|
3084
|
+
y: startY,
|
|
3085
|
+
w: endX - startX,
|
|
3086
|
+
h: endY - startY
|
|
3087
|
+
};
|
|
3088
|
+
}
|
|
2403
3089
|
|
|
2404
3090
|
// src/PixelData/clearPixelData.ts
|
|
2405
3091
|
function clearPixelData(dst, rect) {
|
|
@@ -2447,16 +3133,6 @@ function extractPixelData(source, _x, _y, _w, _h) {
|
|
|
2447
3133
|
return result;
|
|
2448
3134
|
}
|
|
2449
3135
|
|
|
2450
|
-
// src/PixelData/invertPixelData.ts
|
|
2451
|
-
function invertPixelData(pixelData) {
|
|
2452
|
-
const data32 = pixelData.data32;
|
|
2453
|
-
const len = data32.length;
|
|
2454
|
-
for (let i = 0; i < len; i++) {
|
|
2455
|
-
data32[i] = data32[i] ^ 16777215;
|
|
2456
|
-
}
|
|
2457
|
-
return pixelData;
|
|
2458
|
-
}
|
|
2459
|
-
|
|
2460
3136
|
// src/PixelData/reflectPixelData.ts
|
|
2461
3137
|
function reflectPixelDataHorizontal(pixelData) {
|
|
2462
3138
|
const width = pixelData.width;
|
|
@@ -2547,15 +3223,53 @@ function rotateSquareInPlace(pixelData) {
|
|
|
2547
3223
|
}
|
|
2548
3224
|
}
|
|
2549
3225
|
}
|
|
3226
|
+
|
|
3227
|
+
// src/PixelData/writePixelDataBuffer.ts
|
|
3228
|
+
function writePixelDataBuffer(target, data, _x, _y, _w, _h) {
|
|
3229
|
+
const { x, y, w, h } = typeof _x === "object" ? _x : {
|
|
3230
|
+
x: _x,
|
|
3231
|
+
y: _y,
|
|
3232
|
+
w: _w,
|
|
3233
|
+
h: _h
|
|
3234
|
+
};
|
|
3235
|
+
const dstW = target.width;
|
|
3236
|
+
const dstH = target.height;
|
|
3237
|
+
const dstData = target.data32;
|
|
3238
|
+
const x0 = Math.max(0, x);
|
|
3239
|
+
const y0 = Math.max(0, y);
|
|
3240
|
+
const x1 = Math.min(dstW, x + w);
|
|
3241
|
+
const y1 = Math.min(dstH, y + h);
|
|
3242
|
+
if (x1 <= x0 || y1 <= y0) {
|
|
3243
|
+
return;
|
|
3244
|
+
}
|
|
3245
|
+
const rowLen = x1 - x0;
|
|
3246
|
+
const srcCol = x0 - x;
|
|
3247
|
+
const srcYOffset = y0 - y;
|
|
3248
|
+
const actualH = y1 - y0;
|
|
3249
|
+
for (let row = 0; row < actualH; row++) {
|
|
3250
|
+
const dstStart = (y0 + row) * dstW + x0;
|
|
3251
|
+
const srcRow = srcYOffset + row;
|
|
3252
|
+
const srcStart = srcRow * w + srcCol;
|
|
3253
|
+
dstData.set(data.subarray(srcStart, srcStart + rowLen), dstStart);
|
|
3254
|
+
}
|
|
3255
|
+
}
|
|
2550
3256
|
export {
|
|
2551
3257
|
BASE_FAST_BLEND_MODE_FUNCTIONS,
|
|
2552
3258
|
BASE_PERFECT_BLEND_MODE_FUNCTIONS,
|
|
2553
3259
|
BaseBlendMode,
|
|
3260
|
+
HistoryManager,
|
|
2554
3261
|
IndexedImage,
|
|
2555
3262
|
MaskType,
|
|
3263
|
+
PixelAccumulator,
|
|
2556
3264
|
PixelData,
|
|
3265
|
+
PixelEngineConfig,
|
|
3266
|
+
PixelTile,
|
|
3267
|
+
PixelWriter,
|
|
2557
3268
|
UnsupportedFormatError,
|
|
3269
|
+
applyCircleBrushToPixelData,
|
|
2558
3270
|
applyMaskToPixelData,
|
|
3271
|
+
applyPatchTiles,
|
|
3272
|
+
applyRectBrushToPixelData,
|
|
2559
3273
|
base64DecodeArrayBuffer,
|
|
2560
3274
|
base64EncodeArrayBuffer,
|
|
2561
3275
|
blendColorPixelData,
|
|
@@ -2594,6 +3308,7 @@ export {
|
|
|
2594
3308
|
floodFillSelection,
|
|
2595
3309
|
getImageDataFromClipboard,
|
|
2596
3310
|
getIndexedImageColorCounts,
|
|
3311
|
+
getRectBrushBounds,
|
|
2597
3312
|
getSupportedPixelFormats,
|
|
2598
3313
|
hardLightFast,
|
|
2599
3314
|
hardLightPerfect,
|
|
@@ -2624,6 +3339,7 @@ export {
|
|
|
2624
3339
|
linearLightPerfect,
|
|
2625
3340
|
makeBlendModeRegistry,
|
|
2626
3341
|
makeFastBlendModeRegistry,
|
|
3342
|
+
makeFullPixelMutator,
|
|
2627
3343
|
makePerfectBlendModeRegistry,
|
|
2628
3344
|
makePixelCanvas,
|
|
2629
3345
|
makeReusableCanvas,
|
|
@@ -2631,6 +3347,12 @@ export {
|
|
|
2631
3347
|
mergeMasks,
|
|
2632
3348
|
multiplyFast,
|
|
2633
3349
|
multiplyPerfect,
|
|
3350
|
+
mutatorApplyMask,
|
|
3351
|
+
mutatorBlendColor,
|
|
3352
|
+
mutatorBlendPixel,
|
|
3353
|
+
mutatorBlendPixelData,
|
|
3354
|
+
mutatorFill,
|
|
3355
|
+
mutatorInvert,
|
|
2634
3356
|
overlayFast,
|
|
2635
3357
|
overlayPerfect,
|
|
2636
3358
|
overwriteBase,
|
|
@@ -2668,8 +3390,9 @@ export {
|
|
|
2668
3390
|
vividLightFast,
|
|
2669
3391
|
vividLightPerfect,
|
|
2670
3392
|
writeImageData,
|
|
2671
|
-
|
|
3393
|
+
writeImageDataBuffer,
|
|
2672
3394
|
writeImageDataToClipboard,
|
|
2673
|
-
writeImgBlobToClipboard
|
|
3395
|
+
writeImgBlobToClipboard,
|
|
3396
|
+
writePixelDataBuffer
|
|
2674
3397
|
};
|
|
2675
3398
|
//# sourceMappingURL=index.dev.js.map
|