Fraser commited on
Commit
edc4c90
·
1 Parent(s): c77c1ad

better bck rm

Browse files
package-lock.json CHANGED
@@ -8,6 +8,7 @@
8
  "name": "svelte",
9
  "version": "0.0.0",
10
  "dependencies": {
 
11
  "dexie": "^4.0.11"
12
  },
13
  "devDependencies": {
@@ -480,6 +481,20 @@
480
  "node": ">=18"
481
  }
482
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
483
  "node_modules/@jridgewell/gen-mapping": {
484
  "version": "0.3.12",
485
  "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz",
@@ -526,6 +541,80 @@
526
  "dev": true,
527
  "license": "MIT"
528
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
529
  "node_modules/@rollup/rollup-android-arm-eabi": {
530
  "version": "4.45.1",
531
  "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.45.1.tgz",
@@ -891,7 +980,6 @@
891
  "version": "24.0.14",
892
  "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.14.tgz",
893
  "integrity": "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw==",
894
- "dev": true,
895
  "license": "MIT",
896
  "dependencies": {
897
  "undici-types": "~7.8.0"
@@ -1309,6 +1397,13 @@
1309
  "dev": true,
1310
  "license": "MIT"
1311
  },
 
 
 
 
 
 
 
1312
  "node_modules/flatted": {
1313
  "version": "3.3.3",
1314
  "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
@@ -1331,6 +1426,13 @@
1331
  "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
1332
  }
1333
  },
 
 
 
 
 
 
 
1334
  "node_modules/happy-dom": {
1335
  "version": "18.0.1",
1336
  "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-18.0.1.tgz",
@@ -1363,6 +1465,18 @@
1363
  "dev": true,
1364
  "license": "MIT"
1365
  },
 
 
 
 
 
 
 
 
 
 
 
 
1366
  "node_modules/is-reference": {
1367
  "version": "3.0.3",
1368
  "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",
@@ -1397,6 +1511,19 @@
1397
  "dev": true,
1398
  "license": "MIT"
1399
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
1400
  "node_modules/loupe": {
1401
  "version": "3.1.4",
1402
  "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.4.tgz",
@@ -1460,6 +1587,38 @@
1460
  "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
1461
  }
1462
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1463
  "node_modules/pathe": {
1464
  "version": "2.0.3",
1465
  "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
@@ -1497,6 +1656,13 @@
1497
  "url": "https://github.com/sponsors/jonschlinkert"
1498
  }
1499
  },
 
 
 
 
 
 
 
1500
  "node_modules/postcss": {
1501
  "version": "8.5.6",
1502
  "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
@@ -1526,6 +1692,31 @@
1526
  "node": "^10 || ^12 || >=14"
1527
  }
1528
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1529
  "node_modules/readdirp": {
1530
  "version": "4.1.2",
1531
  "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
@@ -1791,7 +1982,6 @@
1791
  "version": "7.8.0",
1792
  "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz",
1793
  "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==",
1794
- "dev": true,
1795
  "license": "MIT"
1796
  },
1797
  "node_modules/vite": {
@@ -2018,6 +2208,15 @@
2018
  "integrity": "sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==",
2019
  "dev": true,
2020
  "license": "MIT"
 
 
 
 
 
 
 
 
 
2021
  }
2022
  }
2023
  }
 
8
  "name": "svelte",
9
  "version": "0.0.0",
10
  "dependencies": {
11
+ "@imgly/background-removal": "^1.7.0",
12
  "dexie": "^4.0.11"
13
  },
14
  "devDependencies": {
 
481
  "node": ">=18"
482
  }
483
  },
