@slithy/prim-lib 0.7.0 → 0.8.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.d.ts CHANGED
@@ -24,9 +24,12 @@ interface ShapeImageData {
24
24
  interface ShapeInterface {
25
25
  bbox: Bbox;
26
26
  tonalRange?: [number, number];
27
+ invertTonal?: boolean;
27
28
  saturationRange?: [number, number];
29
+ invertSaturation?: boolean;
28
30
  hueCenter?: number;
29
31
  hueTolerance?: number;
32
+ invertHue?: boolean;
30
33
  /** cfg is rarely used by implementations; accepts Partial to keep call sites flexible. */
31
34
  mutate(cfg?: Partial<Cfg>): ShapeInterface;
32
35
  toSVG(): SVGElement | undefined;
@@ -310,9 +313,12 @@ interface NGonOptions {
310
313
  sizeRange?: [number, number];
311
314
  mutationScale?: number;
312
315
  tonalRange?: [number, number];
316
+ invertTonal?: boolean;
313
317
  saturationRange?: [number, number];
318
+ invertSaturation?: boolean;
314
319
  hueCenter?: number;
315
320
  hueTolerance?: number;
321
+ invertHue?: boolean;
316
322
  }
317
323
  declare function makeNGon(opts: NGonOptions): new (w: number, h: number) => ShapeInterface;
318
324
  interface RectOptions {
@@ -322,18 +328,24 @@ interface RectOptions {
322
328
  rotatable?: boolean;
323
329
  mutationScale?: number;
324
330
  tonalRange?: [number, number];
331
+ invertTonal?: boolean;
325
332
  saturationRange?: [number, number];
333
+ invertSaturation?: boolean;
326
334
  hueCenter?: number;
327
335
  hueTolerance?: number;
336
+ invertHue?: boolean;
328
337
  }
329
338
  declare function makeRect(opts?: Partial<RectOptions>): new (w: number, h: number) => ShapeInterface;
330
339
  interface CircleOptions {
331
340
  sizeRange?: [number, number];
332
341
  mutationScale?: number;
333
342
  tonalRange?: [number, number];
343
+ invertTonal?: boolean;
334
344
  saturationRange?: [number, number];
345
+ invertSaturation?: boolean;
335
346
  hueCenter?: number;
336
347
  hueTolerance?: number;
348
+ invertHue?: boolean;
337
349
  }
338
350
  declare function makeCircle(opts?: Partial<CircleOptions>): new (w: number, h: number) => ShapeInterface;
339
351
  interface EllipseOptions {
@@ -342,9 +354,12 @@ interface EllipseOptions {
342
354
  aspectRatio?: number;
343
355
  mutationScale?: number;
344
356
  tonalRange?: [number, number];
357
+ invertTonal?: boolean;
345
358
  saturationRange?: [number, number];
359
+ invertSaturation?: boolean;
346
360
  hueCenter?: number;
347
361
  hueTolerance?: number;
362
+ invertHue?: boolean;
348
363
  }
349
364
  declare function makeEllipse(opts?: Partial<EllipseOptions>): new (w: number, h: number) => ShapeInterface;
350
365
  interface GlyphOptions {
@@ -353,9 +368,12 @@ interface GlyphOptions {
353
368
  sizeRange?: [number, number];
354
369
  mutationScale?: number;
355
370
  tonalRange?: [number, number];
371
+ invertTonal?: boolean;
356
372
  saturationRange?: [number, number];
373
+ invertSaturation?: boolean;
357
374
  hueCenter?: number;
358
375
  hueTolerance?: number;
376
+ invertHue?: boolean;
359
377
  }
360
378
  declare function makeGlyph(opts?: Partial<GlyphOptions>): new (w: number, h: number) => ShapeInterface;
361
379
  declare class Debug extends Shape {
package/dist/index.js CHANGED
@@ -382,7 +382,7 @@ var Step = class _Step {
382
382
  compute(state) {
383
383
  const pixels = state.canvas.node.width * state.canvas.node.height;
384
384
  const offset = this.shape.bbox;
385
- const { tonalRange, saturationRange, hueCenter, hueTolerance } = this.shape;
385
+ const { tonalRange, invertTonal, saturationRange, invertSaturation, hueCenter, hueTolerance, invertHue } = this.shape;
386
386
  if (tonalRange || saturationRange || hueCenter !== void 0 && hueTolerance !== void 0) {
387
387
  const { left, top, width, height } = offset;
388
388
  const targetData = state.target.getImageData();
@@ -405,20 +405,25 @@ var Step = class _Step {
405
405
  if (count > 0) {
406
406
  if (tonalRange) {
407
407
  const luma = (0.299 * rSum + 0.587 * gSum + 0.114 * bSum) / count;
408
- if (luma < tonalRange[0] || luma > tonalRange[1]) {
408
+ const inRange = luma >= tonalRange[0] && luma <= tonalRange[1];
409
+ if (invertTonal ? inRange : !inRange) {
409
410
  this.distance = Infinity;
410
411
  return Promise.resolve(this);
411
412
  }
412
413
  }
413
414
  if (saturationRange || hueCenter !== void 0 && hueTolerance !== void 0) {
414
415
  const [h, s] = rgbToHsl(rSum / count, gSum / count, bSum / count);
415
- if (saturationRange && (s < saturationRange[0] || s > saturationRange[1])) {
416
- this.distance = Infinity;
417
- return Promise.resolve(this);
416
+ if (saturationRange) {
417
+ const inRange = s >= saturationRange[0] && s <= saturationRange[1];
418
+ if (invertSaturation ? inRange : !inRange) {
419
+ this.distance = Infinity;
420
+ return Promise.resolve(this);
421
+ }
418
422
  }
419
423
  if (hueCenter !== void 0 && hueTolerance !== void 0) {
420
424
  const diff = Math.abs((h - hueCenter + 180 + 360) % 360 - 180);
421
- if (diff > hueTolerance) {
425
+ const inRange = diff <= hueTolerance;
426
+ if (invertHue ? inRange : !inRange) {
422
427
  this.distance = Infinity;
423
428
  return Promise.resolve(this);
424
429
  }
@@ -1026,12 +1031,15 @@ function makeNGon(opts) {
1026
1031
  static {
1027
1032
  __name(this, "NGonRegular");
1028
1033
  }
1029
- static _ngonOpts = { sides, regular: true, rotatable, noise, sizeRange, mutationScale, startAngle, tonalRange: opts.tonalRange, saturationRange: opts.saturationRange, hueCenter: opts.hueCenter, hueTolerance: opts.hueTolerance };
1034
+ static _ngonOpts = { sides, regular: true, rotatable, noise, sizeRange, mutationScale, startAngle, tonalRange: opts.tonalRange, invertTonal: opts.invertTonal, saturationRange: opts.saturationRange, invertSaturation: opts.invertSaturation, hueCenter: opts.hueCenter, hueTolerance: opts.hueTolerance, invertHue: opts.invertHue };
1030
1035
  static _shapeSpec = { f: "ngon", o: NGonRegular._ngonOpts };
1031
1036
  tonalRange;
1037
+ invertTonal;
1032
1038
  saturationRange;
1039
+ invertSaturation;
1033
1040
  hueCenter;
1034
1041
  hueTolerance;
1042
+ invertHue;
1035
1043
  center;
1036
1044
  r;
1037
1045
  angle;
@@ -1040,9 +1048,12 @@ function makeNGon(opts) {
1040
1048
  constructor(w, h) {
1041
1049
  super(w, h);
1042
1050
  this.tonalRange = opts.tonalRange;
1051
+ this.invertTonal = opts.invertTonal;
1043
1052
  this.saturationRange = opts.saturationRange;
1053
+ this.invertSaturation = opts.invertSaturation;
1044
1054
  this.hueCenter = opts.hueCenter;
1045
1055
  this.hueTolerance = opts.hueTolerance;
1056
+ this.invertHue = opts.invertHue;
1046
1057
  this.center = Shape.randomPoint(w, h);
1047
1058
  this.r = Math.max(1, sizeRange[0] + ~~(Math.random() * (sizeRange[1] - sizeRange[0])));
1048
1059
  this.angle = rotatable ? Math.random() * (2 * Math.PI / sides) : startAngle;
@@ -1138,19 +1149,25 @@ function makeNGon(opts) {
1138
1149
  static {
1139
1150
  __name(this, "NGonIrregular");
1140
1151
  }
1141
- static _ngonOpts = { sides, regular: false, convex, sizeRange, mutationScale, tonalRange: opts.tonalRange, saturationRange: opts.saturationRange, hueCenter: opts.hueCenter, hueTolerance: opts.hueTolerance };
1152
+ static _ngonOpts = { sides, regular: false, convex, sizeRange, mutationScale, tonalRange: opts.tonalRange, invertTonal: opts.invertTonal, saturationRange: opts.saturationRange, invertSaturation: opts.invertSaturation, hueCenter: opts.hueCenter, hueTolerance: opts.hueTolerance, invertHue: opts.invertHue };
1142
1153
  static _shapeSpec = { f: "ngon", o: NGonIrregular._ngonOpts };
1143
1154
  tonalRange;
1155
+ invertTonal;
1144
1156
  saturationRange;
1157
+ invertSaturation;
1145
1158
  hueCenter;
1146
1159
  hueTolerance;
1160
+ invertHue;
1147
1161
  points;
1148
1162
  constructor(w, h) {
1149
1163
  super(w, h);
1150
1164
  this.tonalRange = opts.tonalRange;
1165
+ this.invertTonal = opts.invertTonal;
1151
1166
  this.saturationRange = opts.saturationRange;
1167
+ this.invertSaturation = opts.invertSaturation;
1152
1168
  this.hueCenter = opts.hueCenter;
1153
1169
  this.hueTolerance = opts.hueTolerance;
1170
+ this.invertHue = opts.invertHue;
1154
1171
  const first = Shape.randomPoint(w, h);
1155
1172
  this.points = [first];
1156
1173
  for (let i = 1; i < sides; i++) {
@@ -1222,12 +1239,15 @@ function makeRect(opts) {
1222
1239
  static {
1223
1240
  __name(this, "Rect");
1224
1241
  }
1225
- static _rectOpts = { widthRange, heightRange, aspectRatio, rotatable, mutationScale, tonalRange: opts?.tonalRange, saturationRange: opts?.saturationRange, hueCenter: opts?.hueCenter, hueTolerance: opts?.hueTolerance };
1242
+ static _rectOpts = { widthRange, heightRange, aspectRatio, rotatable, mutationScale, tonalRange: opts?.tonalRange, invertTonal: opts?.invertTonal, saturationRange: opts?.saturationRange, invertSaturation: opts?.invertSaturation, hueCenter: opts?.hueCenter, hueTolerance: opts?.hueTolerance, invertHue: opts?.invertHue };
1226
1243
  static _shapeSpec = { f: "rect", o: Rect._rectOpts };
1227
1244
  tonalRange;
1245
+ invertTonal;
1228
1246
  saturationRange;
1247
+ invertSaturation;
1229
1248
  hueCenter;
1230
1249
  hueTolerance;
1250
+ invertHue;
1231
1251
  center;
1232
1252
  hw;
1233
1253
  hh;
@@ -1235,9 +1255,12 @@ function makeRect(opts) {
1235
1255
  constructor(w, h) {
1236
1256
  super(w, h);
1237
1257
  this.tonalRange = opts?.tonalRange;
1258
+ this.invertTonal = opts?.invertTonal;
1238
1259
  this.saturationRange = opts?.saturationRange;
1260
+ this.invertSaturation = opts?.invertSaturation;
1239
1261
  this.hueCenter = opts?.hueCenter;
1240
1262
  this.hueTolerance = opts?.hueTolerance;
1263
+ this.invertHue = opts?.invertHue;
1241
1264
  this.center = Shape.randomPoint(w, h);
1242
1265
  this.hw = widthRange[0] + ~~(Math.random() * (widthRange[1] - widthRange[0]));
1243
1266
  if (aspectRatio !== void 0) {
@@ -1350,20 +1373,26 @@ function makeCircle(opts) {
1350
1373
  static {
1351
1374
  __name(this, "MadeCircle");
1352
1375
  }
1353
- static _circleOpts = { sizeRange, mutationScale, tonalRange: opts?.tonalRange, saturationRange: opts?.saturationRange, hueCenter: opts?.hueCenter, hueTolerance: opts?.hueTolerance };
1376
+ static _circleOpts = { sizeRange, mutationScale, tonalRange: opts?.tonalRange, invertTonal: opts?.invertTonal, saturationRange: opts?.saturationRange, invertSaturation: opts?.invertSaturation, hueCenter: opts?.hueCenter, hueTolerance: opts?.hueTolerance, invertHue: opts?.invertHue };
1354
1377
  static _shapeSpec = { f: "circle", o: MadeCircle._circleOpts };
1355
1378
  tonalRange;
1379
+ invertTonal;
1356
1380
  saturationRange;
1381
+ invertSaturation;
1357
1382
  hueCenter;
1358
1383
  hueTolerance;
1384
+ invertHue;
1359
1385
  center;
1360
1386
  r;
1361
1387
  constructor(w, h) {
1362
1388
  super(w, h);
1363
1389
  this.tonalRange = opts?.tonalRange;
1390
+ this.invertTonal = opts?.invertTonal;
1364
1391
  this.saturationRange = opts?.saturationRange;
1392
+ this.invertSaturation = opts?.invertSaturation;
1365
1393
  this.hueCenter = opts?.hueCenter;
1366
1394
  this.hueTolerance = opts?.hueTolerance;
1395
+ this.invertHue = opts?.invertHue;
1367
1396
  this.center = Shape.randomPoint(w, h);
1368
1397
  this.r = Math.max(1, sizeRange[0] + ~~(Math.random() * (sizeRange[1] - sizeRange[0])));
1369
1398
  this.computeBbox();
@@ -1424,21 +1453,27 @@ function makeEllipse(opts) {
1424
1453
  static {
1425
1454
  __name(this, "MadeEllipse");
1426
1455
  }
1427
- static _ellipseOpts = { rxRange, ryRange, aspectRatio, mutationScale, tonalRange: opts?.tonalRange, saturationRange: opts?.saturationRange, hueCenter: opts?.hueCenter, hueTolerance: opts?.hueTolerance };
1456
+ static _ellipseOpts = { rxRange, ryRange, aspectRatio, mutationScale, tonalRange: opts?.tonalRange, invertTonal: opts?.invertTonal, saturationRange: opts?.saturationRange, invertSaturation: opts?.invertSaturation, hueCenter: opts?.hueCenter, hueTolerance: opts?.hueTolerance, invertHue: opts?.invertHue };
1428
1457
  static _shapeSpec = { f: "ellipse", o: MadeEllipse._ellipseOpts };
1429
1458
  tonalRange;
1459
+ invertTonal;
1430
1460
  saturationRange;
1461
+ invertSaturation;
1431
1462
  hueCenter;
1432
1463
  hueTolerance;
1464
+ invertHue;
1433
1465
  center;
1434
1466
  rx;
1435
1467
  ry;
1436
1468
  constructor(w, h) {
1437
1469
  super(w, h);
1438
1470
  this.tonalRange = opts?.tonalRange;
1471
+ this.invertTonal = opts?.invertTonal;
1439
1472
  this.saturationRange = opts?.saturationRange;
1473
+ this.invertSaturation = opts?.invertSaturation;
1440
1474
  this.hueCenter = opts?.hueCenter;
1441
1475
  this.hueTolerance = opts?.hueTolerance;
1476
+ this.invertHue = opts?.invertHue;
1442
1477
  this.center = Shape.randomPoint(w, h);
1443
1478
  this.rx = Math.max(1, rxRange[0] + ~~(Math.random() * (rxRange[1] - rxRange[0])));
1444
1479
  this.ry = aspectRatio !== void 0 ? Math.max(1, Math.round(this.rx / aspectRatio)) : Math.max(1, ryRange[0] + ~~(Math.random() * (ryRange[1] - ryRange[0])));
@@ -1510,20 +1545,26 @@ function makeGlyph(opts) {
1510
1545
  static {
1511
1546
  __name(this, "MadeGlyph");
1512
1547
  }
1513
- static _glyphOpts = { char, fontFamily, sizeRange, mutationScale, tonalRange: opts?.tonalRange, saturationRange: opts?.saturationRange, hueCenter: opts?.hueCenter, hueTolerance: opts?.hueTolerance };
1548
+ static _glyphOpts = { char, fontFamily, sizeRange, mutationScale, tonalRange: opts?.tonalRange, invertTonal: opts?.invertTonal, saturationRange: opts?.saturationRange, invertSaturation: opts?.invertSaturation, hueCenter: opts?.hueCenter, hueTolerance: opts?.hueTolerance, invertHue: opts?.invertHue };
1514
1549
  static _shapeSpec = { f: "glyph", o: MadeGlyph._glyphOpts };
1515
1550
  tonalRange;
1551
+ invertTonal;
1516
1552
  saturationRange;
1553
+ invertSaturation;
1517
1554
  hueCenter;
1518
1555
  hueTolerance;
1556
+ invertHue;
1519
1557
  center;
1520
1558
  fontSize;
1521
1559
  constructor(w, h) {
1522
1560
  super(w, h);
1523
1561
  this.tonalRange = opts?.tonalRange;
1562
+ this.invertTonal = opts?.invertTonal;
1524
1563
  this.saturationRange = opts?.saturationRange;
1564
+ this.invertSaturation = opts?.invertSaturation;
1525
1565
  this.hueCenter = opts?.hueCenter;
1526
1566
  this.hueTolerance = opts?.hueTolerance;
1567
+ this.invertHue = opts?.invertHue;
1527
1568
  this.center = Shape.randomPoint(w, h);
1528
1569
  this.fontSize = Math.max(sizeRange[0], sizeRange[0] + ~~(Math.random() * (sizeRange[1] - sizeRange[0])));
1529
1570
  this.computeBbox();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slithy/prim-lib",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Core engine for primitive-based image reconstruction.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -13,14 +13,24 @@
13
13
  "dist"
14
14
  ],
15
15
  "sideEffects": false,
16
+ "scripts": {
17
+ "clean": "rm -rf dist",
18
+ "prepack": "rm -rf dist && tsup src/index.ts --format esm --dts --keep-names",
19
+ "build": "rm -rf dist && tsup src/index.ts --format esm --dts --keep-names",
20
+ "dev": "tsup src/index.ts --format esm --watch --keep-names",
21
+ "typecheck": "tsc --noEmit",
22
+ "lint": "eslint .",
23
+ "test": "vitest run",
24
+ "test:watch": "vitest"
25
+ },
16
26
  "devDependencies": {
27
+ "@slithy/eslint-config": "workspace:*",
28
+ "@slithy/tsconfig": "workspace:*",
17
29
  "@vitest/coverage-v8": "^4.1.2",
18
30
  "jsdom": "^29.0.1",
19
31
  "tsup": "^8",
20
32
  "typescript": "^5",
21
- "vitest": "^4.1.2",
22
- "@slithy/eslint-config": "0.0.0",
23
- "@slithy/tsconfig": "0.0.0"
33
+ "vitest": "^4.1.2"
24
34
  },
25
35
  "author": {
26
36
  "name": "Matthew Campagna",
@@ -41,14 +51,5 @@
41
51
  },
42
52
  "publishConfig": {
43
53
  "access": "public"
44
- },
45
- "scripts": {
46
- "clean": "rm -rf dist",
47
- "build": "rm -rf dist && tsup src/index.ts --format esm --dts --keep-names",
48
- "dev": "tsup src/index.ts --format esm --watch --keep-names",
49
- "typecheck": "tsc --noEmit",
50
- "lint": "eslint .",
51
- "test": "vitest run",
52
- "test:watch": "vitest"
53
54
  }
54
- }
55
+ }