@pallasoft/ps-file-components 1.3.0 → 1.4.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.
Files changed (154) hide show
  1. package/dist/components/ps-document-scanner-loader.d.ts +1 -0
  2. package/dist/components/ps-document-scanner-loader.js +40 -0
  3. package/dist/components/ps-document-scanner-sheet.d.ts +2 -0
  4. package/dist/components/ps-document-scanner-sheet.js +138 -0
  5. package/dist/components/ps-document-scanner.d.ts +2 -0
  6. package/dist/components/ps-document-scanner.js +17 -0
  7. package/dist/components/ps-file-viewer-pane.d.ts +2 -0
  8. package/dist/components/ps-file-viewer-pane.js +39 -0
  9. package/dist/components/ps-scan-camera-view.d.ts +17 -0
  10. package/dist/components/ps-scan-camera-view.js +27 -0
  11. package/dist/components/ps-scan-crop-editor.d.ts +13 -0
  12. package/dist/components/ps-scan-crop-editor.js +53 -0
  13. package/dist/components/ps-scan-icon-button.d.ts +10 -0
  14. package/dist/components/ps-scan-icon-button.js +7 -0
  15. package/dist/components/ps-scan-page-list.d.ts +12 -0
  16. package/dist/components/ps-scan-page-list.js +23 -0
  17. package/dist/components/ps-scan-review.d.ts +23 -0
  18. package/dist/components/ps-scan-review.js +20 -0
  19. package/dist/constants/ps-document-scanner-labels.d.ts +50 -0
  20. package/dist/constants/ps-document-scanner-labels.js +53 -0
  21. package/dist/constants/ps-scan-camera-status.d.ts +7 -0
  22. package/dist/constants/ps-scan-camera-status.js +9 -0
  23. package/dist/constants/ps-scan-config.d.ts +31 -0
  24. package/dist/constants/ps-scan-config.js +34 -0
  25. package/dist/constants/ps-scan-corner-order.d.ts +1 -0
  26. package/dist/constants/ps-scan-corner-order.js +4 -0
  27. package/dist/constants/ps-scan-filter.d.ts +7 -0
  28. package/dist/constants/ps-scan-filter.js +9 -0
  29. package/dist/constants/ps-scan-output-format.d.ts +5 -0
  30. package/dist/constants/ps-scan-output-format.js +7 -0
  31. package/dist/constants/ps-scan-step.d.ts +6 -0
  32. package/dist/constants/ps-scan-step.js +8 -0
  33. package/dist/esm/components/ps-document-scanner-loader.js +4 -0
  34. package/dist/esm/components/ps-document-scanner-sheet.js +134 -0
  35. package/dist/esm/components/ps-document-scanner.js +13 -0
  36. package/dist/esm/components/ps-file-viewer-pane.js +35 -0
  37. package/dist/esm/components/ps-scan-camera-view.js +23 -0
  38. package/dist/esm/components/ps-scan-crop-editor.js +49 -0
  39. package/dist/esm/components/ps-scan-icon-button.js +3 -0
  40. package/dist/esm/components/ps-scan-page-list.js +19 -0
  41. package/dist/esm/components/ps-scan-review.js +16 -0
  42. package/dist/esm/constants/ps-document-scanner-labels.js +50 -0
  43. package/dist/esm/constants/ps-scan-camera-status.js +6 -0
  44. package/dist/esm/constants/ps-scan-config.js +31 -0
  45. package/dist/esm/constants/ps-scan-corner-order.js +1 -0
  46. package/dist/esm/constants/ps-scan-filter.js +6 -0
  47. package/dist/esm/constants/ps-scan-output-format.js +4 -0
  48. package/dist/esm/constants/ps-scan-step.js +5 -0
  49. package/dist/esm/hooks/use-ps-focus-trap.js +45 -0
  50. package/dist/esm/hooks/use-ps-scan-camera.js +62 -0
  51. package/dist/esm/hooks/use-ps-scan-pages.js +62 -0
  52. package/dist/esm/hooks/use-ps-scan-previews.js +57 -0
  53. package/dist/esm/index.js +7 -0
  54. package/dist/esm/models/ps-document-scanner-props.js +1 -0
  55. package/dist/esm/models/ps-document-scanner-sheet-props.js +1 -0
  56. package/dist/esm/models/ps-file-viewer-pane-props.js +1 -0
  57. package/dist/esm/models/ps-scan-added-page.js +1 -0
  58. package/dist/esm/models/ps-scan-camera-session.js +1 -0
  59. package/dist/esm/models/ps-scan-decoded-image.js +1 -0
  60. package/dist/esm/models/ps-scan-levels.js +1 -0
  61. package/dist/esm/models/ps-scan-output-options.js +1 -0
  62. package/dist/esm/models/ps-scan-page.js +1 -0
  63. package/dist/esm/models/ps-scan-pdf-page.js +1 -0
  64. package/dist/esm/models/ps-scan-prepared.js +1 -0
  65. package/dist/esm/models/ps-scan-quad.js +1 -0
  66. package/dist/esm/models/ps-scan-raster.js +1 -0
  67. package/dist/esm/models/ps-scan-rendered-page.js +1 -0
  68. package/dist/esm/services/ps-scan-camera-service.js +50 -0
  69. package/dist/esm/services/ps-scan-canvas-service.js +46 -0
  70. package/dist/esm/services/ps-scan-edge-service.js +156 -0
  71. package/dist/esm/services/ps-scan-enhance-service.js +97 -0
  72. package/dist/esm/services/ps-scan-file-name-service.js +25 -0
  73. package/dist/esm/services/ps-scan-geometry-service.js +96 -0
  74. package/dist/esm/services/ps-scan-homography-service.js +46 -0
  75. package/dist/esm/services/ps-scan-hull-service.js +59 -0
  76. package/dist/esm/services/ps-scan-image-filter-service.js +52 -0
  77. package/dist/esm/services/ps-scan-order-service.js +13 -0
  78. package/dist/esm/services/ps-scan-output-service.js +24 -0
  79. package/dist/esm/services/ps-scan-pdf-service.js +56 -0
  80. package/dist/esm/services/ps-scan-pipeline-service.js +40 -0
  81. package/dist/esm/services/ps-scan-raster-service.js +67 -0
  82. package/dist/esm/services/ps-scan-template-service.js +5 -0
  83. package/dist/esm/services/ps-scan-warp-service.js +35 -0
  84. package/dist/hooks/use-ps-focus-trap.d.ts +2 -0
  85. package/dist/hooks/use-ps-focus-trap.js +49 -0
  86. package/dist/hooks/use-ps-scan-camera.d.ts +9 -0
  87. package/dist/hooks/use-ps-scan-camera.js +66 -0
  88. package/dist/hooks/use-ps-scan-pages.d.ts +12 -0
  89. package/dist/hooks/use-ps-scan-pages.js +66 -0
  90. package/dist/hooks/use-ps-scan-previews.d.ts +2 -0
  91. package/dist/hooks/use-ps-scan-previews.js +61 -0
  92. package/dist/index.d.ts +7 -0
  93. package/dist/index.js +7 -0
  94. package/dist/models/ps-document-scanner-props.d.ts +15 -0
  95. package/dist/models/ps-document-scanner-props.js +2 -0
  96. package/dist/models/ps-document-scanner-sheet-props.d.ts +13 -0
  97. package/dist/models/ps-document-scanner-sheet-props.js +2 -0
  98. package/dist/models/ps-file-viewer-pane-props.d.ts +12 -0
  99. package/dist/models/ps-file-viewer-pane-props.js +2 -0
  100. package/dist/models/ps-scan-added-page.d.ts +5 -0
  101. package/dist/models/ps-scan-added-page.js +2 -0
  102. package/dist/models/ps-scan-camera-session.d.ts +5 -0
  103. package/dist/models/ps-scan-camera-session.js +2 -0
  104. package/dist/models/ps-scan-decoded-image.d.ts +6 -0
  105. package/dist/models/ps-scan-decoded-image.js +2 -0
  106. package/dist/models/ps-scan-levels.d.ts +4 -0
  107. package/dist/models/ps-scan-levels.js +2 -0
  108. package/dist/models/ps-scan-output-options.d.ts +7 -0
  109. package/dist/models/ps-scan-output-options.js +2 -0
  110. package/dist/models/ps-scan-page.d.ts +12 -0
  111. package/dist/models/ps-scan-page.js +2 -0
  112. package/dist/models/ps-scan-pdf-page.d.ts +5 -0
  113. package/dist/models/ps-scan-pdf-page.js +2 -0
  114. package/dist/models/ps-scan-prepared.d.ts +7 -0
  115. package/dist/models/ps-scan-prepared.js +2 -0
  116. package/dist/models/ps-scan-quad.d.ts +2 -0
  117. package/dist/models/ps-scan-quad.js +2 -0
  118. package/dist/models/ps-scan-raster.d.ts +5 -0
  119. package/dist/models/ps-scan-raster.js +2 -0
  120. package/dist/models/ps-scan-rendered-page.d.ts +5 -0
  121. package/dist/models/ps-scan-rendered-page.js +2 -0
  122. package/dist/services/ps-scan-camera-service.d.ts +10 -0
  123. package/dist/services/ps-scan-camera-service.js +54 -0
  124. package/dist/services/ps-scan-canvas-service.d.ts +8 -0
  125. package/dist/services/ps-scan-canvas-service.js +50 -0
  126. package/dist/services/ps-scan-edge-service.d.ts +9 -0
  127. package/dist/services/ps-scan-edge-service.js +160 -0
  128. package/dist/services/ps-scan-enhance-service.d.ts +9 -0
  129. package/dist/services/ps-scan-enhance-service.js +101 -0
  130. package/dist/services/ps-scan-file-name-service.d.ts +6 -0
  131. package/dist/services/ps-scan-file-name-service.js +29 -0
  132. package/dist/services/ps-scan-geometry-service.d.ts +18 -0
  133. package/dist/services/ps-scan-geometry-service.js +100 -0
  134. package/dist/services/ps-scan-homography-service.d.ts +7 -0
  135. package/dist/services/ps-scan-homography-service.js +50 -0
  136. package/dist/services/ps-scan-hull-service.d.ts +6 -0
  137. package/dist/services/ps-scan-hull-service.js +63 -0
  138. package/dist/services/ps-scan-image-filter-service.d.ts +6 -0
  139. package/dist/services/ps-scan-image-filter-service.js +56 -0
  140. package/dist/services/ps-scan-order-service.d.ts +4 -0
  141. package/dist/services/ps-scan-order-service.js +17 -0
  142. package/dist/services/ps-scan-output-service.d.ts +5 -0
  143. package/dist/services/ps-scan-output-service.js +28 -0
  144. package/dist/services/ps-scan-pdf-service.d.ts +5 -0
  145. package/dist/services/ps-scan-pdf-service.js +60 -0
  146. package/dist/services/ps-scan-pipeline-service.d.ts +10 -0
  147. package/dist/services/ps-scan-pipeline-service.js +44 -0
  148. package/dist/services/ps-scan-raster-service.d.ts +6 -0
  149. package/dist/services/ps-scan-raster-service.js +71 -0
  150. package/dist/services/ps-scan-template-service.d.ts +3 -0
  151. package/dist/services/ps-scan-template-service.js +9 -0
  152. package/dist/services/ps-scan-warp-service.d.ts +6 -0
  153. package/dist/services/ps-scan-warp-service.js +39 -0
  154. package/package.json +9 -6
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsScanOutputService = void 0;
4
+ const ps_scan_output_format_1 = require("../constants/ps-scan-output-format");
5
+ const ps_scan_file_name_service_1 = require("./ps-scan-file-name-service");
6
+ const ps_scan_pdf_service_1 = require("./ps-scan-pdf-service");
7
+ const ps_scan_pipeline_service_1 = require("./ps-scan-pipeline-service");
8
+ class PsScanOutputService {
9
+ static async build(pages, options) {
10
+ const rendered = [];
11
+ for (const page of pages)
12
+ rendered.push(await ps_scan_pipeline_service_1.PsScanPipelineService.render(page, options.maxDimension, options.jpegQuality));
13
+ const type = ps_scan_file_name_service_1.PsScanFileNameService.mimeType(options.format);
14
+ if (options.format === ps_scan_output_format_1.PsScanOutputFormat.Jpeg)
15
+ return rendered.map((item, index) => new File([item.blob], ps_scan_file_name_service_1.PsScanFileNameService.build(options.fileName, options.format, index, rendered.length), { type }));
16
+ const jpegs = await Promise.all(rendered.map(async (item) => ({
17
+ height: item.height,
18
+ jpeg: new Uint8Array(await item.blob.arrayBuffer()),
19
+ width: item.width,
20
+ })));
21
+ return [
22
+ new File([ps_scan_pdf_service_1.PsScanPdfService.build(jpegs)], ps_scan_file_name_service_1.PsScanFileNameService.build(options.fileName, options.format, 0, 1), {
23
+ type,
24
+ }),
25
+ ];
26
+ }
27
+ }
28
+ exports.PsScanOutputService = PsScanOutputService;
@@ -0,0 +1,5 @@
1
+ import type { PsScanPdfPage } from '../models/ps-scan-pdf-page';
2
+ export declare class PsScanPdfService {
3
+ static build(pages: PsScanPdfPage[]): Uint8Array<ArrayBuffer>;
4
+ private static points;
5
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsScanPdfService = void 0;
4
+ const ps_scan_config_1 = require("../constants/ps-scan-config");
5
+ class PsScanPdfService {
6
+ static build(pages) {
7
+ const encoder = new TextEncoder();
8
+ const chunks = [];
9
+ const offsets = [];
10
+ let length = 0;
11
+ const push = (chunk) => {
12
+ chunks.push(chunk);
13
+ length += chunk.length;
14
+ };
15
+ const text = (value) => push(encoder.encode(value));
16
+ const begin = (id) => {
17
+ offsets[id] = length;
18
+ text(`${id} 0 obj\n`);
19
+ };
20
+ const kids = pages.map((_, index) => `${3 + index * 3} 0 R`).join(' ');
21
+ push(Uint8Array.from([
22
+ 0x25, 0x50, 0x44, 0x46, 0x2d, 0x31, 0x2e, 0x34, 0x0a, 0x25, 0xe2, 0xe3, 0xcf, 0xd3, 0x0a,
23
+ ]));
24
+ begin(1);
25
+ text('<< /Type /Catalog /Pages 2 0 R >>\nendobj\n');
26
+ begin(2);
27
+ text(`<< /Type /Pages /Kids [${kids}] /Count ${pages.length} >>\nendobj\n`);
28
+ pages.forEach((page, index) => {
29
+ const pageId = 3 + index * 3;
30
+ const widthPt = PsScanPdfService.points(page.width);
31
+ const heightPt = PsScanPdfService.points(page.height);
32
+ const content = `q ${widthPt} 0 0 ${heightPt} 0 0 cm /Im0 Do Q`;
33
+ begin(pageId);
34
+ text(`<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${widthPt} ${heightPt}] /Resources << /XObject << /Im0 ${pageId + 2} 0 R >> >> /Contents ${pageId + 1} 0 R >>\nendobj\n`);
35
+ begin(pageId + 1);
36
+ text(`<< /Length ${content.length} >>\nstream\n${content}\nendstream\nendobj\n`);
37
+ begin(pageId + 2);
38
+ text(`<< /Type /XObject /Subtype /Image /Width ${page.width} /Height ${page.height} /ColorSpace /DeviceRGB /BitsPerComponent 8 /Filter /DCTDecode /Length ${page.jpeg.length} >>\nstream\n`);
39
+ push(page.jpeg);
40
+ text('\nendstream\nendobj\n');
41
+ });
42
+ const count = 3 + pages.length * 3;
43
+ const xrefAt = length;
44
+ text(`xref\n0 ${count}\n0000000000 65535 f \n`);
45
+ for (let id = 1; id < count; id += 1)
46
+ text(`${String(offsets[id]).padStart(10, '0')} 00000 n \n`);
47
+ text(`trailer\n<< /Size ${count} /Root 1 0 R >>\nstartxref\n${xrefAt}\n%%EOF\n`);
48
+ const out = new Uint8Array(length);
49
+ let at = 0;
50
+ chunks.forEach((chunk) => {
51
+ out.set(chunk, at);
52
+ at += chunk.length;
53
+ });
54
+ return out;
55
+ }
56
+ static points(pixels) {
57
+ return Math.round((pixels * ps_scan_config_1.PsScanConfig.pdfPointsPerInch * 100) / ps_scan_config_1.PsScanConfig.pdfDpi) / 100;
58
+ }
59
+ }
60
+ exports.PsScanPdfService = PsScanPdfService;
@@ -0,0 +1,10 @@
1
+ import type { PsScanPage } from '../models/ps-scan-page';
2
+ import type { PsScanPrepared } from '../models/ps-scan-prepared';
3
+ import type { PsScanRaster } from '../models/ps-scan-raster';
4
+ import type { PsScanRenderedPage } from '../models/ps-scan-rendered-page';
5
+ export declare class PsScanPipelineService {
6
+ static prepare(source: Blob): Promise<PsScanPrepared>;
7
+ static measure(source: Blob): Promise<PsScanRaster>;
8
+ static process(page: Pick<PsScanPage, 'corners' | 'filter' | 'rotation'>, raster: PsScanRaster, maxDimension: number): PsScanRaster;
9
+ static render(page: PsScanPage, maxDimension: number, quality: number): Promise<PsScanRenderedPage>;
10
+ }
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsScanPipelineService = void 0;
4
+ const ps_scan_config_1 = require("../constants/ps-scan-config");
5
+ const ps_scan_canvas_service_1 = require("./ps-scan-canvas-service");
6
+ const ps_scan_edge_service_1 = require("./ps-scan-edge-service");
7
+ const ps_scan_enhance_service_1 = require("./ps-scan-enhance-service");
8
+ const ps_scan_geometry_service_1 = require("./ps-scan-geometry-service");
9
+ const ps_scan_raster_service_1 = require("./ps-scan-raster-service");
10
+ const ps_scan_warp_service_1 = require("./ps-scan-warp-service");
11
+ class PsScanPipelineService {
12
+ static async prepare(source) {
13
+ const decoded = await ps_scan_canvas_service_1.PsScanCanvasService.decode(source, ps_scan_config_1.PsScanConfig.detectMaxDimension * 2);
14
+ const detected = ps_scan_edge_service_1.PsScanEdgeService.detect(decoded.raster);
15
+ return {
16
+ corners: detected === null ? ps_scan_geometry_service_1.PsScanGeometryService.defaultQuad() : detected,
17
+ height: decoded.naturalHeight,
18
+ isDetected: detected !== null,
19
+ width: decoded.naturalWidth,
20
+ };
21
+ }
22
+ static async measure(source) {
23
+ const decoded = await ps_scan_canvas_service_1.PsScanCanvasService.decode(source, ps_scan_config_1.PsScanConfig.previewMaxDimension);
24
+ return decoded.raster;
25
+ }
26
+ static process(page, raster, maxDimension) {
27
+ const size = ps_scan_geometry_service_1.PsScanGeometryService.fitWithin(ps_scan_geometry_service_1.PsScanGeometryService.outputSize(page.corners, raster), maxDimension);
28
+ const warped = ps_scan_warp_service_1.PsScanWarpService.warp(raster, ps_scan_geometry_service_1.PsScanGeometryService.toPixels(page.corners, {
29
+ height: raster.height - 1,
30
+ width: raster.width - 1,
31
+ }), size.width, size.height);
32
+ return ps_scan_raster_service_1.PsScanRasterService.rotate(ps_scan_enhance_service_1.PsScanEnhanceService.apply(warped, page.filter), page.rotation);
33
+ }
34
+ static async render(page, maxDimension, quality) {
35
+ const decoded = await ps_scan_canvas_service_1.PsScanCanvasService.decode(page.source, ps_scan_config_1.PsScanConfig.decodeMaxDimension);
36
+ const raster = PsScanPipelineService.process(page, decoded.raster, maxDimension);
37
+ return {
38
+ blob: await ps_scan_canvas_service_1.PsScanCanvasService.encode(raster, quality),
39
+ height: raster.height,
40
+ width: raster.width,
41
+ };
42
+ }
43
+ }
44
+ exports.PsScanPipelineService = PsScanPipelineService;
@@ -0,0 +1,6 @@
1
+ import type { PsScanRaster } from '../models/ps-scan-raster';
2
+ export declare class PsScanRasterService {
3
+ static create(width: number, height: number): PsScanRaster;
4
+ static resize(source: PsScanRaster, width: number, height: number): PsScanRaster;
5
+ static rotate(source: PsScanRaster, degrees: number): PsScanRaster;
6
+ }
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsScanRasterService = void 0;
4
+ class PsScanRasterService {
5
+ static create(width, height) {
6
+ return { data: new Uint8ClampedArray(width * height * 4), height, width };
7
+ }
8
+ static resize(source, width, height) {
9
+ if (width === source.width && height === source.height)
10
+ return source;
11
+ const target = PsScanRasterService.create(width, height);
12
+ const scaleX = source.width / width;
13
+ const scaleY = source.height / height;
14
+ for (let y = 0; y < height; y += 1) {
15
+ const y0 = Math.floor(y * scaleY);
16
+ const y1 = Math.min(source.height, Math.max(y0 + 1, Math.ceil((y + 1) * scaleY)));
17
+ for (let x = 0; x < width; x += 1) {
18
+ const x0 = Math.floor(x * scaleX);
19
+ const x1 = Math.min(source.width, Math.max(x0 + 1, Math.ceil((x + 1) * scaleX)));
20
+ let r = 0;
21
+ let g = 0;
22
+ let b = 0;
23
+ let a = 0;
24
+ let count = 0;
25
+ for (let sy = y0; sy < y1; sy += 1)
26
+ for (let sx = x0; sx < x1; sx += 1) {
27
+ const at = (sy * source.width + sx) * 4;
28
+ r += source.data[at];
29
+ g += source.data[at + 1];
30
+ b += source.data[at + 2];
31
+ a += source.data[at + 3];
32
+ count += 1;
33
+ }
34
+ const out = (y * width + x) * 4;
35
+ target.data[out] = r / count;
36
+ target.data[out + 1] = g / count;
37
+ target.data[out + 2] = b / count;
38
+ target.data[out + 3] = a / count;
39
+ }
40
+ }
41
+ return target;
42
+ }
43
+ static rotate(source, degrees) {
44
+ const turns = ((Math.round(degrees / 90) % 4) + 4) % 4;
45
+ if (turns === 0)
46
+ return source;
47
+ const swapped = turns % 2 === 1;
48
+ const width = swapped ? source.height : source.width;
49
+ const height = swapped ? source.width : source.height;
50
+ const target = PsScanRasterService.create(width, height);
51
+ for (let y = 0; y < source.height; y += 1)
52
+ for (let x = 0; x < source.width; x += 1) {
53
+ let tx = x;
54
+ let ty = y;
55
+ if (turns === 1)
56
+ [tx, ty] = [source.height - 1 - y, x];
57
+ else if (turns === 2)
58
+ [tx, ty] = [source.width - 1 - x, source.height - 1 - y];
59
+ else
60
+ [tx, ty] = [y, source.width - 1 - x];
61
+ const from = (y * source.width + x) * 4;
62
+ const to = (ty * width + tx) * 4;
63
+ target.data[to] = source.data[from];
64
+ target.data[to + 1] = source.data[from + 1];
65
+ target.data[to + 2] = source.data[from + 2];
66
+ target.data[to + 3] = source.data[from + 3];
67
+ }
68
+ return target;
69
+ }
70
+ }
71
+ exports.PsScanRasterService = PsScanRasterService;
@@ -0,0 +1,3 @@
1
+ export declare class PsScanTemplateService {
2
+ static fill(template: string, values: Record<string, string | number>): string;
3
+ }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsScanTemplateService = void 0;
4
+ class PsScanTemplateService {
5
+ static fill(template, values) {
6
+ return template.replace(/\{(\w+)\}/g, (match, key) => key in values ? String(values[key]) : match);
7
+ }
8
+ }
9
+ exports.PsScanTemplateService = PsScanTemplateService;
@@ -0,0 +1,6 @@
1
+ import type { PsScanQuad } from '../models/ps-scan-quad';
2
+ import type { PsScanRaster } from '../models/ps-scan-raster';
3
+ export declare class PsScanWarpService {
4
+ static warp(source: PsScanRaster, pixelQuad: PsScanQuad, width: number, height: number): PsScanRaster;
5
+ private static sample;
6
+ }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsScanWarpService = void 0;
4
+ const ps_scan_homography_service_1 = require("./ps-scan-homography-service");
5
+ const ps_scan_raster_service_1 = require("./ps-scan-raster-service");
6
+ class PsScanWarpService {
7
+ static warp(source, pixelQuad, width, height) {
8
+ const matrix = ps_scan_homography_service_1.PsScanHomographyService.fromUnitSquare(pixelQuad);
9
+ const target = ps_scan_raster_service_1.PsScanRasterService.create(width, height);
10
+ const spanX = Math.max(1, width - 1);
11
+ const spanY = Math.max(1, height - 1);
12
+ for (let y = 0; y < height; y += 1)
13
+ for (let x = 0; x < width; x += 1) {
14
+ const point = ps_scan_homography_service_1.PsScanHomographyService.apply(matrix, x / spanX, y / spanY);
15
+ PsScanWarpService.sample(source, point.x, point.y, target.data, (y * width + x) * 4);
16
+ }
17
+ return target;
18
+ }
19
+ static sample(source, x, y, out, at) {
20
+ const cx = Math.min(source.width - 1, Math.max(0, x));
21
+ const cy = Math.min(source.height - 1, Math.max(0, y));
22
+ const x0 = Math.floor(cx);
23
+ const y0 = Math.floor(cy);
24
+ const x1 = Math.min(source.width - 1, x0 + 1);
25
+ const y1 = Math.min(source.height - 1, y0 + 1);
26
+ const fx = cx - x0;
27
+ const fy = cy - y0;
28
+ const a = (y0 * source.width + x0) * 4;
29
+ const b = (y0 * source.width + x1) * 4;
30
+ const c = (y1 * source.width + x0) * 4;
31
+ const d = (y1 * source.width + x1) * 4;
32
+ for (let channel = 0; channel < 4; channel += 1) {
33
+ const top = source.data[a + channel] * (1 - fx) + source.data[b + channel] * fx;
34
+ const bottom = source.data[c + channel] * (1 - fx) + source.data[d + channel] * fx;
35
+ out[at + channel] = top * (1 - fy) + bottom * fy;
36
+ }
37
+ }
38
+ }
39
+ exports.PsScanWarpService = PsScanWarpService;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pallasoft/ps-file-components",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "private": false,
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -32,10 +32,10 @@
32
32
  "test": "vitest run"
33
33
  },
