label-studio-converter 1.4.0 → 1.5.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.
@@ -30,15 +30,15 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  mod
31
31
  ));
32
32
 
33
- // node_modules/.pnpm/tsup@8.5.1_jiti@2.4.2_postcss@8.5.6_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js
33
+ // node_modules/.pnpm/tsup@8.5.1_jiti@2.4.2_postcss@8.5.6_typescript@6.0.3_yaml@2.9.0/node_modules/tsup/assets/cjs_shims.js
34
34
  var init_cjs_shims = __esm({
35
- "node_modules/.pnpm/tsup@8.5.1_jiti@2.4.2_postcss@8.5.6_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js"() {
35
+ "node_modules/.pnpm/tsup@8.5.1_jiti@2.4.2_postcss@8.5.6_typescript@6.0.3_yaml@2.9.0/node_modules/tsup/assets/cjs_shims.js"() {
36
36
  "use strict";
37
37
  }
38
38
  });
39
39
 
40
40
  // src/constants.ts
41
- var DEFAULT_DETECT_IMAGE_SIZE, DEFAULT_LABEL_NAME, DEFAULT_LABEL_STUDIO_FULL_JSON, DEFAULT_CREATE_FILE_PER_IMAGE, DEFAULT_CREATE_FILE_LIST_FOR_SERVING, DEFAULT_FILE_LIST_NAME, DEFAULT_BASE_SERVER_URL, DEFAULT_PPOCR_FILE_NAME, SORT_VERTICAL_NONE, SORT_VERTICAL_TOP_BOTTOM, SORT_VERTICAL_BOTTOM_TOP, DEFAULT_SORT_VERTICAL, SORT_HORIZONTAL_NONE, SORT_HORIZONTAL_LTR, SORT_HORIZONTAL_RTL, DEFAULT_SORT_HORIZONTAL, SHAPE_NORMALIZE_NONE, SHAPE_NORMALIZE_RECTANGLE, DEFAULT_SHAPE_NORMALIZE, DEFAULT_USE_ORIENTED_BOX, DEFAULT_WIDTH_INCREMENT, DEFAULT_HEIGHT_INCREMENT, DEFAULT_ADAPT_RESIZE_THRESHOLD, DEFAULT_ADAPT_RESIZE_MARGIN, DEFAULT_ADAPT_RESIZE_MIN_COMPONENT_SIZE, DEFAULT_ADAPT_RESIZE_MAX_COMPONENT_SIZE, DEFAULT_ADAPT_RESIZE_OUTLIER_PERCENTILE, DEFAULT_ADAPT_RESIZE_MORPHOLOGY_SIZE, DEFAULT_ADAPT_RESIZE_MAX_HORIZONTAL_EXPANSION, DEFAULT_ADAPT_RESIZE_TIMEOUT_MS, DEFAULT_ADAPT_RESIZE_MAX_BOX_SIZE, DEFAULT_LABEL_STUDIO_PRECISION, DEFAULT_PPOCR_PRECISION, DEFAULT_RECURSIVE, DEFAULT_PPOCR_FILE_PATTERN, DEFAULT_LABEL_STUDIO_FILE_PATTERN, OUTPUT_MODE_ANNOTATIONS, OUTPUT_MODE_PREDICTIONS, DEFAULT_OUTPUT_MODE, DEFAULT_BACKUP, BACKUP_SUFFIX_PREFIX, DEFAULT_COPY_IMAGES;
41
+ var DEFAULT_DETECT_IMAGE_SIZE, DEFAULT_LABEL_NAME, DEFAULT_LABEL_STUDIO_FULL_JSON, DEFAULT_CREATE_FILE_PER_IMAGE, DEFAULT_CREATE_FILE_LIST_FOR_SERVING, DEFAULT_FILE_LIST_NAME, DEFAULT_BASE_SERVER_URL, DEFAULT_PPOCR_FILE_NAME, SORT_VERTICAL_NONE, SORT_VERTICAL_TOP_BOTTOM, SORT_VERTICAL_BOTTOM_TOP, DEFAULT_SORT_VERTICAL, SORT_HORIZONTAL_NONE, SORT_HORIZONTAL_LTR, SORT_HORIZONTAL_RTL, DEFAULT_SORT_HORIZONTAL, SHAPE_NORMALIZE_NONE, SHAPE_NORMALIZE_RECTANGLE, DEFAULT_SHAPE_NORMALIZE, DEFAULT_USE_ORIENTED_BOX, DEFAULT_WIDTH_INCREMENT, DEFAULT_HEIGHT_INCREMENT, DEFAULT_ADAPT_RESIZE, DEFAULT_ADAPT_RESIZE_THRESHOLD, DEFAULT_ADAPT_RESIZE_MARGIN, DEFAULT_ADAPT_RESIZE_MIN_COMPONENT_SIZE, DEFAULT_ADAPT_RESIZE_MAX_COMPONENT_SIZE, DEFAULT_ADAPT_RESIZE_OUTLIER_PERCENTILE, DEFAULT_ADAPT_RESIZE_MORPHOLOGY_SIZE, DEFAULT_ADAPT_RESIZE_MAX_HORIZONTAL_EXPANSION, DEFAULT_ADAPT_RESIZE_TIMEOUT_MS, DEFAULT_ADAPT_RESIZE_MAX_BOX_SIZE, DEFAULT_ADAPT_RESIZE_PADDING_CHECK_WIDTH, DEFAULT_ADAPT_RESIZE_MIN_PADDING_BRIGHTNESS, DEFAULT_ADAPT_RESIZE_MIN_PADDING_RATIO, DEFAULT_ADAPT_RESIZE_USE_ADAPTIVE_THRESHOLD, DEFAULT_ADAPT_RESIZE_ADAPTIVE_BLOCK_SIZE, DEFAULT_LABEL_STUDIO_PRECISION, DEFAULT_PPOCR_PRECISION, DEFAULT_RECURSIVE, DEFAULT_PPOCR_FILE_PATTERN, DEFAULT_LABEL_STUDIO_FILE_PATTERN, OUTPUT_MODE_ANNOTATIONS, OUTPUT_MODE_PREDICTIONS, DEFAULT_OUTPUT_MODE, DEFAULT_BACKUP, BACKUP_SUFFIX_PREFIX, DEFAULT_COPY_IMAGES, IMAGE_BASE_DIR_TASK_FILE, IMAGE_BASE_DIR_INPUT_DIR, DEFAULT_IMAGE_BASE_DIR, DEFAULT_LABEL_STUDIO_OUTPUT_IMAGE_BASE_DIR;
42
42
  var init_constants = __esm({
43
43
  "src/constants.ts"() {
44
44
  "use strict";
@@ -65,6 +65,7 @@ var init_constants = __esm({
65
65
  DEFAULT_USE_ORIENTED_BOX = false;
66
66
  DEFAULT_WIDTH_INCREMENT = 0;
67
67
  DEFAULT_HEIGHT_INCREMENT = 0;
68
+ DEFAULT_ADAPT_RESIZE = false;
68
69
  DEFAULT_ADAPT_RESIZE_THRESHOLD = 128;
69
70
  DEFAULT_ADAPT_RESIZE_MARGIN = 5;
70
71
  DEFAULT_ADAPT_RESIZE_MIN_COMPONENT_SIZE = 10;
@@ -72,8 +73,13 @@ var init_constants = __esm({
72
73
  DEFAULT_ADAPT_RESIZE_OUTLIER_PERCENTILE = 2;
73
74
  DEFAULT_ADAPT_RESIZE_MORPHOLOGY_SIZE = 2;
74
75
  DEFAULT_ADAPT_RESIZE_MAX_HORIZONTAL_EXPANSION = 50;
75
- DEFAULT_ADAPT_RESIZE_TIMEOUT_MS = 3e4;
76
+ DEFAULT_ADAPT_RESIZE_TIMEOUT_MS = 15e3;
76
77
  DEFAULT_ADAPT_RESIZE_MAX_BOX_SIZE = 3e3;
78
+ DEFAULT_ADAPT_RESIZE_PADDING_CHECK_WIDTH = 3;
79
+ DEFAULT_ADAPT_RESIZE_MIN_PADDING_BRIGHTNESS = 200;
80
+ DEFAULT_ADAPT_RESIZE_MIN_PADDING_RATIO = 0.85;
81
+ DEFAULT_ADAPT_RESIZE_USE_ADAPTIVE_THRESHOLD = true;
82
+ DEFAULT_ADAPT_RESIZE_ADAPTIVE_BLOCK_SIZE = 50;
77
83
  DEFAULT_LABEL_STUDIO_PRECISION = -1;
78
84
  DEFAULT_PPOCR_PRECISION = 0;
79
85
  DEFAULT_RECURSIVE = false;
@@ -85,6 +91,10 @@ var init_constants = __esm({
85
91
  DEFAULT_BACKUP = false;
86
92
  BACKUP_SUFFIX_PREFIX = "backup-";
87
93
  DEFAULT_COPY_IMAGES = true;
94
+ IMAGE_BASE_DIR_TASK_FILE = "task-file";
95
+ IMAGE_BASE_DIR_INPUT_DIR = "input-dir";
96
+ DEFAULT_IMAGE_BASE_DIR = IMAGE_BASE_DIR_TASK_FILE;
97
+ DEFAULT_LABEL_STUDIO_OUTPUT_IMAGE_BASE_DIR = "/data/local-files/?d=";
88
98
  }
89
99
  });
90
100
 
@@ -92,11 +102,17 @@ var init_constants = __esm({
92
102
  function withOptions(fn, options) {
93
103
  return [fn, options];
94
104
  }
95
- var Processor;
105
+ var defaultResolveInputImagePath, defaultResolveOutputImagePath, Processor;
96
106
  var init_processor = __esm({
97
107
  "src/lib/processor.ts"() {
98
108
  "use strict";
99
109
  init_cjs_shims();
110
+ defaultResolveInputImagePath = (taskImagePath) => {
111
+ return taskImagePath;
112
+ };
113
+ defaultResolveOutputImagePath = (taskImagePath) => {
114
+ return taskImagePath;
115
+ };
100
116
  Processor = class {
101
117
  input;
102
118
  output;
@@ -113,8 +129,8 @@ var init_processor = __esm({
113
129
  async process({
114
130
  inputData,
115
131
  taskFilePath,
116
- resolveInputImagePath,
117
- resolveOutputImagePath
132
+ resolveInputImagePath = defaultResolveInputImagePath,
133
+ resolveOutputImagePath = defaultResolveOutputImagePath
118
134
  }) {
119
135
  const [inputFn, inputOptions] = Array.isArray(this.input) ? this.input : [this.input, void 0];
120
136
  const [outputFn, outputOptions] = Array.isArray(this.output) ? this.output : [this.output, void 0];
@@ -540,10 +556,62 @@ function withTimeout(promise, timeoutMs, timeoutValue) {
540
556
  return Promise.race([
541
557
  promise,
542
558
  new Promise(
543
- (resolve3) => setTimeout(() => resolve3(timeoutValue), timeoutMs)
559
+ (resolve4) => setTimeout(() => resolve4(timeoutValue), timeoutMs)
544
560
  )
545
561
  ]);
546
562
  }
563
+ function calculateAdaptiveThreshold(grayscaleData, width, height) {
564
+ const histogram = new Array(256).fill(0);
565
+ for (let i = 0; i < grayscaleData.length; i++) {
566
+ const pixelValue = grayscaleData[i];
567
+ if (pixelValue !== void 0) {
568
+ histogram[pixelValue]++;
569
+ }
570
+ }
571
+ const totalPixels = width * height;
572
+ let sum = 0;
573
+ for (let i = 0; i < 256; i++) {
574
+ sum += i * histogram[i];
575
+ }
576
+ let sumB = 0;
577
+ let wB = 0;
578
+ let wF = 0;
579
+ let maxVariance = 0;
580
+ let threshold = 0;
581
+ for (let t = 0; t < 256; t++) {
582
+ wB += histogram[t];
583
+ if (wB === 0) continue;
584
+ wF = totalPixels - wB;
585
+ if (wF === 0) break;
586
+ sumB += t * histogram[t];
587
+ const mB = sumB / wB;
588
+ const mF = (sum - sumB) / wF;
589
+ const variance = wB * wF * (mB - mF) * (mB - mF);
590
+ if (variance > maxVariance) {
591
+ maxVariance = variance;
592
+ threshold = t;
593
+ }
594
+ }
595
+ return Math.max(100, Math.min(200, threshold + 10));
596
+ }
597
+ function validatePaddingStrip(grayscaleData, x1, y1, x2, y2, width, height, minBrightness, minRatio) {
598
+ let totalPixels = 0;
599
+ let whitePixels = 0;
600
+ for (let y = Math.floor(y1); y <= Math.ceil(y2); y++) {
601
+ for (let x = Math.floor(x1); x <= Math.ceil(x2); x++) {
602
+ if (x >= 0 && x < width && y >= 0 && y < height) {
603
+ totalPixels++;
604
+ const idx = y * width + x;
605
+ const pixelValue = grayscaleData[idx];
606
+ if (pixelValue !== void 0 && pixelValue >= minBrightness) {
607
+ whitePixels++;
608
+ }
609
+ }
610
+ }
611
+ }
612
+ if (totalPixels === 0) return false;
613
+ return whitePixels / totalPixels >= minRatio;
614
+ }
547
615
  async function adaptiveResizeBoundingBox(points, imagePath, options) {
548
616
  if (points.length === 0 || !(0, import_node_fs.existsSync)(imagePath)) {
549
617
  return points;
@@ -555,7 +623,11 @@ async function adaptiveResizeBoundingBox(points, imagePath, options) {
555
623
  maxComponentSize = DEFAULT_ADAPT_RESIZE_MAX_COMPONENT_SIZE,
556
624
  outlierPercentile = DEFAULT_ADAPT_RESIZE_OUTLIER_PERCENTILE,
557
625
  morphologySize = DEFAULT_ADAPT_RESIZE_MORPHOLOGY_SIZE,
558
- maxHorizontalExpansion = DEFAULT_ADAPT_RESIZE_MAX_HORIZONTAL_EXPANSION
626
+ maxHorizontalExpansion = DEFAULT_ADAPT_RESIZE_MAX_HORIZONTAL_EXPANSION,
627
+ paddingCheckWidth = DEFAULT_ADAPT_RESIZE_PADDING_CHECK_WIDTH,
628
+ minPaddingBrightness = DEFAULT_ADAPT_RESIZE_MIN_PADDING_BRIGHTNESS,
629
+ minPaddingRatio = DEFAULT_ADAPT_RESIZE_MIN_PADDING_RATIO,
630
+ useAdaptiveThreshold = DEFAULT_ADAPT_RESIZE_USE_ADAPTIVE_THRESHOLD
559
631
  } = options;
560
632
  try {
561
633
  const rotation = getBoxRotation(points);
@@ -600,14 +672,30 @@ async function adaptiveResizeBoundingBox(points, imagePath, options) {
600
672
  if (analysisW <= 0 || analysisH <= 0) {
601
673
  return points;
602
674
  }
603
- const { data, info } = await image.extract({
675
+ const grayscaleImage = image.extract({
604
676
  left: analysisX,
605
677
  top: analysisY,
606
678
  width: analysisW,
607
679
  height: analysisH
608
- }).grayscale().threshold(threshold).raw().toBuffer({ resolveWithObject: true });
680
+ }).grayscale();
681
+ const { data: grayscaleData, info: grayscaleInfo } = await grayscaleImage.raw().toBuffer({ resolveWithObject: true });
682
+ let actualThreshold = threshold;
683
+ if (useAdaptiveThreshold) {
684
+ actualThreshold = calculateAdaptiveThreshold(
685
+ grayscaleData,
686
+ grayscaleInfo.width,
687
+ grayscaleInfo.height
688
+ );
689
+ }
690
+ const { data: binaryData, info } = await (0, import_sharp.default)(grayscaleData, {
691
+ raw: {
692
+ width: grayscaleInfo.width,
693
+ height: grayscaleInfo.height,
694
+ channels: 1
695
+ }
696
+ }).threshold(actualThreshold).raw().toBuffer({ resolveWithObject: true });
609
697
  const morphed = morphologicalClosing(
610
- data,
698
+ binaryData,
611
699
  info.width,
612
700
  info.height,
613
701
  morphologySize
@@ -616,7 +704,7 @@ async function adaptiveResizeBoundingBox(points, imagePath, options) {
616
704
  morphed,
617
705
  info.width,
618
706
  info.height,
619
- threshold
707
+ actualThreshold
620
708
  );
621
709
  const validComponents = components.filter(
622
710
  (comp) => comp.size >= minComponentSize && comp.size <= maxComponentSize
@@ -643,10 +731,10 @@ async function adaptiveResizeBoundingBox(points, imagePath, options) {
643
731
  const minY = sortedY[0] || 0;
644
732
  const maxY = sortedY[sortedY.length - 1] || info.height - 1;
645
733
  const detectSeparator = createSeparatorDetector({
646
- data,
734
+ data: binaryData,
647
735
  width: info.width,
648
736
  height: info.height,
649
- threshold
737
+ threshold: actualThreshold
650
738
  });
651
739
  const originalBoxMinX = x - analysisX;
652
740
  const originalBoxMaxX = x - analysisX + w;
@@ -659,21 +747,142 @@ async function adaptiveResizeBoundingBox(points, imagePath, options) {
659
747
  detectSeparator,
660
748
  info.width
661
749
  );
662
- const limitedMinX = Math.max(
750
+ let limitedMinX = Math.max(
663
751
  leftBoundary,
664
752
  originalBoxMinX - maxHorizontalExpansion
665
753
  );
666
- const limitedMaxX = Math.min(
754
+ let limitedMaxX = Math.min(
667
755
  rightBoundary,
668
756
  originalBoxMaxX + maxHorizontalExpansion
669
757
  );
758
+ let limitedMinY = minY;
759
+ let limitedMaxY = maxY;
760
+ const leftPaddingValid = validatePaddingStrip(
761
+ grayscaleData,
762
+ limitedMinX,
763
+ limitedMinY,
764
+ Math.min(limitedMinX + paddingCheckWidth - 1, limitedMaxX),
765
+ limitedMaxY,
766
+ info.width,
767
+ info.height,
768
+ minPaddingBrightness,
769
+ minPaddingRatio
770
+ );
771
+ if (!leftPaddingValid && limitedMinX < originalBoxMinX) {
772
+ for (let i = 0; i < maxHorizontalExpansion; i++) {
773
+ limitedMinX++;
774
+ if (validatePaddingStrip(
775
+ grayscaleData,
776
+ limitedMinX,
777
+ limitedMinY,
778
+ Math.min(limitedMinX + paddingCheckWidth - 1, limitedMaxX),
779
+ limitedMaxY,
780
+ info.width,
781
+ info.height,
782
+ minPaddingBrightness,
783
+ minPaddingRatio
784
+ )) {
785
+ break;
786
+ }
787
+ }
788
+ }
789
+ const rightPaddingValid = validatePaddingStrip(
790
+ grayscaleData,
791
+ Math.max(limitedMaxX - paddingCheckWidth + 1, limitedMinX),
792
+ limitedMinY,
793
+ limitedMaxX,
794
+ limitedMaxY,
795
+ info.width,
796
+ info.height,
797
+ minPaddingBrightness,
798
+ minPaddingRatio
799
+ );
800
+ if (!rightPaddingValid && limitedMaxX > originalBoxMaxX) {
801
+ for (let i = 0; i < maxHorizontalExpansion; i++) {
802
+ limitedMaxX--;
803
+ if (validatePaddingStrip(
804
+ grayscaleData,
805
+ Math.max(limitedMaxX - paddingCheckWidth + 1, limitedMinX),
806
+ limitedMinY,
807
+ limitedMaxX,
808
+ limitedMaxY,
809
+ info.width,
810
+ info.height,
811
+ minPaddingBrightness,
812
+ minPaddingRatio
813
+ )) {
814
+ break;
815
+ }
816
+ }
817
+ }
818
+ const topPaddingValid = validatePaddingStrip(
819
+ grayscaleData,
820
+ limitedMinX,
821
+ limitedMinY,
822
+ limitedMaxX,
823
+ Math.min(limitedMinY + paddingCheckWidth - 1, limitedMaxY),
824
+ info.width,
825
+ info.height,
826
+ minPaddingBrightness,
827
+ minPaddingRatio
828
+ );
829
+ if (!topPaddingValid && limitedMinY > 0) {
830
+ for (let i = 0; i < 20; i++) {
831
+ limitedMinY++;
832
+ if (validatePaddingStrip(
833
+ grayscaleData,
834
+ limitedMinX,
835
+ limitedMinY,
836
+ limitedMaxX,
837
+ Math.min(limitedMinY + paddingCheckWidth - 1, limitedMaxY),
838
+ info.width,
839
+ info.height,
840
+ minPaddingBrightness,
841
+ minPaddingRatio
842
+ )) {
843
+ break;
844
+ }
845
+ }
846
+ }
847
+ const bottomPaddingValid = validatePaddingStrip(
848
+ grayscaleData,
849
+ limitedMinX,
850
+ Math.max(limitedMaxY - paddingCheckWidth + 1, limitedMinY),
851
+ limitedMaxX,
852
+ limitedMaxY,
853
+ info.width,
854
+ info.height,
855
+ minPaddingBrightness,
856
+ minPaddingRatio
857
+ );
858
+ if (!bottomPaddingValid && limitedMaxY < info.height - 1) {
859
+ for (let i = 0; i < 20; i++) {
860
+ limitedMaxY--;
861
+ if (validatePaddingStrip(
862
+ grayscaleData,
863
+ limitedMinX,
864
+ Math.max(limitedMaxY - paddingCheckWidth + 1, limitedMinY),
865
+ limitedMaxX,
866
+ limitedMaxY,
867
+ info.width,
868
+ info.height,
869
+ minPaddingBrightness,
870
+ minPaddingRatio
871
+ )) {
872
+ break;
873
+ }
874
+ }
875
+ }
670
876
  const newMinX = Math.max(0, analysisX + limitedMinX - margin);
671
- const newMinY = Math.max(0, analysisY + minY - margin);
877
+ const newMinY = Math.max(0, analysisY + limitedMinY - margin);
672
878
  const newMaxX = Math.min(
673
879
  metadata.width,
674
880
  analysisX + limitedMaxX + 1 + margin
675
881
  );
676
- const newMaxY = Math.min(metadata.height, analysisY + maxY + 1 + margin);
882
+ const newMaxY = Math.min(
883
+ metadata.height,
884
+ analysisY + limitedMaxY + 1 + margin
885
+ );
677
886
  if (isRotated) {
678
887
  const center = calculateCenter(points);
679
888
  const cos = Math.cos(rotation);
@@ -720,13 +929,18 @@ var init_adapt_resize = __esm({
720
929
  init_separator_detection();
721
930
  adaptResizeTransformer = (async (boxes, imageFilePath, options) => {
722
931
  const {
723
- threshold = 128,
724
- margin = 5,
725
- minComponentSize = 10,
726
- maxComponentSize = 1e5,
727
- outlierPercentile = 2,
728
- morphologySize = 2,
729
- maxHorizontalExpansion = 50
932
+ threshold = DEFAULT_ADAPT_RESIZE_THRESHOLD,
933
+ margin = DEFAULT_ADAPT_RESIZE_MARGIN,
934
+ minComponentSize = DEFAULT_ADAPT_RESIZE_MIN_COMPONENT_SIZE,
935
+ maxComponentSize = DEFAULT_ADAPT_RESIZE_MAX_COMPONENT_SIZE,
936
+ outlierPercentile = DEFAULT_ADAPT_RESIZE_OUTLIER_PERCENTILE,
937
+ morphologySize = DEFAULT_ADAPT_RESIZE_MORPHOLOGY_SIZE,
938
+ maxHorizontalExpansion = DEFAULT_ADAPT_RESIZE_MAX_HORIZONTAL_EXPANSION,
939
+ paddingCheckWidth = DEFAULT_ADAPT_RESIZE_PADDING_CHECK_WIDTH,
940
+ minPaddingBrightness = DEFAULT_ADAPT_RESIZE_MIN_PADDING_BRIGHTNESS,
941
+ minPaddingRatio = DEFAULT_ADAPT_RESIZE_MIN_PADDING_RATIO,
942
+ useAdaptiveThreshold = DEFAULT_ADAPT_RESIZE_USE_ADAPTIVE_THRESHOLD,
943
+ adaptiveBlockSize = DEFAULT_ADAPT_RESIZE_ADAPTIVE_BLOCK_SIZE
730
944
  } = options || {};
731
945
  if (boxes.length === 0) {
732
946
  return boxes;
@@ -734,6 +948,9 @@ var init_adapt_resize = __esm({
734
948
  console.log(
735
949
  `Processing ${boxes.length} boxes with adaptive resize for: ${imageFilePath}`
736
950
  );
951
+ if (useAdaptiveThreshold) {
952
+ console.log(" Using adaptive thresholding based on image histogram");
953
+ }
737
954
  const resized = await Promise.all(
738
955
  boxes.map(async (box, index) => {
739
956
  const newPoints = await withTimeout(
@@ -744,7 +961,12 @@ var init_adapt_resize = __esm({
744
961
  maxComponentSize,
745
962
  outlierPercentile,
746
963
  morphologySize,
747
- maxHorizontalExpansion
964
+ maxHorizontalExpansion,
965
+ paddingCheckWidth,
966
+ minPaddingBrightness,
967
+ minPaddingRatio,
968
+ useAdaptiveThreshold,
969
+ adaptiveBlockSize
748
970
  }),
749
971
  DEFAULT_ADAPT_RESIZE_TIMEOUT_MS,
750
972
  box.points
@@ -1186,6 +1408,34 @@ var init_schema3 = __esm({
1186
1408
  }
1187
1409
  });
1188
1410
 
1411
+ // src/modules/label-studio-output/schema.ts
1412
+ var import_zod5, OutputLabelStudioSchema;
1413
+ var init_schema4 = __esm({
1414
+ "src/modules/label-studio-output/schema.ts"() {
1415
+ "use strict";
1416
+ init_cjs_shims();
1417
+ import_zod5 = __toESM(require("zod"), 1);
1418
+ init_schema();
1419
+ OutputLabelStudioSchema = AnnotationSchema.extend({
1420
+ created_username: import_zod5.default.string(),
1421
+ created_ago: import_zod5.default.string().optional(),
1422
+ completed_by: import_zod5.default.object({
1423
+ id: import_zod5.default.number(),
1424
+ first_name: import_zod5.default.string(),
1425
+ last_name: import_zod5.default.string(),
1426
+ email: import_zod5.default.string()
1427
+ }),
1428
+ task: FullOCRLabelStudioSchema.omit({
1429
+ annotations: true,
1430
+ predictions: true,
1431
+ drafts: true
1432
+ }).extend({
1433
+ overlap: import_zod5.default.number()
1434
+ })
1435
+ });
1436
+ }
1437
+ });
1438
+
1189
1439
  // src/lib/image.ts
1190
1440
  var import_node_fs2, import_promises, import_image_size, getImageDimensions;
1191
1441
  var init_image = __esm({
@@ -1616,6 +1866,68 @@ var init_output3 = __esm({
1616
1866
  }
1617
1867
  });
1618
1868
 
1869
+ // src/modules/label-studio-output/input.ts
1870
+ var import_es_toolkit3, OutputLabelStudioInput;
1871
+ var init_input4 = __esm({
1872
+ "src/modules/label-studio-output/input.ts"() {
1873
+ "use strict";
1874
+ init_cjs_shims();
1875
+ import_es_toolkit3 = require("es-toolkit");
1876
+ init_geometry();
1877
+ OutputLabelStudioInput = (async (inputTask, resolveImagePath) => {
1878
+ const imageFilePath = await resolveImagePath(inputTask.task.data.ocr);
1879
+ const { id, result, ...metadata } = inputTask;
1880
+ const annoData = result;
1881
+ const imageMeta = annoData?.find(
1882
+ (item) => item.original_height !== void 0 && item.original_width !== void 0
1883
+ );
1884
+ let { original_height: imgHeight, original_width: imgWidth } = imageMeta ?? {};
1885
+ const groupByAnnoId = (0, import_es_toolkit3.groupBy)(annoData || [], (item) => item.id);
1886
+ return {
1887
+ id: id.toString(),
1888
+ height: imgHeight,
1889
+ width: imgWidth,
1890
+ imagePath: imageFilePath,
1891
+ metadata,
1892
+ boxes: Object.entries(groupByAnnoId).map(([annoId, items]) => {
1893
+ let baseAnno = {};
1894
+ for (const item of items) {
1895
+ baseAnno = { ...baseAnno, ...item.value };
1896
+ }
1897
+ let newPoints = "points" in baseAnno ? tupleToPoints(baseAnno.points) : [];
1898
+ if (newPoints.length === 0 && "x" in baseAnno && "y" in baseAnno && "width" in baseAnno && "height" in baseAnno) {
1899
+ newPoints = rectangleToPoints(
1900
+ baseAnno.x,
1901
+ baseAnno.y,
1902
+ baseAnno.width,
1903
+ baseAnno.height,
1904
+ imgWidth,
1905
+ imgHeight
1906
+ );
1907
+ }
1908
+ return {
1909
+ id: annoId,
1910
+ points: newPoints,
1911
+ metadata: baseAnno,
1912
+ score: imageMeta?.score,
1913
+ text: "text" in baseAnno ? Array.isArray(baseAnno.text) ? baseAnno.text.join(" ") : baseAnno.text : void 0
1914
+ };
1915
+ })
1916
+ };
1917
+ });
1918
+ }
1919
+ });
1920
+
1921
+ // src/modules/label-studio-output/output.ts
1922
+ var init_output4 = __esm({
1923
+ "src/modules/label-studio-output/output.ts"() {
1924
+ "use strict";
1925
+ init_cjs_shims();
1926
+ init_constants();
1927
+ init_geometry();
1928
+ }
1929
+ });
1930
+
1619
1931
  // src/config.ts
1620
1932
  var baseFileIOFlagOptions, baseEnhanceFlagOptions;
1621
1933
  var init_config = __esm({
@@ -1656,6 +1968,12 @@ var init_config = __esm({
1656
1968
  kind: "boolean",
1657
1969
  brief: `Copy images to output directory when --outDir is specified. Only applies to toLabelStudio and toPPOCR commands. Default: ${DEFAULT_COPY_IMAGES}`,
1658
1970
  optional: true
1971
+ },
1972
+ imageBaseDir: {
1973
+ kind: "parsed",
1974
+ brief: `Base directory for resolving image paths. Options: "${IMAGE_BASE_DIR_TASK_FILE}" (relative to task file location), "${IMAGE_BASE_DIR_INPUT_DIR}" (relative to command execution directory). Default: "${DEFAULT_IMAGE_BASE_DIR}"`,
1975
+ parse: String,
1976
+ optional: true
1659
1977
  }
1660
1978
  };
1661
1979
  baseEnhanceFlagOptions = {
@@ -1696,7 +2014,7 @@ var init_config = __esm({
1696
2014
  },
1697
2015
  adaptResize: {
1698
2016
  kind: "boolean",
1699
- brief: `Apply adaptive resize to automatically adjust bounding boxes based on image content. Default: false`,
2017
+ brief: `Apply adaptive resize to automatically adjust bounding boxes based on image content. Default: ${DEFAULT_ADAPT_RESIZE}`,
1700
2018
  optional: true
1701
2019
  },
1702
2020
  adaptResizeThreshold: {
@@ -1741,6 +2059,35 @@ var init_config = __esm({
1741
2059
  parse: Number,
1742
2060
  optional: true
1743
2061
  },
2062
+ adaptResizePaddingCheckWidth: {
2063
+ kind: "parsed",
2064
+ brief: `Width of padding strip to validate (in pixels). Default: ${DEFAULT_ADAPT_RESIZE_PADDING_CHECK_WIDTH}`,
2065
+ parse: Number,
2066
+ optional: true
2067
+ },
2068
+ adaptResizeMinPaddingBrightness: {
2069
+ kind: "parsed",
2070
+ brief: `Minimum brightness for white padding pixels (0-255). Default: ${DEFAULT_ADAPT_RESIZE_MIN_PADDING_BRIGHTNESS}`,
2071
+ parse: Number,
2072
+ optional: true
2073
+ },
2074
+ adaptResizeMinPaddingRatio: {
2075
+ kind: "parsed",
2076
+ brief: `Minimum ratio of white pixels in padding strip (0-1). Default: ${DEFAULT_ADAPT_RESIZE_MIN_PADDING_RATIO}`,
2077
+ parse: Number,
2078
+ optional: true
2079
+ },
2080
+ adaptResizeUseAdaptiveThreshold: {
2081
+ kind: "boolean",
2082
+ brief: `Use adaptive thresholding based on image histogram (recommended). Default: ${DEFAULT_ADAPT_RESIZE_USE_ADAPTIVE_THRESHOLD}`,
2083
+ optional: true
2084
+ },
2085
+ adaptResizeAdaptiveBlockSize: {
2086
+ kind: "parsed",
2087
+ brief: `Block size for adaptive thresholding. Default: ${DEFAULT_ADAPT_RESIZE_ADAPTIVE_BLOCK_SIZE}`,
2088
+ parse: Number,
2089
+ optional: true
2090
+ },
1744
2091
  precision: {
1745
2092
  kind: "parsed",
1746
2093
  brief: `Number of decimal places for coordinates. Use -1 for full precision (no rounding). Default: ${DEFAULT_PPOCR_PRECISION} (integers)`,
@@ -1764,13 +2111,14 @@ var init_label_studio_to_ppocr = __esm({
1764
2111
  fullLabelStudioToPPOCRConverters = async (inputTasks, taskFilePath, outputDir, options) => {
1765
2112
  const {
1766
2113
  baseImageDir,
2114
+ imageBaseDir: _imageBaseDir,
1767
2115
  sortVertical,
1768
2116
  sortHorizontal,
1769
2117
  normalizeShape,
1770
2118
  useOrientedBox,
1771
2119
  widthIncrement,
1772
2120
  heightIncrement,
1773
- adaptResize = false,
2121
+ adaptResize,
1774
2122
  adaptResizeThreshold,
1775
2123
  adaptResizeMargin,
1776
2124
  adaptResizeMinComponentSize,
@@ -1814,13 +2162,13 @@ var init_label_studio_to_ppocr = __esm({
1814
2162
  const filename = (0, import_path.basename)(urlPath);
1815
2163
  const fileDir2 = (0, import_path.dirname)(taskFilePath2);
1816
2164
  const localPath = (0, import_path.join)(fileDir2, filename);
1817
- await new Promise((resolve3, reject) => {
2165
+ await new Promise((resolve4, reject) => {
1818
2166
  (0, import_https.get)(taskImagePath, (response) => {
1819
2167
  const fileStream = (0, import_fs.createWriteStream)(localPath);
1820
2168
  response.pipe(fileStream);
1821
2169
  fileStream.on("finish", () => {
1822
2170
  fileStream.close();
1823
- resolve3();
2171
+ resolve4();
1824
2172
  });
1825
2173
  fileStream.on("error", reject);
1826
2174
  }).on("error", reject);
@@ -1861,13 +2209,14 @@ var init_label_studio_to_ppocr = __esm({
1861
2209
  minLabelStudioToPPOCRConverters = async (inputTasks, taskFilePath, outputDir, options) => {
1862
2210
  const {
1863
2211
  baseImageDir,
2212
+ imageBaseDir: _imageBaseDir,
1864
2213
  sortVertical,
1865
2214
  sortHorizontal,
1866
2215
  normalizeShape,
1867
2216
  useOrientedBox,
1868
2217
  widthIncrement,
1869
2218
  heightIncrement,
1870
- adaptResize = false,
2219
+ adaptResize,
1871
2220
  adaptResizeThreshold,
1872
2221
  adaptResizeMargin,
1873
2222
  adaptResizeMinComponentSize,
@@ -1911,13 +2260,13 @@ var init_label_studio_to_ppocr = __esm({
1911
2260
  const filename = (0, import_path.basename)(urlPath);
1912
2261
  const fileDir2 = (0, import_path.dirname)(taskFilePath2);
1913
2262
  const localPath = (0, import_path.join)(fileDir2, filename);
1914
- await new Promise((resolve3, reject) => {
2263
+ await new Promise((resolve4, reject) => {
1915
2264
  (0, import_https.get)(taskImagePath, (response) => {
1916
2265
  const fileStream = (0, import_fs.createWriteStream)(localPath);
1917
2266
  response.pipe(fileStream);
1918
2267
  fileStream.on("finish", () => {
1919
2268
  fileStream.close();
1920
- resolve3();
2269
+ resolve4();
1921
2270
  });
1922
2271
  fileStream.on("error", reject);
1923
2272
  }).on("error", reject);
@@ -1965,20 +2314,26 @@ var init_ppocr_to_label_studio = __esm({
1965
2314
  "use strict";
1966
2315
  init_cjs_shims();
1967
2316
  import_path2 = require("path");
2317
+ init_constants();
1968
2318
  init_lib();
1969
2319
  ppocrToFullLabelStudioConverters = async (inputTasks, taskFilePath, options) => {
1970
2320
  const {
1971
2321
  baseServerUrl,
1972
2322
  defaultLabelName,
1973
- outDir,
1974
- copyImages = false,
2323
+ outputMode,
2324
+ outDir: _outDir,
2325
+ // Keep for potential future use
2326
+ copyImages: _copyImages = false,
2327
+ // Keep for potential future use
2328
+ imageBaseDir,
2329
+ inputBaseDir,
1975
2330
  sortVertical,
1976
2331
  sortHorizontal,
1977
2332
  normalizeShape,
1978
2333
  useOrientedBox,
1979
2334
  widthIncrement,
1980
2335
  heightIncrement,
1981
- adaptResize = false,
2336
+ adaptResize,
1982
2337
  adaptResizeThreshold,
1983
2338
  adaptResizeMargin,
1984
2339
  adaptResizeMinComponentSize,
@@ -1986,6 +2341,11 @@ var init_ppocr_to_label_studio = __esm({
1986
2341
  adaptResizeOutlierPercentile,
1987
2342
  adaptResizeMorphologySize,
1988
2343
  adaptResizeMaxHorizontalExpansion,
2344
+ adaptResizePaddingCheckWidth,
2345
+ adaptResizeMinPaddingBrightness,
2346
+ adaptResizeMinPaddingRatio,
2347
+ adaptResizeUseAdaptiveThreshold,
2348
+ adaptResizeAdaptiveBlockSize,
1989
2349
  precision
1990
2350
  } = options;
1991
2351
  const transformerParams = [
@@ -2005,7 +2365,12 @@ var init_ppocr_to_label_studio = __esm({
2005
2365
  maxComponentSize: adaptResizeMaxComponentSize,
2006
2366
  outlierPercentile: adaptResizeOutlierPercentile,
2007
2367
  morphologySize: adaptResizeMorphologySize,
2008
- maxHorizontalExpansion: adaptResizeMaxHorizontalExpansion
2368
+ maxHorizontalExpansion: adaptResizeMaxHorizontalExpansion,
2369
+ paddingCheckWidth: adaptResizePaddingCheckWidth,
2370
+ minPaddingBrightness: adaptResizeMinPaddingBrightness,
2371
+ minPaddingRatio: adaptResizeMinPaddingRatio,
2372
+ useAdaptiveThreshold: adaptResizeUseAdaptiveThreshold,
2373
+ adaptiveBlockSize: adaptResizeAdaptiveBlockSize
2009
2374
  })
2010
2375
  ] : [],
2011
2376
  withOptions(roundTransformer, {
@@ -2026,35 +2391,23 @@ var init_ppocr_to_label_studio = __esm({
2026
2391
  return (0, import_path2.join)(fileDir, taskImagePath);
2027
2392
  }
2028
2393
  };
2029
- const resolveOutputImagePath = (taskImagePath, taskFilePath2) => {
2030
- let resolvedPath;
2031
- if (outDir) {
2032
- const outputJsonDir = (0, import_path2.resolve)(outDir);
2033
- if (copyImages) {
2034
- const fileName = (0, import_path2.basename)(taskImagePath);
2035
- resolvedPath = fileName;
2036
- } else {
2037
- const absoluteImagePath = (0, import_path2.resolve)(process.cwd(), taskImagePath);
2038
- resolvedPath = (0, import_path2.relative)(outputJsonDir, absoluteImagePath);
2039
- }
2040
- } else {
2041
- const taskDir = (0, import_path2.dirname)(taskFilePath2);
2042
- resolvedPath = (0, import_path2.relative)(taskDir, taskImagePath);
2043
- }
2394
+ const resolveOutputImagePath = (taskImagePath, _taskFilePath) => {
2395
+ const relativePath = imageBaseDir === IMAGE_BASE_DIR_INPUT_DIR && inputBaseDir ? (0, import_path2.relative)(inputBaseDir, taskImagePath) : (0, import_path2.basename)(taskImagePath);
2396
+ const resolvedPath = relativePath;
2044
2397
  if (baseServerUrl !== void 0) {
2045
2398
  if (baseServerUrl === "") {
2046
2399
  return encodeURI(`/${resolvedPath}`);
2047
- } else {
2048
- const normalizedBaseUrl = baseServerUrl.replace(/\/+$/, "");
2049
- return encodeURI(`${normalizedBaseUrl}/${resolvedPath}`);
2050
2400
  }
2401
+ const normalizedBaseUrl = baseServerUrl.replace(/\/+$/, "");
2402
+ return encodeURI(`${normalizedBaseUrl}/${resolvedPath}`);
2051
2403
  }
2052
2404
  return resolvedPath;
2053
2405
  };
2054
2406
  const processor = new Processor({
2055
2407
  input: PPOCRInput,
2056
2408
  output: withOptions(FullOCRLabelStudioOutput, {
2057
- defaultLabelName
2409
+ defaultLabelName,
2410
+ outputMode
2058
2411
  }),
2059
2412
  transformers: transformerParams
2060
2413
  });
@@ -2074,8 +2427,12 @@ var init_ppocr_to_label_studio = __esm({
2074
2427
  const {
2075
2428
  baseServerUrl,
2076
2429
  defaultLabelName,
2077
- outDir,
2078
- copyImages = false,
2430
+ outDir: _outDir,
2431
+ // Keep for potential future use
2432
+ copyImages: _copyImages = false,
2433
+ // Keep for potential future use
2434
+ imageBaseDir,
2435
+ inputBaseDir,
2079
2436
  sortVertical,
2080
2437
  sortHorizontal,
2081
2438
  normalizeShape,
@@ -2111,28 +2468,15 @@ var init_ppocr_to_label_studio = __esm({
2111
2468
  return (0, import_path2.join)(fileDir, taskImagePath);
2112
2469
  }
2113
2470
  };
2114
- const resolveOutputImagePath = (taskImagePath, taskFilePath2) => {
2115
- let resolvedPath;
2116
- if (outDir) {
2117
- const outputJsonDir = (0, import_path2.resolve)(outDir);
2118
- if (copyImages) {
2119
- const fileName = (0, import_path2.basename)(taskImagePath);
2120
- resolvedPath = fileName;
2121
- } else {
2122
- const absoluteImagePath = (0, import_path2.resolve)(process.cwd(), taskImagePath);
2123
- resolvedPath = (0, import_path2.relative)(outputJsonDir, absoluteImagePath);
2124
- }
2125
- } else {
2126
- const taskDir = (0, import_path2.dirname)(taskFilePath2);
2127
- resolvedPath = (0, import_path2.relative)(taskDir, taskImagePath);
2128
- }
2471
+ const resolveOutputImagePath = (taskImagePath, _taskFilePath) => {
2472
+ const relativePath = imageBaseDir === IMAGE_BASE_DIR_INPUT_DIR && inputBaseDir ? (0, import_path2.relative)(inputBaseDir, taskImagePath) : (0, import_path2.basename)(taskImagePath);
2473
+ const resolvedPath = relativePath;
2129
2474
  if (baseServerUrl !== void 0) {
2130
2475
  if (baseServerUrl === "") {
2131
2476
  return encodeURI(`/${resolvedPath}`);
2132
- } else {
2133
- const normalizedBaseUrl = baseServerUrl.replace(/\/+$/, "");
2134
- return encodeURI(`${normalizedBaseUrl}/${resolvedPath}`);
2135
2477
  }
2478
+ const normalizedBaseUrl = baseServerUrl.replace(/\/+$/, "");
2479
+ return encodeURI(`${normalizedBaseUrl}/${resolvedPath}`);
2136
2480
  }
2137
2481
  return resolvedPath;
2138
2482
  };
@@ -2168,18 +2512,23 @@ var init_enhance_label_studio = __esm({
2168
2512
  import_fs2 = require("fs");
2169
2513
  import_https2 = require("https");
2170
2514
  import_path3 = require("path");
2515
+ init_constants();
2171
2516
  init_lib();
2172
2517
  enhanceFullLabelStudioConverters = async (inputTasks, taskFilePath, options) => {
2173
2518
  const {
2174
2519
  baseServerUrl,
2175
- outDir,
2520
+ outDir: _outDir,
2521
+ // Keep for potential future use
2522
+ imageBaseDir,
2523
+ copyImages: _copyImages,
2524
+ inputBaseDir,
2176
2525
  sortVertical,
2177
2526
  sortHorizontal,
2178
2527
  normalizeShape,
2179
2528
  useOrientedBox,
2180
2529
  widthIncrement,
2181
2530
  heightIncrement,
2182
- adaptResize = false,
2531
+ adaptResize,
2183
2532
  adaptResizeThreshold,
2184
2533
  adaptResizeMargin,
2185
2534
  adaptResizeMinComponentSize,
@@ -2187,6 +2536,11 @@ var init_enhance_label_studio = __esm({
2187
2536
  adaptResizeOutlierPercentile,
2188
2537
  adaptResizeMorphologySize,
2189
2538
  adaptResizeMaxHorizontalExpansion,
2539
+ adaptResizePaddingCheckWidth,
2540
+ adaptResizeMinPaddingBrightness,
2541
+ adaptResizeMinPaddingRatio,
2542
+ adaptResizeUseAdaptiveThreshold,
2543
+ adaptResizeAdaptiveBlockSize,
2190
2544
  precision
2191
2545
  } = options;
2192
2546
  const transformerParams = [
@@ -2206,7 +2560,12 @@ var init_enhance_label_studio = __esm({
2206
2560
  maxComponentSize: adaptResizeMaxComponentSize,
2207
2561
  outlierPercentile: adaptResizeOutlierPercentile,
2208
2562
  morphologySize: adaptResizeMorphologySize,
2209
- maxHorizontalExpansion: adaptResizeMaxHorizontalExpansion
2563
+ maxHorizontalExpansion: adaptResizeMaxHorizontalExpansion,
2564
+ paddingCheckWidth: adaptResizePaddingCheckWidth,
2565
+ minPaddingBrightness: adaptResizeMinPaddingBrightness,
2566
+ minPaddingRatio: adaptResizeMinPaddingRatio,
2567
+ useAdaptiveThreshold: adaptResizeUseAdaptiveThreshold,
2568
+ adaptiveBlockSize: adaptResizeAdaptiveBlockSize
2210
2569
  })
2211
2570
  ] : [],
2212
2571
  withOptions(roundTransformer, {
@@ -2223,13 +2582,13 @@ var init_enhance_label_studio = __esm({
2223
2582
  const urlPath = new URL(taskImagePath).pathname;
2224
2583
  const filename = (0, import_path3.basename)(urlPath);
2225
2584
  const localPath = (0, import_path3.join)(fileDir, filename);
2226
- await new Promise((resolve3, reject) => {
2585
+ await new Promise((resolve4, reject) => {
2227
2586
  (0, import_https2.get)(taskImagePath, (response) => {
2228
2587
  const fileStream = (0, import_fs2.createWriteStream)(localPath);
2229
2588
  response.pipe(fileStream);
2230
2589
  fileStream.on("finish", () => {
2231
2590
  fileStream.close();
2232
- resolve3();
2591
+ resolve4();
2233
2592
  });
2234
2593
  fileStream.on("error", reject);
2235
2594
  }).on("error", reject);
@@ -2239,19 +2598,15 @@ var init_enhance_label_studio = __esm({
2239
2598
  const cleanPath = taskImagePath.replace(/^\/+/, "");
2240
2599
  return (0, import_path3.join)(fileDir, cleanPath);
2241
2600
  };
2242
- const resolveOutputImagePath = (taskImagePath, taskFilePath2) => {
2243
- let resolvedPath = taskImagePath;
2244
- if (outDir) {
2245
- const relativePath = (0, import_path3.relative)(process.cwd(), taskFilePath2);
2246
- const relativeDir = (0, import_path3.dirname)(relativePath);
2247
- const outputSubDir = (0, import_path3.join)(outDir, relativeDir);
2248
- resolvedPath = (0, import_path3.relative)(outputSubDir, taskImagePath);
2601
+ const resolveOutputImagePath = (taskImagePath, _taskFilePath) => {
2602
+ const relativePath = imageBaseDir === IMAGE_BASE_DIR_INPUT_DIR && inputBaseDir ? (0, import_path3.relative)(inputBaseDir, taskImagePath) : (0, import_path3.basename)(taskImagePath);
2603
+ if (baseServerUrl === void 0) {
2604
+ return relativePath;
2249
2605
  }
2250
- const newBaseServerUrl = baseServerUrl?.replace(/\/+$/, "") + (baseServerUrl === "" ? "" : "");
2251
- if (newBaseServerUrl) {
2252
- return encodeURI(`${newBaseServerUrl}/${resolvedPath}`);
2606
+ if (baseServerUrl === "") {
2607
+ return "/" + relativePath;
2253
2608
  }
2254
- return resolvedPath;
2609
+ return new URL(relativePath, baseServerUrl).href;
2255
2610
  };
2256
2611
  const processor = new Processor({
2257
2612
  input: FullOCRLabelStudioInput,
@@ -2273,14 +2628,18 @@ var init_enhance_label_studio = __esm({
2273
2628
  enhanceMinLabelStudioConverters = async (inputTasks, taskFilePath, options) => {
2274
2629
  const {
2275
2630
  baseServerUrl,
2276
- outDir,
2631
+ outDir: _outDir,
2632
+ // Keep for potential future use
2633
+ imageBaseDir,
2634
+ copyImages: _copyImages,
2635
+ inputBaseDir,
2277
2636
  sortVertical,
2278
2637
  sortHorizontal,
2279
2638
  normalizeShape,
2280
2639
  useOrientedBox,
2281
2640
  widthIncrement,
2282
2641
  heightIncrement,
2283
- adaptResize = false,
2642
+ adaptResize,
2284
2643
  adaptResizeThreshold,
2285
2644
  adaptResizeMargin,
2286
2645
  adaptResizeMinComponentSize,
@@ -2288,6 +2647,11 @@ var init_enhance_label_studio = __esm({
2288
2647
  adaptResizeOutlierPercentile,
2289
2648
  adaptResizeMorphologySize,
2290
2649
  adaptResizeMaxHorizontalExpansion,
2650
+ adaptResizePaddingCheckWidth,
2651
+ adaptResizeMinPaddingBrightness,
2652
+ adaptResizeMinPaddingRatio,
2653
+ adaptResizeUseAdaptiveThreshold,
2654
+ adaptResizeAdaptiveBlockSize,
2291
2655
  precision
2292
2656
  } = options;
2293
2657
  const transformerParams = [
@@ -2307,7 +2671,12 @@ var init_enhance_label_studio = __esm({
2307
2671
  maxComponentSize: adaptResizeMaxComponentSize,
2308
2672
  outlierPercentile: adaptResizeOutlierPercentile,
2309
2673
  morphologySize: adaptResizeMorphologySize,
2310
- maxHorizontalExpansion: adaptResizeMaxHorizontalExpansion
2674
+ maxHorizontalExpansion: adaptResizeMaxHorizontalExpansion,
2675
+ paddingCheckWidth: adaptResizePaddingCheckWidth,
2676
+ minPaddingBrightness: adaptResizeMinPaddingBrightness,
2677
+ minPaddingRatio: adaptResizeMinPaddingRatio,
2678
+ useAdaptiveThreshold: adaptResizeUseAdaptiveThreshold,
2679
+ adaptiveBlockSize: adaptResizeAdaptiveBlockSize
2311
2680
  })
2312
2681
  ] : [],
2313
2682
  withOptions(roundTransformer, {
@@ -2324,13 +2693,13 @@ var init_enhance_label_studio = __esm({
2324
2693
  const urlPath = new URL(taskImagePath).pathname;
2325
2694
  const filename = (0, import_path3.basename)(urlPath);
2326
2695
  const localPath = (0, import_path3.join)(fileDir, filename);
2327
- await new Promise((resolve3, reject) => {
2696
+ await new Promise((resolve4, reject) => {
2328
2697
  (0, import_https2.get)(taskImagePath, (response) => {
2329
2698
  const fileStream = (0, import_fs2.createWriteStream)(localPath);
2330
2699
  response.pipe(fileStream);
2331
2700
  fileStream.on("finish", () => {
2332
2701
  fileStream.close();
2333
- resolve3();
2702
+ resolve4();
2334
2703
  });
2335
2704
  fileStream.on("error", reject);
2336
2705
  }).on("error", reject);
@@ -2340,19 +2709,15 @@ var init_enhance_label_studio = __esm({
2340
2709
  const cleanPath = taskImagePath.replace(/^\/+/, "");
2341
2710
  return (0, import_path3.join)(fileDir, cleanPath);
2342
2711
  };
2343
- const resolveOutputImagePath = (taskImagePath, taskFilePath2) => {
2344
- let resolvedPath = taskImagePath;
2345
- if (outDir) {
2346
- const relativePath = (0, import_path3.relative)(process.cwd(), taskFilePath2);
2347
- const relativeDir = (0, import_path3.dirname)(relativePath);
2348
- const outputSubDir = (0, import_path3.join)(outDir, relativeDir);
2349
- resolvedPath = (0, import_path3.relative)(outputSubDir, taskImagePath);
2712
+ const resolveOutputImagePath = (taskImagePath, _taskFilePath) => {
2713
+ const relativePath = imageBaseDir === IMAGE_BASE_DIR_INPUT_DIR && inputBaseDir ? (0, import_path3.relative)(inputBaseDir, taskImagePath) : (0, import_path3.basename)(taskImagePath);
2714
+ if (baseServerUrl === void 0) {
2715
+ return relativePath;
2350
2716
  }
2351
- const newBaseServerUrl = baseServerUrl?.replace(/\/+$/, "") + (baseServerUrl === "" ? "" : "");
2352
- if (newBaseServerUrl) {
2353
- return encodeURI(`${newBaseServerUrl}/${resolvedPath}`);
2717
+ if (baseServerUrl === "") {
2718
+ return "/" + relativePath;
2354
2719
  }
2355
- return resolvedPath;
2720
+ return new URL(relativePath, baseServerUrl).href;
2356
2721
  };
2357
2722
  const processor = new Processor({
2358
2723
  input: MinOCRLabelStudioInput,
@@ -2384,13 +2749,14 @@ var init_enhance_ppocr = __esm({
2384
2749
  init_lib();
2385
2750
  enhancePPOCRConverters = async (inputTasks, taskFilePath, options) => {
2386
2751
  const {
2752
+ imageBaseDir: _imageBaseDir,
2387
2753
  sortVertical,
2388
2754
  sortHorizontal,
2389
2755
  normalizeShape,
2390
2756
  useOrientedBox,
2391
2757
  widthIncrement,
2392
2758
  heightIncrement,
2393
- adaptResize = false,
2759
+ adaptResize,
2394
2760
  adaptResizeThreshold,
2395
2761
  adaptResizeMargin,
2396
2762
  adaptResizeMinComponentSize,
@@ -2398,6 +2764,11 @@ var init_enhance_ppocr = __esm({
2398
2764
  adaptResizeOutlierPercentile,
2399
2765
  adaptResizeMorphologySize,
2400
2766
  adaptResizeMaxHorizontalExpansion,
2767
+ adaptResizePaddingCheckWidth,
2768
+ adaptResizeMinPaddingBrightness,
2769
+ adaptResizeMinPaddingRatio,
2770
+ adaptResizeUseAdaptiveThreshold,
2771
+ adaptResizeAdaptiveBlockSize,
2401
2772
  precision
2402
2773
  } = options;
2403
2774
  const transformerParams = [
@@ -2417,7 +2788,12 @@ var init_enhance_ppocr = __esm({
2417
2788
  maxComponentSize: adaptResizeMaxComponentSize,
2418
2789
  outlierPercentile: adaptResizeOutlierPercentile,
2419
2790
  morphologySize: adaptResizeMorphologySize,
2420
- maxHorizontalExpansion: adaptResizeMaxHorizontalExpansion
2791
+ maxHorizontalExpansion: adaptResizeMaxHorizontalExpansion,
2792
+ paddingCheckWidth: adaptResizePaddingCheckWidth,
2793
+ minPaddingBrightness: adaptResizeMinPaddingBrightness,
2794
+ minPaddingRatio: adaptResizeMinPaddingRatio,
2795
+ useAdaptiveThreshold: adaptResizeUseAdaptiveThreshold,
2796
+ adaptiveBlockSize: adaptResizeAdaptiveBlockSize
2421
2797
  })
2422
2798
  ] : [],
2423
2799
  withOptions(roundTransformer, {
@@ -2463,6 +2839,32 @@ var init_enhance_ppocr = __esm({
2463
2839
  }
2464
2840
  });
2465
2841
 
2842
+ // src/converters/label-studio-output-to-ppocr.ts
2843
+ var outputLabelStudioToPPOCRConverters;
2844
+ var init_label_studio_output_to_ppocr = __esm({
2845
+ "src/converters/label-studio-output-to-ppocr.ts"() {
2846
+ "use strict";
2847
+ init_cjs_shims();
2848
+ init_lib();
2849
+ outputLabelStudioToPPOCRConverters = async (inputTasks, taskFilePath) => {
2850
+ const processor = new Processor({
2851
+ input: OutputLabelStudioInput,
2852
+ output: PPOCROutput
2853
+ });
2854
+ return await Promise.all(
2855
+ inputTasks.map(async (task) => {
2856
+ const outputData = await processor.process({
2857
+ inputData: task,
2858
+ taskFilePath,
2859
+ resolveOutputImagePath: (taskImagePath) => decodeURI(taskImagePath)
2860
+ });
2861
+ return outputData;
2862
+ })
2863
+ );
2864
+ };
2865
+ }
2866
+ });
2867
+
2466
2868
  // src/lib/index.ts
2467
2869
  var init_lib = __esm({
2468
2870
  "src/lib/index.ts"() {
@@ -2478,17 +2880,21 @@ var init_lib = __esm({
2478
2880
  init_schema();
2479
2881
  init_schema2();
2480
2882
  init_schema3();
2883
+ init_schema4();
2481
2884
  init_input();
2482
2885
  init_output();
2483
2886
  init_input2();
2484
2887
  init_output2();
2485
2888
  init_input3();
2486
2889
  init_output3();
2890
+ init_input4();
2891
+ init_output4();
2487
2892
  init_config();
2488
2893
  init_label_studio_to_ppocr();
2489
2894
  init_ppocr_to_label_studio();
2490
2895
  init_enhance_label_studio();
2491
2896
  init_enhance_ppocr();
2897
+ init_label_studio_output_to_ppocr();
2492
2898
  init_constants();
2493
2899
  init_geometry();
2494
2900
  }
@@ -2518,7 +2924,7 @@ var init_backup_utils = __esm({
2518
2924
  // src/lib/file-utils.ts
2519
2925
  async function findFiles(dirs, pattern, recursive) {
2520
2926
  const allFiles = [];
2521
- const regex = new RegExp(pattern);
2927
+ const regex = pattern ? new RegExp(pattern) : null;
2522
2928
  async function scanDirectory(dirPath) {
2523
2929
  const entries = await (0, import_promises3.readdir)(dirPath, { withFileTypes: true });
2524
2930
  for (const entry of entries) {
@@ -2528,7 +2934,9 @@ async function findFiles(dirs, pattern, recursive) {
2528
2934
  await scanDirectory(fullPath);
2529
2935
  }
2530
2936
  } else if (entry.isFile()) {
2531
- if (regex.test(entry.name)) {
2937
+ if (regex && regex.test(entry.name)) {
2938
+ allFiles.push(fullPath);
2939
+ } else if (!regex) {
2532
2940
  allFiles.push(fullPath);
2533
2941
  }
2534
2942
  }
@@ -2539,7 +2947,9 @@ async function findFiles(dirs, pattern, recursive) {
2539
2947
  if (dirStat.isDirectory()) {
2540
2948
  await scanDirectory(dir);
2541
2949
  } else if (dirStat.isFile()) {
2542
- if (regex.test(dir)) {
2950
+ if (regex && regex.test(dir)) {
2951
+ allFiles.push(dir);
2952
+ } else if (!regex) {
2543
2953
  allFiles.push(dir);
2544
2954
  }
2545
2955
  }
@@ -2569,12 +2979,13 @@ async function convertToPPOCR(flags, ...inputDirs) {
2569
2979
  backup = DEFAULT_BACKUP,
2570
2980
  copyImages = DEFAULT_COPY_IMAGES,
2571
2981
  baseImageDir,
2982
+ imageBaseDir = DEFAULT_IMAGE_BASE_DIR,
2572
2983
  sortVertical = DEFAULT_SORT_VERTICAL,
2573
2984
  sortHorizontal = DEFAULT_SORT_HORIZONTAL,
2574
2985
  normalizeShape = DEFAULT_SHAPE_NORMALIZE,
2575
2986
  widthIncrement = DEFAULT_WIDTH_INCREMENT,
2576
2987
  heightIncrement = DEFAULT_HEIGHT_INCREMENT,
2577
- adaptResize = false,
2988
+ adaptResize = DEFAULT_ADAPT_RESIZE,
2578
2989
  adaptResizeThreshold = DEFAULT_ADAPT_RESIZE_THRESHOLD,
2579
2990
  adaptResizeMargin = DEFAULT_ADAPT_RESIZE_MARGIN,
2580
2991
  adaptResizeMinComponentSize = DEFAULT_ADAPT_RESIZE_MIN_COMPONENT_SIZE,
@@ -2594,11 +3005,12 @@ async function convertToPPOCR(flags, ...inputDirs) {
2594
3005
  }
2595
3006
  console.log(import_chalk.default.blue(`Found ${filePaths.length} files to process
2596
3007
  `));
3008
+ const baseDir = inputDirs.length > 0 ? (0, import_path6.resolve)(inputDirs[0]) : process.cwd();
2597
3009
  for (const filePath of filePaths) {
2598
3010
  const file = (0, import_path6.basename)(filePath);
2599
3011
  const relativePath = (0, import_path6.relative)(process.cwd(), filePath);
2600
3012
  const relativeDir = (0, import_path6.dirname)(relativePath);
2601
- console.log(import_chalk.default.gray(`Processing file: ${filePath}`));
3013
+ console.log(import_chalk.default.gray(`Processing file: "${filePath}"`));
2602
3014
  try {
2603
3015
  const fileData = await (0, import_promises4.readFile)(filePath, "utf-8");
2604
3016
  const labelStudioData = JSON.parse(fileData);
@@ -2621,7 +3033,8 @@ async function convertToPPOCR(flags, ...inputDirs) {
2621
3033
  adaptResizeOutlierPercentile,
2622
3034
  adaptResizeMorphologySize,
2623
3035
  adaptResizeMaxHorizontalExpansion,
2624
- precision
3036
+ precision,
3037
+ imageBaseDir
2625
3038
  };
2626
3039
  const outputSubDir = outDir ? (0, import_path6.join)(outDir, relativeDir) : (0, import_path6.dirname)(filePath);
2627
3040
  if (isFull) {
@@ -2658,11 +3071,18 @@ async function convertToPPOCR(flags, ...inputDirs) {
2658
3071
  const cleanPath = imageUrl.startsWith("/") ? imageUrl.slice(1) : imageUrl;
2659
3072
  sourceImagePath = (0, import_path6.join)(taskFileDir, cleanPath);
2660
3073
  }
2661
- const destImagePath = (0, import_path6.join)(outputSubDir, (0, import_path6.basename)(sourceImagePath));
3074
+ let destImagePath;
3075
+ if (imageBaseDir === IMAGE_BASE_DIR_INPUT_DIR) {
3076
+ const relativeFromInput = (0, import_path6.relative)(baseDir, sourceImagePath);
3077
+ destImagePath = (0, import_path6.join)(outDir, relativeFromInput);
3078
+ } else {
3079
+ const relativeFromTask = (0, import_path6.relative)(taskFileDir, sourceImagePath);
3080
+ destImagePath = (0, import_path6.join)(outputSubDir, relativeFromTask);
3081
+ }
2662
3082
  await (0, import_promises4.mkdir)((0, import_path6.dirname)(destImagePath), { recursive: true });
2663
3083
  await (0, import_promises4.copyFile)(sourceImagePath, destImagePath);
2664
3084
  console.log(
2665
- import_chalk.default.gray(` \u2713 Copied image: ${(0, import_path6.basename)(sourceImagePath)}`)
3085
+ import_chalk.default.gray(` \u2713 Copied image: "${(0, import_path6.basename)(sourceImagePath)}"`)
2666
3086
  );
2667
3087
  } catch (error) {
2668
3088
  console.warn(
@@ -2685,14 +3105,14 @@ async function convertToPPOCR(flags, ...inputDirs) {
2685
3105
  if (backup) {
2686
3106
  const backupPath = await backupFileIfExists(outputPath);
2687
3107
  if (backupPath) {
2688
- console.log(import_chalk.default.gray(` Backed up to: ${backupPath}`));
3108
+ console.log(import_chalk.default.gray(` Backed up to: "${backupPath}"`));
2689
3109
  }
2690
3110
  }
2691
3111
  await (0, import_promises4.writeFile)(outputPath, outputLines.join("\n"), "utf-8");
2692
- console.log(import_chalk.default.green(`\u2713 Converted ${file} -> ${outputPath}`));
3112
+ console.log(import_chalk.default.green(`\u2713 Converted "${file}" -> "${outputPath}"`));
2693
3113
  } catch (error) {
2694
3114
  console.error(
2695
- import_chalk.default.red(`\u2717 Failed to process ${file}:`),
3115
+ import_chalk.default.red(`\u2717 Failed to process "${file}":`),
2696
3116
  error instanceof Error ? error.message : error
2697
3117
  );
2698
3118
  }
@@ -2740,12 +3160,13 @@ async function enhanceLabelStudio(flags, ...inputDirs) {
2740
3160
  outDir,
2741
3161
  fileName,
2742
3162
  backup = DEFAULT_BACKUP,
3163
+ imageBaseDir = DEFAULT_IMAGE_BASE_DIR,
2743
3164
  sortVertical = DEFAULT_SORT_VERTICAL,
2744
3165
  sortHorizontal = DEFAULT_SORT_HORIZONTAL,
2745
3166
  normalizeShape = DEFAULT_SHAPE_NORMALIZE,
2746
3167
  widthIncrement = DEFAULT_WIDTH_INCREMENT,
2747
3168
  heightIncrement = DEFAULT_HEIGHT_INCREMENT,
2748
- adaptResize = false,
3169
+ adaptResize = DEFAULT_ADAPT_RESIZE,
2749
3170
  adaptResizeThreshold = DEFAULT_ADAPT_RESIZE_THRESHOLD,
2750
3171
  adaptResizeMargin = DEFAULT_ADAPT_RESIZE_MARGIN,
2751
3172
  adaptResizeMinComponentSize = DEFAULT_ADAPT_RESIZE_MIN_COMPONENT_SIZE,
@@ -2768,7 +3189,7 @@ async function enhanceLabelStudio(flags, ...inputDirs) {
2768
3189
  `));
2769
3190
  for await (const filePath of filePaths) {
2770
3191
  const file = (0, import_path7.basename)(filePath);
2771
- console.log(import_chalk2.default.gray(`Processing file: ${filePath}`));
3192
+ console.log(import_chalk2.default.gray(`Processing file: "${filePath}"`));
2772
3193
  try {
2773
3194
  const fileData = await (0, import_promises5.readFile)(filePath, "utf-8");
2774
3195
  const labelStudioData = JSON.parse(fileData);
@@ -2776,7 +3197,7 @@ async function enhanceLabelStudio(flags, ...inputDirs) {
2776
3197
  if (outputMode !== DEFAULT_OUTPUT_MODE && !isFull) {
2777
3198
  console.log(
2778
3199
  import_chalk2.default.red(
2779
- ` Skipping file: ${filePath}
3200
+ ` Skipping file: "${filePath}"
2780
3201
  Error: --outputMode can only be used with Full JSON format. This file is in Min JSON format which does not support annotations/predictions distinction.`
2781
3202
  )
2782
3203
  );
@@ -2798,7 +3219,8 @@ async function enhanceLabelStudio(flags, ...inputDirs) {
2798
3219
  adaptResizeOutlierPercentile,
2799
3220
  adaptResizeMorphologySize,
2800
3221
  adaptResizeMaxHorizontalExpansion,
2801
- precision
3222
+ precision,
3223
+ imageBaseDir
2802
3224
  };
2803
3225
  if (isFull) {
2804
3226
  outputTasks = await enhanceFullLabelStudioConverters(
@@ -2824,7 +3246,7 @@ async function enhanceLabelStudio(flags, ...inputDirs) {
2824
3246
  if (backup) {
2825
3247
  const backupPath = await backupFileIfExists(outputFilePath);
2826
3248
  if (backupPath) {
2827
- console.log(import_chalk2.default.gray(` Backed up to: ${backupPath}`));
3249
+ console.log(import_chalk2.default.gray(` Backed up to: "${backupPath}"`));
2828
3250
  }
2829
3251
  }
2830
3252
  await (0, import_promises5.writeFile)(
@@ -2832,10 +3254,10 @@ async function enhanceLabelStudio(flags, ...inputDirs) {
2832
3254
  JSON.stringify(outputTasks, null, 2),
2833
3255
  "utf-8"
2834
3256
  );
2835
- console.log(import_chalk2.default.green(`\u2713 Enhanced file saved: ${outputFilePath}`));
3257
+ console.log(import_chalk2.default.green(`\u2713 Enhanced file saved: "${outputFilePath}"`));
2836
3258
  } catch (error) {
2837
3259
  console.error(
2838
- import_chalk2.default.red(`Error processing file ${file}:`),
3260
+ import_chalk2.default.red(`Error processing file "${file}":`),
2839
3261
  error instanceof Error ? error.message : String(error)
2840
3262
  );
2841
3263
  }
@@ -2868,12 +3290,13 @@ async function enhancePPOCR(flags, ...inputDirs) {
2868
3290
  outDir,
2869
3291
  fileName,
2870
3292
  backup = DEFAULT_BACKUP,
3293
+ imageBaseDir = DEFAULT_IMAGE_BASE_DIR,
2871
3294
  sortVertical = DEFAULT_SORT_VERTICAL,
2872
3295
  sortHorizontal = DEFAULT_SORT_HORIZONTAL,
2873
3296
  normalizeShape = DEFAULT_SHAPE_NORMALIZE,
2874
3297
  widthIncrement = DEFAULT_WIDTH_INCREMENT,
2875
3298
  heightIncrement = DEFAULT_HEIGHT_INCREMENT,
2876
- adaptResize = false,
3299
+ adaptResize = DEFAULT_ADAPT_RESIZE,
2877
3300
  adaptResizeThreshold = DEFAULT_ADAPT_RESIZE_THRESHOLD,
2878
3301
  adaptResizeMargin = DEFAULT_ADAPT_RESIZE_MARGIN,
2879
3302
  adaptResizeMinComponentSize = DEFAULT_ADAPT_RESIZE_MIN_COMPONENT_SIZE,
@@ -2895,7 +3318,7 @@ async function enhancePPOCR(flags, ...inputDirs) {
2895
3318
  `));
2896
3319
  for (const filePath of filePaths) {
2897
3320
  const file = (0, import_path8.basename)(filePath);
2898
- console.log(import_chalk3.default.gray(`Processing file: ${filePath}`));
3321
+ console.log(import_chalk3.default.gray(`Processing file: "${filePath}"`));
2899
3322
  try {
2900
3323
  const fileData = await (0, import_promises6.readFile)(filePath, "utf-8");
2901
3324
  const lines = fileData.trim().split("\n");
@@ -2927,7 +3350,7 @@ async function enhancePPOCR(flags, ...inputDirs) {
2927
3350
  }
2928
3351
  if (inputTasks.length === 0) {
2929
3352
  console.log(
2930
- import_chalk3.default.yellow(` Skipping file with no valid data: ${filePath}`)
3353
+ import_chalk3.default.yellow(` Skipping file with no valid data: "${filePath}"`)
2931
3354
  );
2932
3355
  continue;
2933
3356
  }
@@ -2945,7 +3368,8 @@ async function enhancePPOCR(flags, ...inputDirs) {
2945
3368
  adaptResizeOutlierPercentile,
2946
3369
  adaptResizeMorphologySize,
2947
3370
  adaptResizeMaxHorizontalExpansion,
2948
- precision
3371
+ precision,
3372
+ imageBaseDir
2949
3373
  };
2950
3374
  const outputTasks = await enhancePPOCRConverters(
2951
3375
  inputTasks,
@@ -2963,14 +3387,14 @@ async function enhancePPOCR(flags, ...inputDirs) {
2963
3387
  if (backup) {
2964
3388
  const backupPath = await backupFileIfExists(outputFilePath);
2965
3389
  if (backupPath) {
2966
- console.log(import_chalk3.default.gray(` Backed up to: ${backupPath}`));
3390
+ console.log(import_chalk3.default.gray(` Backed up to: "${backupPath}"`));
2967
3391
  }
2968
3392
  }
2969
3393
  await (0, import_promises6.writeFile)(outputFilePath, outputTasks.join("\n"), "utf-8");
2970
- console.log(import_chalk3.default.green(`\u2713 Enhanced file saved: ${outputFilePath}`));
3394
+ console.log(import_chalk3.default.green(`\u2713 Enhanced file saved: "${outputFilePath}"`));
2971
3395
  } catch (error) {
2972
3396
  console.error(
2973
- import_chalk3.default.red(`Error processing file ${file}:`),
3397
+ import_chalk3.default.red(`Error processing file "${file}":`),
2974
3398
  error instanceof Error ? error.message : String(error)
2975
3399
  );
2976
3400
  }
@@ -2992,9 +3416,98 @@ var init_impl3 = __esm({
2992
3416
  }
2993
3417
  });
2994
3418
 
2995
- // src/commands/toLabelStudio/impl.ts
3419
+ // src/commands/labelStudioOutputToPPOCR/impl.ts
2996
3420
  var impl_exports4 = {};
2997
3421
  __export(impl_exports4, {
3422
+ labelStudioOutputToPPOCR: () => labelStudioOutputToPPOCR
3423
+ });
3424
+ async function labelStudioOutputToPPOCR(flags, ...inputDirs) {
3425
+ const {
3426
+ outDir,
3427
+ fileName = DEFAULT_PPOCR_FILE_NAME,
3428
+ backup = DEFAULT_BACKUP,
3429
+ recursive = DEFAULT_RECURSIVE,
3430
+ filePattern = void 0,
3431
+ removeBaseImageDir = DEFAULT_LABEL_STUDIO_OUTPUT_IMAGE_BASE_DIR
3432
+ } = flags;
3433
+ console.log(import_chalk4.default.blue("Finding files..."));
3434
+ const filePaths = await findFiles(inputDirs, filePattern, recursive);
3435
+ if (filePaths.length === 0) {
3436
+ console.log(import_chalk4.default.yellow("No files found matching the pattern."));
3437
+ return;
3438
+ }
3439
+ console.log(import_chalk4.default.blue(`Found ${filePaths.length} files to process
3440
+ `));
3441
+ let masterOutputTasks = [];
3442
+ for (const filePath of filePaths) {
3443
+ console.log(import_chalk4.default.gray(`Processing file: "${filePath}"`));
3444
+ const fileData = await (0, import_promises7.readFile)(filePath, "utf-8");
3445
+ const labelStudioData = JSON.parse(fileData);
3446
+ const [outputTask] = await outputLabelStudioToPPOCRConverters(
3447
+ [labelStudioData],
3448
+ filePath
3449
+ );
3450
+ masterOutputTasks = masterOutputTasks.concat([
3451
+ {
3452
+ ...outputTask,
3453
+ imagePath: outputTask.imagePath.replace(removeBaseImageDir, "")
3454
+ }
3455
+ ]);
3456
+ }
3457
+ const groupTaskByImagePath = (0, import_es_toolkit4.groupBy)(
3458
+ masterOutputTasks,
3459
+ (task) => (0, import_path9.dirname)(task.imagePath)
3460
+ );
3461
+ for (const [baseOutputImageDir, tasks] of Object.entries(
3462
+ groupTaskByImagePath
3463
+ )) {
3464
+ const subImageDir = baseOutputImageDir.split("/").slice(-1)[0];
3465
+ const outputImageDir = (0, import_path9.resolve)(outDir, baseOutputImageDir);
3466
+ await (0, import_promises7.mkdir)(outputImageDir, { recursive: true });
3467
+ const outputPath = (0, import_path9.join)(outputImageDir, `${fileName}`);
3468
+ const outputLines = [];
3469
+ for (const task of tasks) {
3470
+ const imagePath = removeBaseImageDir ? task.imagePath.replace(removeBaseImageDir, "") : task.imagePath;
3471
+ const imageFileName = (0, import_path9.basename)(imagePath);
3472
+ PPOCRLabelSchema.parse(task.data);
3473
+ const jsonArray = JSON.stringify(task.data);
3474
+ outputLines.push(`${subImageDir}/${imageFileName} ${jsonArray}`);
3475
+ console.log(
3476
+ import_chalk4.default.green(
3477
+ `\u2713 Saved image group: "${imagePath}" to "${outputPath}"`
3478
+ )
3479
+ );
3480
+ }
3481
+ if (backup) {
3482
+ const backupPath = await backupFileIfExists(outputPath);
3483
+ if (backupPath) {
3484
+ console.log(import_chalk4.default.gray(` Backed up to: "${backupPath}"`));
3485
+ }
3486
+ }
3487
+ await (0, import_promises7.writeFile)(outputPath, outputLines.join("\n"), "utf-8");
3488
+ }
3489
+ console.log(import_chalk4.default.green("\n\u2713 Conversion completed!"));
3490
+ }
3491
+ var import_promises7, import_path9, import_chalk4, import_es_toolkit4;
3492
+ var init_impl4 = __esm({
3493
+ "src/commands/labelStudioOutputToPPOCR/impl.ts"() {
3494
+ "use strict";
3495
+ init_cjs_shims();
3496
+ import_promises7 = require("fs/promises");
3497
+ import_path9 = require("path");
3498
+ import_chalk4 = __toESM(require("chalk"), 1);
3499
+ import_es_toolkit4 = require("es-toolkit");
3500
+ init_constants();
3501
+ init_lib();
3502
+ init_lib();
3503
+ init_backup_utils();
3504
+ init_file_utils();
3505
+ }
3506
+ });
3507
+
3508
+ // src/commands/toLabelStudio/impl.ts
3509
+ var impl_exports5 = {};
3510
+ __export(impl_exports5, {
2998
3511
  convertToLabelStudio: () => convertToLabelStudio
2999
3512
  });
3000
3513
  async function convertToLabelStudio(flags, ...inputDirs) {
@@ -3003,6 +3516,7 @@ async function convertToLabelStudio(flags, ...inputDirs) {
3003
3516
  fileName,
3004
3517
  backup = DEFAULT_BACKUP,
3005
3518
  copyImages = DEFAULT_COPY_IMAGES,
3519
+ imageBaseDir = DEFAULT_IMAGE_BASE_DIR,
3006
3520
  defaultLabelName = DEFAULT_LABEL_NAME,
3007
3521
  toFullJson = DEFAULT_LABEL_STUDIO_FULL_JSON,
3008
3522
  createFilePerImage = DEFAULT_CREATE_FILE_PER_IMAGE,
@@ -3014,7 +3528,7 @@ async function convertToLabelStudio(flags, ...inputDirs) {
3014
3528
  normalizeShape = DEFAULT_SHAPE_NORMALIZE,
3015
3529
  widthIncrement = DEFAULT_WIDTH_INCREMENT,
3016
3530
  heightIncrement = DEFAULT_HEIGHT_INCREMENT,
3017
- adaptResize = false,
3531
+ adaptResize = DEFAULT_ADAPT_RESIZE,
3018
3532
  adaptResizeThreshold = DEFAULT_ADAPT_RESIZE_THRESHOLD,
3019
3533
  adaptResizeMargin = DEFAULT_ADAPT_RESIZE_MARGIN,
3020
3534
  adaptResizeMinComponentSize = DEFAULT_ADAPT_RESIZE_MIN_COMPONENT_SIZE,
@@ -3029,38 +3543,38 @@ async function convertToLabelStudio(flags, ...inputDirs) {
3029
3543
  } = flags;
3030
3544
  if (outputMode !== DEFAULT_OUTPUT_MODE && !toFullJson) {
3031
3545
  console.log(
3032
- import_chalk4.default.red(
3546
+ import_chalk5.default.red(
3033
3547
  "Error: --outputMode can only be used with --toFullJson (Full JSON format). Min JSON format does not support annotations/predictions distinction."
3034
3548
  )
3035
3549
  );
3036
3550
  return;
3037
3551
  }
3038
- console.log(import_chalk4.default.blue("Finding files..."));
3552
+ console.log(import_chalk5.default.blue("Finding files..."));
3039
3553
  const filePaths = await findFiles(inputDirs, filePattern, recursive);
3040
3554
  if (filePaths.length === 0) {
3041
- console.log(import_chalk4.default.yellow("No files found matching the pattern."));
3555
+ console.log(import_chalk5.default.yellow("No files found matching the pattern."));
3042
3556
  return;
3043
3557
  }
3044
- console.log(import_chalk4.default.blue(`Found ${filePaths.length} files to process
3558
+ console.log(import_chalk5.default.blue(`Found ${filePaths.length} files to process
3045
3559
  `));
3046
- const resolvedOutDir = outDir ? (0, import_path9.resolve)(outDir) : void 0;
3560
+ const resolvedOutDir = outDir ? (0, import_path10.resolve)(outDir) : void 0;
3047
3561
  let fileListPath = null;
3048
3562
  if (createFileListForServing && resolvedOutDir) {
3049
- fileListPath = (0, import_path9.join)(resolvedOutDir, fileListName);
3050
- await (0, import_promises7.mkdir)(resolvedOutDir, { recursive: true });
3051
- await (0, import_promises7.writeFile)(fileListPath, "", "utf-8");
3563
+ fileListPath = (0, import_path10.join)(resolvedOutDir, fileListName);
3564
+ await (0, import_promises8.mkdir)(resolvedOutDir, { recursive: true });
3565
+ await (0, import_promises8.writeFile)(fileListPath, "", "utf-8");
3052
3566
  }
3053
- const baseDir = inputDirs.length > 0 ? (0, import_path9.resolve)(inputDirs[0]) : process.cwd();
3567
+ const baseDir = inputDirs.length > 0 ? (0, import_path10.resolve)(inputDirs[0]) : process.cwd();
3054
3568
  for (const filePath of filePaths) {
3055
- const file = (0, import_path9.basename)(filePath);
3056
- const relativePath = (0, import_path9.relative)(baseDir, filePath);
3057
- const relativeDir = (0, import_path9.dirname)(relativePath);
3058
- console.log(import_chalk4.default.gray(`Processing file: ${filePath}`));
3569
+ const file = (0, import_path10.basename)(filePath);
3570
+ const relativePath = (0, import_path10.relative)(baseDir, filePath);
3571
+ const relativeDir = (0, import_path10.dirname)(relativePath);
3572
+ console.log(import_chalk5.default.gray(`Processing file: "${filePath}"`));
3059
3573
  try {
3060
- const fileData = await (0, import_promises7.readFile)(filePath, "utf-8");
3574
+ const fileData = await (0, import_promises8.readFile)(filePath, "utf-8");
3061
3575
  const trimmedData = fileData.trim();
3062
3576
  if (trimmedData === "") {
3063
- console.log(import_chalk4.default.yellow(` Skipping empty file: ${filePath}`));
3577
+ console.log(import_chalk5.default.yellow(` Skipping empty file: "${filePath}"`));
3064
3578
  continue;
3065
3579
  }
3066
3580
  const lines = trimmedData.split("\n");
@@ -3095,17 +3609,20 @@ async function convertToLabelStudio(flags, ...inputDirs) {
3095
3609
  }
3096
3610
  if (inputTasks.length === 0) {
3097
3611
  console.log(
3098
- import_chalk4.default.yellow(` Skipping file with no valid data: ${filePath}`)
3612
+ import_chalk5.default.yellow(` Skipping file with no valid data: "${filePath}"`)
3099
3613
  );
3100
3614
  continue;
3101
3615
  }
3102
3616
  let outputTasks = [];
3103
- const converterOutputDir = resolvedOutDir ? (0, import_path9.join)(resolvedOutDir, relativeDir) : (0, import_path9.dirname)(filePath);
3617
+ const converterOutputDir = resolvedOutDir ? (0, import_path10.join)(resolvedOutDir, relativeDir) : (0, import_path10.dirname)(filePath);
3104
3618
  const convertParams = {
3105
3619
  defaultLabelName,
3106
3620
  baseServerUrl,
3621
+ outputMode,
3107
3622
  outDir: converterOutputDir,
3108
- copyImages: resolvedOutDir ? copyImages : false
3623
+ copyImages: resolvedOutDir ? copyImages : false,
3624
+ inputBaseDir: baseDir,
3625
+ outputRootDir: resolvedOutDir
3109
3626
  };
3110
3627
  const enhanceParams = {
3111
3628
  sortVertical,
@@ -3121,7 +3638,8 @@ async function convertToLabelStudio(flags, ...inputDirs) {
3121
3638
  adaptResizeOutlierPercentile,
3122
3639
  adaptResizeMorphologySize,
3123
3640
  adaptResizeMaxHorizontalExpansion,
3124
- precision
3641
+ precision,
3642
+ imageBaseDir
3125
3643
  };
3126
3644
  if (toFullJson) {
3127
3645
  outputTasks = await ppocrToFullLabelStudioConverters(
@@ -3143,24 +3661,31 @@ async function convertToLabelStudio(flags, ...inputDirs) {
3143
3661
  );
3144
3662
  }
3145
3663
  if (resolvedOutDir && copyImages) {
3146
- const taskFileDir = (0, import_path9.dirname)(filePath);
3147
- const outputSubDir2 = (0, import_path9.join)(resolvedOutDir, relativeDir);
3664
+ const taskFileDir = (0, import_path10.dirname)(filePath);
3665
+ const outputSubDir2 = (0, import_path10.join)(resolvedOutDir, relativeDir);
3148
3666
  for (const task of inputTasks) {
3149
3667
  try {
3150
3668
  const parts = task.imagePath.split("/");
3151
3669
  const folderName = parts.length > 1 ? parts[0] : "";
3152
3670
  const fileName2 = parts.length > 1 ? parts.slice(1).join("/") : task.imagePath;
3153
- const sourceImagePath = folderName ? (0, import_path9.resolve)((0, import_path9.dirname)(taskFileDir), folderName, fileName2) : (0, import_path9.resolve)(taskFileDir, fileName2);
3154
- const destImagePath = (0, import_path9.join)(outputSubDir2, (0, import_path9.basename)(sourceImagePath));
3155
- await (0, import_promises7.mkdir)((0, import_path9.dirname)(destImagePath), { recursive: true });
3156
- await (0, import_promises7.copyFile)(sourceImagePath, destImagePath);
3671
+ const sourceImagePath = folderName ? (0, import_path10.resolve)((0, import_path10.dirname)(taskFileDir), folderName, fileName2) : (0, import_path10.resolve)(taskFileDir, fileName2);
3672
+ let destImagePath;
3673
+ if (imageBaseDir === IMAGE_BASE_DIR_INPUT_DIR) {
3674
+ const relativeFromInput = (0, import_path10.relative)(baseDir, sourceImagePath);
3675
+ destImagePath = (0, import_path10.join)(resolvedOutDir, relativeFromInput);
3676
+ } else {
3677
+ const relativeFromTask = (0, import_path10.relative)(taskFileDir, sourceImagePath);
3678
+ destImagePath = (0, import_path10.join)(outputSubDir2, relativeFromTask);
3679
+ }
3680
+ await (0, import_promises8.mkdir)((0, import_path10.dirname)(destImagePath), { recursive: true });
3681
+ await (0, import_promises8.copyFile)(sourceImagePath, destImagePath);
3157
3682
  console.log(
3158
- import_chalk4.default.gray(` \u2713 Copied image: ${(0, import_path9.basename)(sourceImagePath)}`)
3683
+ import_chalk5.default.gray(` \u2713 Copied image: "${(0, import_path10.basename)(sourceImagePath)}"`)
3159
3684
  );
3160
3685
  } catch (error) {
3161
3686
  console.warn(
3162
- import_chalk4.default.yellow(
3163
- ` \u26A0 Failed to copy image ${task.imagePath}: ${error instanceof Error ? error.message : error}`
3687
+ import_chalk5.default.yellow(
3688
+ ` \u26A0 Failed to copy image "${task.imagePath}": ${error instanceof Error ? error.message : error}`
3164
3689
  )
3165
3690
  );
3166
3691
  }
@@ -3170,22 +3695,24 @@ async function convertToLabelStudio(flags, ...inputDirs) {
3170
3695
  for await (const taskOutput of outputTasks) {
3171
3696
  const imageFilePath = toFullJson ? taskOutput.data.ocr : taskOutput.ocr;
3172
3697
  const imageBaseName = imageFilePath.split("/").pop().replace(/\//g, "_").replace(/\.[^.]+$/, "");
3173
- const outputSubDir2 = resolvedOutDir ? (0, import_path9.join)(resolvedOutDir, relativeDir) : (0, import_path9.dirname)(filePath);
3174
- await (0, import_promises7.mkdir)(outputSubDir2, { recursive: true });
3175
- const individualOutputPath = (0, import_path9.join)(
3698
+ const outputSubDir2 = resolvedOutDir ? (0, import_path10.join)(resolvedOutDir, relativeDir) : (0, import_path10.dirname)(filePath);
3699
+ await (0, import_promises8.mkdir)(outputSubDir2, { recursive: true });
3700
+ const individualOutputPath = (0, import_path10.join)(
3176
3701
  outputSubDir2,
3177
3702
  `${imageBaseName}_${toFullJson ? "full" : "min"}.json`
3178
3703
  );
3179
- await (0, import_promises7.writeFile)(
3704
+ await (0, import_promises8.writeFile)(
3180
3705
  individualOutputPath,
3181
3706
  JSON.stringify(taskOutput, null, 2),
3182
3707
  "utf-8"
3183
3708
  );
3184
3709
  console.log(
3185
- import_chalk4.default.gray(` \u2713 Created individual file: ${individualOutputPath}`)
3710
+ import_chalk5.default.gray(
3711
+ ` \u2713 Created individual file: "${individualOutputPath}"`
3712
+ )
3186
3713
  );
3187
3714
  if (fileListPath) {
3188
- await (0, import_promises7.writeFile)(fileListPath, `${imageFilePath}
3715
+ await (0, import_promises8.writeFile)(fileListPath, `${imageFilePath}
3189
3716
  `, {
3190
3717
  encoding: "utf-8",
3191
3718
  flag: "a"
@@ -3194,41 +3721,41 @@ async function convertToLabelStudio(flags, ...inputDirs) {
3194
3721
  }
3195
3722
  }
3196
3723
  const baseName = fileName || file.replace(".txt", "");
3197
- const outputSubDir = resolvedOutDir ? (0, import_path9.join)(resolvedOutDir, relativeDir) : (0, import_path9.dirname)(filePath);
3198
- await (0, import_promises7.mkdir)(outputSubDir, { recursive: true });
3199
- const outputPath = (0, import_path9.join)(
3724
+ const outputSubDir = resolvedOutDir ? (0, import_path10.join)(resolvedOutDir, relativeDir) : (0, import_path10.dirname)(filePath);
3725
+ await (0, import_promises8.mkdir)(outputSubDir, { recursive: true });
3726
+ const outputPath = (0, import_path10.join)(
3200
3727
  outputSubDir,
3201
3728
  fileName ? `${fileName}.json` : `${baseName}_${toFullJson ? "full" : "min"}.json`
3202
3729
  );
3203
3730
  if (backup) {
3204
3731
  const backupPath = await backupFileIfExists(outputPath);
3205
3732
  if (backupPath) {
3206
- console.log(import_chalk4.default.gray(` \u2713 Created backup: ${backupPath}`));
3733
+ console.log(import_chalk5.default.gray(` \u2713 Created backup: ${backupPath}`));
3207
3734
  }
3208
3735
  }
3209
- await (0, import_promises7.writeFile)(
3736
+ await (0, import_promises8.writeFile)(
3210
3737
  outputPath,
3211
3738
  JSON.stringify(outputTasks, null, 2),
3212
3739
  "utf-8"
3213
3740
  );
3214
- console.log(import_chalk4.default.green(`\u2713 Converted ${file} -> ${outputPath}`));
3741
+ console.log(import_chalk5.default.green(`\u2713 Converted "${file}" -> "${outputPath}"`));
3215
3742
  } catch (error) {
3216
3743
  console.error(
3217
- import_chalk4.default.red(`\u2717 Failed to process ${file}:`),
3744
+ import_chalk5.default.red(`\u2717 Failed to process "${file}":`),
3218
3745
  error instanceof Error ? error.message : error
3219
3746
  );
3220
3747
  }
3221
3748
  }
3222
- console.log(import_chalk4.default.green("\n\u2713 Conversion completed!"));
3749
+ console.log(import_chalk5.default.green("\n\u2713 Conversion completed!"));
3223
3750
  }
3224
- var import_promises7, import_path9, import_chalk4;
3225
- var init_impl4 = __esm({
3751
+ var import_promises8, import_path10, import_chalk5;
3752
+ var init_impl5 = __esm({
3226
3753
  "src/commands/toLabelStudio/impl.ts"() {
3227
3754
  "use strict";
3228
3755
  init_cjs_shims();
3229
- import_promises7 = require("fs/promises");
3230
- import_path9 = require("path");
3231
- import_chalk4 = __toESM(require("chalk"), 1);
3756
+ import_promises8 = require("fs/promises");
3757
+ import_path10 = require("path");
3758
+ import_chalk5 = __toESM(require("chalk"), 1);
3232
3759
  init_constants();
3233
3760
  init_lib();
3234
3761
  init_backup_utils();
@@ -3238,15 +3765,15 @@ var init_impl4 = __esm({
3238
3765
 
3239
3766
  // src/bin/bash-complete.ts
3240
3767
  init_cjs_shims();
3241
- var import_core6 = require("@stricli/core");
3768
+ var import_core7 = require("@stricli/core");
3242
3769
 
3243
3770
  // src/app.ts
3244
3771
  init_cjs_shims();
3245
3772
  var import_auto_complete = require("@stricli/auto-complete");
3246
- var import_core5 = require("@stricli/core");
3773
+ var import_core6 = require("@stricli/core");
3247
3774
 
3248
3775
  // package.json
3249
- var version = "1.4.0";
3776
+ var version = "1.5.0";
3250
3777
  var description = "Convert between Label Studio OCR format and PPOCRLabelv2 format";
3251
3778
 
3252
3779
  // src/commands/enhance-labelstudio/command.ts
@@ -3337,14 +3864,61 @@ var enhancePPOCRCommand = (0, import_core2.buildCommand)({
3337
3864
  }
3338
3865
  });
3339
3866
 
3340
- // src/commands/toLabelStudio/command.ts
3867
+ // src/commands/labelStudioOutputToPPOCR/commands.ts
3341
3868
  init_cjs_shims();
3342
3869
  var import_core3 = require("@stricli/core");
3870
+ var import_es_toolkit5 = require("es-toolkit");
3343
3871
  init_constants();
3344
3872
  init_lib();
3345
- var toLabelStudioCommand = (0, import_core3.buildCommand)({
3873
+ var labelStudioOutputToPPOCRCommand = (0, import_core3.buildCommand)({
3346
3874
  loader: async () => {
3347
- const { convertToLabelStudio: convertToLabelStudio2 } = await Promise.resolve().then(() => (init_impl4(), impl_exports4));
3875
+ const { labelStudioOutputToPPOCR: labelStudioOutputToPPOCR2 } = await Promise.resolve().then(() => (init_impl4(), impl_exports4));
3876
+ return labelStudioOutputToPPOCR2;
3877
+ },
3878
+ parameters: {
3879
+ positional: {
3880
+ kind: "array",
3881
+ parameter: {
3882
+ brief: "Input directories containing Label Studio files",
3883
+ parse: String
3884
+ },
3885
+ minimum: 1
3886
+ },
3887
+ flags: {
3888
+ ...(0, import_es_toolkit5.pick)(baseFileIOFlagOptions, ["recursive", "backup", "filePattern"]),
3889
+ outDir: {
3890
+ kind: "parsed",
3891
+ brief: "Output directory.",
3892
+ parse: String,
3893
+ optional: false
3894
+ },
3895
+ fileName: {
3896
+ kind: "parsed",
3897
+ brief: `Output PPOCR file name. Default: "${DEFAULT_PPOCR_FILE_NAME}"`,
3898
+ parse: String,
3899
+ optional: true
3900
+ },
3901
+ removeBaseImageDir: {
3902
+ kind: "parsed",
3903
+ parse: String,
3904
+ brief: `Remove base image directory from image paths in output. Default: "${DEFAULT_LABEL_STUDIO_OUTPUT_IMAGE_BASE_DIR}"`,
3905
+ optional: true
3906
+ }
3907
+ }
3908
+ },
3909
+ docs: {
3910
+ brief: "Convert Label Studio output files to PPOCRLabel format"
3911
+ }
3912
+ });
3913
+
3914
+ // src/commands/toLabelStudio/command.ts
3915
+ init_cjs_shims();
3916
+ var import_core4 = require("@stricli/core");
3917
+ init_constants();
3918
+ init_lib();
3919
+ var toLabelStudioCommand = (0, import_core4.buildCommand)({
3920
+ loader: async () => {
3921
+ const { convertToLabelStudio: convertToLabelStudio2 } = await Promise.resolve().then(() => (init_impl5(), impl_exports5));
3348
3922
  return convertToLabelStudio2;
3349
3923
  },
3350
3924
  parameters: {
@@ -3419,10 +3993,10 @@ var toLabelStudioCommand = (0, import_core3.buildCommand)({
3419
3993
 
3420
3994
  // src/commands/toPPOCR/commands.ts
3421
3995
  init_cjs_shims();
3422
- var import_core4 = require("@stricli/core");
3996
+ var import_core5 = require("@stricli/core");
3423
3997
  init_constants();
3424
3998
  init_lib();
3425
- var toPPOCRCommand = (0, import_core4.buildCommand)({
3999
+ var toPPOCRCommand = (0, import_core5.buildCommand)({
3426
4000
  loader: async () => {
3427
4001
  const { convertToPPOCR: convertToPPOCR2 } = await Promise.resolve().then(() => (init_impl(), impl_exports));
3428
4002
  return convertToPPOCR2;
@@ -3465,12 +4039,13 @@ var toPPOCRCommand = (0, import_core4.buildCommand)({
3465
4039
  });
3466
4040
 
3467
4041
  // src/app.ts
3468
- var routes = (0, import_core5.buildRouteMap)({
4042
+ var routes = (0, import_core6.buildRouteMap)({
3469
4043
  routes: {
3470
4044
  toLabelStudio: toLabelStudioCommand,
3471
4045
  toPPOCR: toPPOCRCommand,
3472
4046
  "enhance-labelstudio": enhanceLabelStudioCommand,
3473
4047
  "enhance-ppocr": enhancePPOCRCommand,
4048
+ "label-studio-output-to-ppocr": labelStudioOutputToPPOCRCommand,
3474
4049
  install: (0, import_auto_complete.buildInstallCommand)("label-studio-converter", {
3475
4050
  bash: "__label-studio-converter_bash_complete"
3476
4051
  }),
@@ -3484,7 +4059,7 @@ var routes = (0, import_core5.buildRouteMap)({
3484
4059
  }
3485
4060
  }
3486
4061
  });
3487
- var app = (0, import_core5.buildApplication)(routes, {
4062
+ var app = (0, import_core6.buildApplication)(routes, {
3488
4063
  name: "label-studio-converter",
3489
4064
  versionInfo: {
3490
4065
  currentVersion: version
@@ -3511,9 +4086,9 @@ function buildContext(process2) {
3511
4086
  if (process.env.COMP_LINE?.endsWith(" ")) {
3512
4087
  inputs.push("");
3513
4088
  }
3514
- await (0, import_core6.proposeCompletions)(app, inputs, buildContext(process));
4089
+ await (0, import_core7.proposeCompletions)(app, inputs, buildContext(process));
3515
4090
  try {
3516
- for (const { completion } of await (0, import_core6.proposeCompletions)(
4091
+ for (const { completion } of await (0, import_core7.proposeCompletions)(
3517
4092
  app,
3518
4093
  inputs,
3519
4094
  buildContext(process)