484
+ "node_modules/@imgly/background-removal": {
485
+ "version": "1.7.0",
486
+ "resolved": "https://registry.npmjs.org/@imgly/background-removal/-/background-removal-1.7.0.tgz",
487
+ "integrity": "sha512-/1ZryrMYg2ckIvJKoTu5Np50JfYMVffDMlVmppw/BdbN3pBTN7e6stI5/7E/LVh9DDzz6J588s7sWqul3fy5wA==",
488
+ "license": "SEE LICENSE IN LICENSE.md",
489
+ "dependencies": {
490
+ "lodash-es": "^4.17.21",
491
+ "ndarray": "~1.0.0",
492
+ "zod": "^3.23.8"
493
+ },
494
+ "peerDependencies": {
495
+ "onnxruntime-web": "1.21.0"
496
+ }
497
+ },
498
  "node_modules/@jridgewell/gen-mapping": {
499
  "version": "0.3.12",
500
  "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz",
 
541
  "dev": true,
542
  "license": "MIT"
543
  },
544
+ "node_modules/@protobufjs/aspromise": {
545
+ "version": "1.1.2",
546
+ "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
547
+ "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
548
+ "license": "BSD-3-Clause",
549
+ "peer": true
550
+ },
551
+ "node_modules/@protobufjs/base64": {
552
+ "version": "1.1.2",
553
+ "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
554
+ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
555
+ "license": "BSD-3-Clause",
556
+ "peer": true
557
+ },
558
+ "node_modules/@protobufjs/codegen": {
559
+ "version": "2.0.4",
560
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
561
+ "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==",
562
+ "license": "BSD-3-Clause",
563
+ "peer": true
564
+ },
565
+ "node_modules/@protobufjs/eventemitter": {
566
+ "version": "1.1.0",
567
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
568
+ "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==",
569
+ "license": "BSD-3-Clause",
570
+ "peer": true
571
+ },
572
+ "node_modules/@protobufjs/fetch": {
573
+ "version": "1.1.0",
574
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
575
+ "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
576
+ "license": "BSD-3-Clause",
577
+ "peer": true,
578
+ "dependencies": {
579
+ "@protobufjs/aspromise": "^1.1.1",
580
+ "@protobufjs/inquire": "^1.1.0"
581
+ }
582
+ },
583
+ "node_modules/@protobufjs/float": {
584
+ "version": "1.0.2",
585
+ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
586
+ "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
587
+ "license": "BSD-3-Clause",
588
+ "peer": true
589
+ },
590
+ "node_modules/@protobufjs/inquire": {
591
+ "version": "1.1.0",
592
+ "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
593
+ "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==",
594
+ "license": "BSD-3-Clause",
595
+ "peer": true
596
+ },
597
+ "node_modules/@protobufjs/path": {
598
+ "version": "1.1.2",
599
+ "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
600
+ "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
601
+ "license": "BSD-3-Clause",
602
+ "peer": true
603
+ },
604
+ "node_modules/@protobufjs/pool": {
605
+ "version": "1.1.0",
606
+ "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
607
+ "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
608
+ "license": "BSD-3-Clause",
609
+ "peer": true
610
+ },
611
+ "node_modules/@protobufjs/utf8": {
612
+ "version": "1.1.0",
613
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
614
+ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==",
615
+ "license": "BSD-3-Clause",
616
+ "peer": true
617
+ },
618
  "node_modules/@rollup/rollup-android-arm-eabi": {
619
  "version": "4.45.1",
620
  "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.45.1.tgz",
 
980
  "version": "24.0.14",
981
  "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.14.tgz",
982
  "integrity": "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw==",
 
983
  "license": "MIT",
984
  "dependencies": {
985
  "undici-types": "~7.8.0"
 
1397
  "dev": true,
1398
  "license": "MIT"
1399
  },
1400
+ "node_modules/flatbuffers": {
1401
+ "version": "25.2.10",
1402
+ "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-25.2.10.tgz",
1403
+ "integrity": "sha512-7JlN9ZvLDG1McO3kbX0k4v+SUAg48L1rIwEvN6ZQl/eCtgJz9UylTMzE9wrmYrcorgxm3CX/3T/w5VAub99UUw==",
1404
+ "license": "Apache-2.0",
1405
+ "peer": true
1406
+ },
1407
  "node_modules/flatted": {
1408
  "version": "3.3.3",
1409
  "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
 
1426
  "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
1427
  }
1428
  },