34
34
  "dependencies": {
35
- "@pallasoft/ps-core-components": "^2.13.0",
36
- "@pallasoft/ps-icons": "^1.6.0",
37
- "@pallasoft/ps-popovers": "^1.5.2",
38
- "@pallasoft/ps-utilities": "^2.9.0",
35
+ "@pallasoft/ps-core-components": "^2.27.0",
36
+ "@pallasoft/ps-icons": "^1.8.1",
37
+ "@pallasoft/ps-popovers": "^1.10.2",
38
+ "@pallasoft/ps-utilities": "^2.19.1",
39
39
  "pdfjs-dist": "^6.3.289"
40
40
  },
41
41
  "peerDependencies": {
@@ -47,13 +47,15 @@
47
47
  "@commitlint/config-conventional": "^20.0.0",
48
48
  "@eslint/compat": "^2.0.0",
49
49
  "@ianvs/prettier-plugin-sort-imports": "^4.7.0",
50
- "@pallasoft/ps-design-system": "^1.14.0",
50
+ "@pallasoft/ps-design-system": "^1.15.0",
51
51
  "@semantic-release/changelog": "^6.0.3",
52
52
  "@semantic-release/commit-analyzer": "^13.0.0",
53
53
  "@semantic-release/git": "^10.0.1",
54
54
  "@semantic-release/github": "^11.0.1",
55
55
  "@semantic-release/npm": "^12.0.0",
56
56
  "@semantic-release/release-notes-generator": "^14.0.1",
57
+ "@testing-library/dom": "^10.4.2",
58
+ "@testing-library/react": "^16.3.3",
57
59
  "@types/react": "^18.3.28",
58
60
  "@types/react-dom": "^18.3.7",
59
61
  "@typescript-eslint/eslint-plugin": "^8.48.0",
@@ -65,6 +67,7 @@
65
67
  "eslint-plugin-import": "^2.32.0",
66
68
  "eslint-plugin-prettier": "^5.5.4",
67
69
  "husky": "^9.1.7",
70
+ "jsdom": "^30.1.2",
68
71
  "lint-staged": "^16.2.7",
69
72
  "prettier": "^3.6.2",
70
73
  "react": "^19.3.0",