1429
+ "node_modules/guid-typescript": {
1430
+ "version": "1.0.9",
1431
+ "resolved": "https://registry.npmjs.org/guid-typescript/-/guid-typescript-1.0.9.tgz",
1432
+ "integrity": "sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ==",
1433
+ "license": "ISC",
1434
+ "peer": true
1435
+ },
1436
  "node_modules/happy-dom": {
1437
  "version": "18.0.1",
1438
  "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-18.0.1.tgz",
 
1465
  "dev": true,
1466
  "license": "MIT"
1467
  },
1468
+ "node_modules/iota-array": {
1469
+ "version": "1.0.0",
1470
+ "resolved": "https://registry.npmjs.org/iota-array/-/iota-array-1.0.0.tgz",
1471
+ "integrity": "sha512-pZ2xT+LOHckCatGQ3DcG/a+QuEqvoxqkiL7tvE8nn3uuu+f6i1TtpB5/FtWFbxUuVr5PZCx8KskuGatbJDXOWA==",
1472
+ "license": "MIT"
1473
+ },
1474
+ "node_modules/is-buffer": {
1475
+ "version": "1.1.6",
1476
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
1477
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
1478
+ "license": "MIT"
1479
+ },
1480
  "node_modules/is-reference": {
1481
  "version": "3.0.3",
1482
  "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",
 
1511
  "dev": true,
1512
  "license": "MIT"
1513
  },
1514
+ "node_modules/lodash-es": {
1515
+ "version": "4.17.21",
1516
+ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
1517
+ "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
1518
+ "license": "MIT"
1519
+ },
1520
+ "node_modules/long": {
1521
+ "version": "5.3.2",
1522
+ "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
1523
+ "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
1524
+ "license": "Apache-2.0",
1525
+ "peer": true
1526
+ },
1527
  "node_modules/loupe": {
1528
  "version": "3.1.4",
1529
  "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.4.tgz",
 
1587
  "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
1588
  }
1589
  },
1590
+ "node_modules/ndarray": {
1591
+ "version": "1.0.19",
1592
+ "resolved": "https://registry.npmjs.org/ndarray/-/ndarray-1.0.19.tgz",
1593
+ "integrity": "sha512-B4JHA4vdyZU30ELBw3g7/p9bZupyew5a7tX1Y/gGeF2hafrPaQZhgrGQfsvgfYbgdFZjYwuEcnaobeM/WMW+HQ==",
1594
+ "license": "MIT",
1595
+ "dependencies": {
1596
+ "iota-array": "^1.0.0",
1597
+ "is-buffer": "^1.0.2"
1598
+ }
1599
+ },
1600
+ "node_modules/onnxruntime-common": {
1601
+ "version": "1.21.0",
1602
+ "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.21.0.tgz",
1603
+ "integrity": "sha512-Q632iLLrtCAVOTO65dh2+mNbQir/QNTVBG3h/QdZBpns7mZ0RYbLRBgGABPbpU9351AgYy7SJf1WaeVwMrBFPQ==",
1604
+ "license": "MIT",
1605
+ "peer": true
1606
+ },
1607
+ "node_modules/onnxruntime-web": {
1608
+ "version": "1.21.0",
1609
+ "resolved": "https://registry.npmjs.org/onnxruntime-web/-/onnxruntime-web-1.21.0.tgz",
1610
+ "integrity": "sha512-adzOe+7uI7lKz6pQNbAsLMQd2Fq5Jhmoxd8LZjJr8m3KvbFyiYyRxRiC57/XXD+jb18voppjeGAjoZmskXG+7A==",
1611
+ "license": "MIT",
1612
+ "peer": true,
1613
+ "dependencies": {
1614
+ "flatbuffers": "^25.1.24",
1615
+ "guid-typescript": "^1.0.9",
1616
+ "long": "^5.2.3",
1617
+ "onnxruntime-common": "1.21.0",
1618
+ "platform": "^1.3.6",
1619
+ "protobufjs": "^7.2.4"
1620
+ }
1621
+ },
1622
  "node_modules/pathe": {
1623
  "version": "2.0.3",
1624
  "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
 
1656
  "url": "https://github.com/sponsors/jonschlinkert"
1657
  }
1658
  },
1659
+ "node_modules/platform": {
1660
+ "version": "1.3.6",
1661
+ "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz",
1662
+ "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==",
1663
+ "license": "MIT",
1664
+ "peer": true
1665
+ },
1666
  "node_modules/postcss": {
1667
  "version": "8.5.6",
1668
  "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
 
1692
  "node": "^10 || ^12 || >=14"
1693
  }
1694
  },
1695
+ "node_modules/protobufjs": {
1696
+ "version": "7.5.3",
1697
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.3.tgz",
1698
+ "integrity": "sha512-sildjKwVqOI2kmFDiXQ6aEB0fjYTafpEvIBs8tOR8qI4spuL9OPROLVu2qZqi/xgCfsHIwVqlaF8JBjWFHnKbw==",
1699
+ "hasInstallScript": true,
1700
+ "license": "BSD-3-Clause",
1701
+ "peer": true,
1702
+ "dependencies": {
1703
+ "@protobufjs/aspromise": "^1.1.2",
1704
+ "@protobufjs/base64": "^1.1.2",
1705
+ "@protobufjs/codegen": "^2.0.4",
1706
+ "@protobufjs/eventemitter": "^1.1.0",
1707
+ "@protobufjs/fetch": "^1.1.0",
1708
+ "@protobufjs/float": "^1.0.2",
1709
+ "@protobufjs/inquire": "^1.1.0",
1710
+ "@protobufjs/path": "^1.1.2",
1711
+ "@protobufjs/pool": "^1.1.0",
1712
+ "@protobufjs/utf8": "^1.1.0",
1713
+ "@types/node": ">=13.7.0",
1714
+ "long": "^5.0.0"
1715
+ },
1716
+ "engines": {
1717
+ "node": ">=12.0.0"
1718
+ }
1719
+ },
1720
  "node_modules/readdirp": {
1721
  "version": "4.1.2",
1722
  "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
 
1982
  "version": "7.8.0",
1983
  "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz",
1984
  "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==",
 
1985
  "license": "MIT"
1986
  },
1987
  "node_modules/vite": {
 
2208
  "integrity": "sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==",
2209
  "dev": true,
2210
  "license": "MIT"
2211
+ },
2212
+ "node_modules/zod": {
2213
+ "version": "3.25.76",
2214
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
2215
+ "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
2216
+ "license": "MIT",
2217
+ "funding": {
2218
+ "url": "https://github.com/sponsors/colinhacks"
2219
+ }
2220
  }
2221
  }
2222
  }
package.json CHANGED
@@ -25,6 +25,7 @@
25
  "vitest": "^3.2.4"
26
  },
27
  "dependencies": {
 
28
  "dexie": "^4.0.11"
29
  }
30
  }
 
25
  "vitest": "^3.2.4"
26
  },
27
  "dependencies": {
28
+ "@imgly/background-removal": "^1.7.0",
29
  "dexie": "^4.0.11"
30
  }
31
  }
src/lib/components/MonsterGenerator/MonsterGenerator.svelte CHANGED
@@ -4,7 +4,7 @@
4
  import UploadStep from './UploadStep.svelte';
5
  import WorkflowProgress from './WorkflowProgress.svelte';
6
  import MonsterResult from './MonsterResult.svelte';
7
- import { makeWhiteTransparent } from '$lib/utils/imageProcessing';
8
  import { saveMonster } from '$lib/db/monsters';
9
  import { extractPicletMetadata } from '$lib/services/picletMetadata';
10
  import { savePicletInstance } from '$lib/db/piclets';
@@ -259,19 +259,19 @@ Focus on: colors, body shape, eyes, limbs, mouth, and key visual features. Omit
259
  else if (image && image.path) url = image.path;
260
 
261
  if (url) {
262
- // Process the image to make white background transparent
263
- console.log('Processing image for transparency...');
264
  try {
265
- const largeWhiteSegmentThreshold = 0.1; // 10% of image area
266
- const transparentBase64 = await makeWhiteTransparent(url, largeWhiteSegmentThreshold);
267
  state.monsterImage = {
268
  imageUrl: url,
269
  imageData: transparentBase64,
270
  seed: usedSeed,
271
  prompt: state.imagePrompt
272
  };
 
273
  } catch (processError) {
274
- console.error('Failed to process image for transparency:', processError);
275
  // Fallback to original image
276
  state.monsterImage = {
277
  imageUrl: url,
 
4
  import UploadStep from './UploadStep.svelte';
5
  import WorkflowProgress from './WorkflowProgress.svelte';
6
  import MonsterResult from './MonsterResult.svelte';
7
+ import { removeBackground } from '$lib/utils/professionalImageProcessing';
8
  import { saveMonster } from '$lib/db/monsters';
9
  import { extractPicletMetadata } from '$lib/services/picletMetadata';
10
  import { savePicletInstance } from '$lib/db/piclets';
 
259
  else if (image && image.path) url = image.path;
260
 
261
  if (url) {
262
+ // Process the image to remove background using professional AI method
263
+ console.log('Processing image for background removal...');
264
  try {
265
+ const transparentBase64 = await removeBackground(url);
 
266
  state.monsterImage = {
267
  imageUrl: url,
268
  imageData: transparentBase64,
269
  seed: usedSeed,
270
  prompt: state.imagePrompt
271
  };
272
+ console.log('Background removal completed successfully');
273
  } catch (processError) {
274
+ console.error('Failed to process image for background removal:', processError);
275
  // Fallback to original image
276
  state.monsterImage = {
277
  imageUrl: url,
src/lib/utils/imageProcessing.ts DELETED
@@ -1,236 +0,0 @@
1
- /**
2
- * Converts an image URL to a base64 data URL with white background made transparent
3
- * Uses flood-fill from edges to only remove background white, preserving internal white
4
- * Also removes large white segments that exceed the threshold percentage
5
- */
6
- export async function makeWhiteTransparent(imageUrl: string, largeSegmentThreshold: number = 0.013): Promise<string> {
7
- return new Promise((resolve, reject) => {
8
- const img = new Image();
9
- img.crossOrigin = 'anonymous';
10
-
11
- img.onload = () => {
12
- const canvas = document.createElement('canvas');
13
- const ctx = canvas.getContext('2d');
14
-
15
- if (!ctx) {
16
- reject(new Error('Failed to get canvas context'));
17
- return;
18
- }
19
-
20
- canvas.width = img.width;
21
- canvas.height = img.height;
22
-
23
- // Draw the image
24
- ctx.drawImage(img, 0, 0);
25
-
26
- // Get image data
27
- const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
28
- const data = imageData.data;
29
- const width = canvas.width;
30
- const height = canvas.height;
31
-
32
- // Create a mask to track which pixels to make transparent
33
- const mask = new Uint8Array(width * height);
34
-
35
- // Define white threshold with some tolerance
36
- const whiteThreshold = 240;
37
- const tolerance = 20;
38
-
39
- // Helper function to check if a pixel is white-ish
40
- const isWhite = (index: number): boolean => {
41
- const i = index * 4;
42
- const r = data[i];
43
- const g = data[i + 1];
44
- const b = data[i + 2];
45
- return r > whiteThreshold && g > whiteThreshold && b > whiteThreshold;
46
- };
47
-
48
- // Helper function to check if colors are similar
49
- const colorSimilar = (i1: number, i2: number): boolean => {
50
- const idx1 = i1 * 4;
51
- const idx2 = i2 * 4;
52
- return Math.abs(data[idx1] - data[idx2]) < tolerance &&
53
- Math.abs(data[idx1 + 1] - data[idx2 + 1]) < tolerance &&
54
- Math.abs(data[idx1 + 2] - data[idx2 + 2]) < tolerance;
55
- };
56
-
57
- // Flood fill from edges
58
- const queue: number[] = [];
59
-
60
- // Add all edge pixels that are white to the queue
61
- // Top and bottom edges
62
- for (let x = 0; x < width; x++) {
63
- if (isWhite(x)) {
64
- queue.push(x);
65
- mask[x] = 1;
66
- }
67
- const bottomIdx = (height - 1) * width + x;
68
- if (isWhite(bottomIdx)) {
69
- queue.push(bottomIdx);
70
- mask[bottomIdx] = 1;
71
- }
72
- }
73
-
74
- // Left and right edges
75
- for (let y = 1; y < height - 1; y++) {
76
- const leftIdx = y * width;
77
- if (isWhite(leftIdx)) {
78
- queue.push(leftIdx);
79
- mask[leftIdx] = 1;
80
- }
81
- const rightIdx = y * width + width - 1;
82
- if (isWhite(rightIdx)) {
83
- queue.push(rightIdx);
84
- mask[rightIdx] = 1;
85
- }
86
- }
87
-
88
- // Flood fill
89
- while (queue.length > 0) {
90
- const idx = queue.pop()!;
91
- const x = idx % width;
92
- const y = Math.floor(idx / width);
93
-
94
- // Check 4 neighbors
95
- const neighbors = [
96
- { dx: -1, dy: 0 }, // left
97
- { dx: 1, dy: 0 }, // right
98
- { dx: 0, dy: -1 }, // up
99
- { dx: 0, dy: 1 } // down
100
- ];
101
-
102
- for (const { dx, dy } of neighbors) {
103
- const nx = x + dx;
104
- const ny = y + dy;
105
-
106
- if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
107
- const nIdx = ny * width + nx;
108
-
109
- // If not already marked and color is similar to current pixel
110
- if (!mask[nIdx] && isWhite(nIdx) && colorSimilar(idx, nIdx)) {
111
- mask[nIdx] = 1;
112
- queue.push(nIdx);
113
- }
114
- }
115
- }
116
- }
117
-
118
- // Apply transparency based on edge flood fill mask
119
- for (let i = 0; i < mask.length; i++) {
120
- if (mask[i]) {
121
- data[i * 4 + 3] = 0; // Set alpha to 0
122
- }
123
- }
124
-
125
- // Now detect and remove large white segments
126
- const totalPixels = width * height;
127
- const segmentMask = new Uint8Array(width * height);
128
- const visited = new Uint8Array(width * height);
129
-
130
- // Find all white segments using flood fill
131
- for (let y = 0; y < height; y++) {
132
- for (let x = 0; x < width; x++) {
133
- const idx = y * width + x;
134
-
135
- // Skip if already transparent, visited, or not white
136
- if (mask[idx] || visited[idx] || !isWhite(idx)) continue;
137
-
138
- // Start flood fill for this white segment
139
- const segmentPixels: number[] = [];
140
- const segmentQueue: number[] = [idx];
141
- visited[idx] = 1;
142
-
143
- while (segmentQueue.length > 0) {
144
- const currentIdx = segmentQueue.pop()!;
145
- segmentPixels.push(currentIdx);
146
-
147
- const cx = currentIdx % width;
148
- const cy = Math.floor(currentIdx / width);
149
-
150
- // Check 4 neighbors
151
- const neighbors = [
152
- { dx: -1, dy: 0 }, { dx: 1, dy: 0 },
153
- { dx: 0, dy: -1 }, { dx: 0, dy: 1 }
154
- ];
155
-
156
- for (const { dx, dy } of neighbors) {
157
- const nx = cx + dx;
158
- const ny = cy + dy;
159
-
160
- if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
161
- const nIdx = ny * width + nx;
162
-
163
- if (!visited[nIdx] && !mask[nIdx] && isWhite(nIdx) && colorSimilar(currentIdx, nIdx)) {
164
- visited[nIdx] = 1;
165
- segmentQueue.push(nIdx);
166
- }
167
- }
168
- }
169
- }
170
-
171
- // Check if this segment is larger than threshold
172
- const segmentSize = segmentPixels.length / totalPixels;
173
- if (segmentSize > largeSegmentThreshold) {
174
- // Mark all pixels in this segment for removal
175
- for (const pixelIdx of segmentPixels) {
176
- segmentMask[pixelIdx] = 1;
177
- }
178
- }
179
- }
180
- }
181
-
182
- // Apply transparency to large segments
183
- for (let i = 0; i < segmentMask.length; i++) {
184
- if (segmentMask[i]) {
185
- data[i * 4 + 3] = 0; // Set alpha to 0
186
- }
187
- }
188
-
189
- // Put the modified image data back
190
- ctx.putImageData(imageData, 0, 0);
191
-
192
- // Convert to base64
193
- const base64 = canvas.toDataURL('image/png');
194
- resolve(base64);
195
- };
196
-
197
- img.onerror = () => {
198
- reject(new Error('Failed to load image'));
199
- };
200
-
201
- img.src = imageUrl;
202
- });
203
- }
204
-
205
- /**
206
- * Fetches an image from URL and converts it to base64
207
- */
208
- export async function imageUrlToBase64(imageUrl: string): Promise<string> {
209
- return new Promise((resolve, reject) => {
210
- const img = new Image();
211
- img.crossOrigin = 'anonymous';
212
-
213
- img.onload = () => {
214
- const canvas = document.createElement('canvas');
215
- const ctx = canvas.getContext('2d');
216
-
217
- if (!ctx) {
218
- reject(new Error('Failed to get canvas context'));
219
- return;
220
- }
221
-
222
- canvas.width = img.width;
223
- canvas.height = img.height;
224
- ctx.drawImage(img, 0, 0);
225
-
226
- const base64 = canvas.toDataURL('image/png');
227
- resolve(base64);
228
- };
229
-
230
- img.onerror = () => {
231
- reject(new Error('Failed to load image'));
232
- };
233
-
234
- img.src = imageUrl;
235
- });
236
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/utils/professionalImageProcessing.ts ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Professional background removal using industry-standard libraries
3
+ * This replaces the custom algorithm with proven solutions
4
+ */
5
+
6
+ import { removeBackground as removeBackgroundLib } from '@imgly/background-removal';
7
+
8
+ // Type definitions for the background removal library
9
+ interface BackgroundRemovalConfig {
10
+ model?: 'small' | 'medium' | 'large';
11
+ output?: {
12
+ format?: string;
13
+ quality?: number;
14
+ };
15
+ debug?: boolean;
16
+ }
17
+
18
+ /**
19
+ * Remove background using AI-powered background removal
20
+ * This is the preferred method for high-quality results
21
+ */
22
+ export async function removeBackgroundAI(imageUrl: string): Promise<string> {
23
+ try {
24
+ // Fetch the image as a blob
25
+ const response = await fetch(imageUrl);
26
+ if (!response.ok) {
27
+ throw new Error(`Failed to fetch image: ${response.statusText}`);
28
+ }
29
+ const imageBlob = await response.blob();
30
+
31
+ // Remove background using AI (using default configuration for simplicity)
32
+ const resultBlob = await removeBackgroundLib(imageBlob);
33
+
34
+ // Convert result blob to data URL
35
+ return new Promise((resolve, reject) => {
36
+ const reader = new FileReader();
37
+ reader.onload = () => resolve(reader.result as string);
38
+ reader.onerror = () => reject(new Error('Failed to convert result to data URL'));
39
+ reader.readAsDataURL(resultBlob);
40
+ });
41
+
42
+ } catch (error) {
43
+ console.error('AI background removal failed:', error);
44
+ throw new Error(`Background removal failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Simple fallback method for basic white background removal
50
+ * Use this when the AI method is not available
51
+ */
52
+ export async function removeWhiteBackgroundSimple(imageUrl: string): Promise<string> {
53
+ return new Promise((resolve, reject) => {
54
+ const img = new Image();
55
+ img.crossOrigin = 'anonymous';
56
+
57
+ img.onload = () => {
58
+ const canvas = document.createElement('canvas');
59
+ const ctx = canvas.getContext('2d');
60
+
61
+ if (!ctx) {
62
+ reject(new Error('Failed to get canvas context'));
63
+ return;
64
+ }
65
+
66
+ canvas.width = img.width;
67
+ canvas.height = img.height;
68
+ ctx.drawImage(img, 0, 0);
69
+
70
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
71
+ const data = imageData.data;
72
+
73
+ // Simple white background removal
74
+ const whiteThreshold = 240;
75
+ for (let i = 0; i < data.length; i += 4) {
76
+ const r = data[i];
77
+ const g = data[i + 1];
78
+ const b = data[i + 2];
79
+
80
+ // If pixel is close to white, make it transparent
81
+ if (r > whiteThreshold && g > whiteThreshold && b > whiteThreshold) {
82
+ data[i + 3] = 0; // Set alpha to 0
83
+ }
84
+ }
85
+
86
+ ctx.putImageData(imageData, 0, 0);
87
+ resolve(canvas.toDataURL('image/png'));
88
+ };
89
+
90
+ img.onerror = () => {
91
+ reject(new Error('Failed to load image'));
92
+ };
93
+
94
+ img.src = imageUrl;
95
+ });
96
+ }
97
+
98
+ /**
99
+ * Main function that tries AI method first, then falls back to simple method
100
+ * This provides the best results while maintaining compatibility
101
+ */
102
+ export async function removeBackground(imageUrl: string): Promise<string> {
103
+ try {
104
+ // Try AI method first
105
+ return await removeBackgroundAI(imageUrl);
106
+ } catch (aiError) {
107
+ console.warn('AI background removal failed, falling back to simple method:', aiError);
108
+
109
+ try {
110
+ // Fallback to simple method
111
+ return await removeWhiteBackgroundSimple(imageUrl);
112
+ } catch (fallbackError) {
113
+ console.error('All background removal methods failed:', fallbackError);
114
+ throw new Error('Background removal failed with all methods');
115
+ }
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Check if the AI background removal library is available
121
+ */
122
+ export async function isAIBackgroundRemovalAvailable(): Promise<boolean> {
123
+ return true; // Library is now installed as a dependency
124
+ }
125
+
126
+ /**
127
+ * Batch process multiple images with progress callback
128
+ */
129
+ export async function removeBackgroundBatch(
130
+ imageUrls: string[],
131
+ onProgress?: (completed: number, total: number, currentImage: string) => void
132
+ ): Promise<{ url: string; result?: string; error?: string }[]> {
133
+ const results: { url: string; result?: string; error?: string }[] = [];
134
+
135
+ for (let i = 0; i < imageUrls.length; i++) {
136
+ const imageUrl = imageUrls[i];
137
+
138
+ try {
139
+ const result = await removeBackground(imageUrl);
140
+ results.push({ url: imageUrl, result });
141
+ } catch (error) {
142
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
143
+ results.push({ url: imageUrl, error: errorMessage });
144
+ }
145
+
146
+ if (onProgress) {
147
+ onProgress(i + 1, imageUrls.length, imageUrl);
148
+ }
149
+ }
150
+
151
+ return results;
152
+ }