@@ -54,18 +54,39 @@ public void PlanSlices_WithoutBlankBand_UsesOverlapAndCoversImage() {
5454 }
5555
5656 [ Fact ]
57- public void MergeResults_RemovesRepeatedBoundaryLines ( ) {
57+ public void PlanSlices_SingleBlankRowStillUsesOverlap ( ) {
58+ using var image = CreateDenseImage ( 800 , 7000 ) ;
59+ FillRows ( image , LongImageOcrSlicer . TargetSliceHeight , LongImageOcrSlicer . TargetSliceHeight + 1 , SKColors . White ) ;
60+
61+ var slices = LongImageOcrSlicer . PlanSlices ( image ) ;
62+
63+ Assert . True ( slices [ 1 ] . HasOverlap ) ;
64+ AssertCompleteCoverage ( slices , image . Height ) ;
65+ }
66+
67+ [ Fact ]
68+ public void MergeResults_RemovesRepeatedBoundaryLinesFromOverlappingSlices ( ) {
5869 var result = LongImageOcrSlicer . MergeResults ( [
59- "第一段 重叠块一 重叠块二" ,
60- "重叠块一 重叠块二 第二段" ,
61- "第三段"
70+ ( new OcrImageSlice ( 0 , 3072 , false ) , "第一段 重叠块一 重叠块二" ) ,
71+ ( new OcrImageSlice ( 2976 , 3072 , true ) , "重叠块一 重叠块二 第二段" ) ,
72+ ( new OcrImageSlice ( 6048 , 952 , false ) , "第三段" )
6273 ] ) ;
6374
6475 Assert . Equal ( "第一段 重叠块一 重叠块二 第二段 第三段" , result ) ;
6576 }
6677
6778 [ Fact ]
68- public async Task ExecuteAsync_LongImage_RunsSlicesInOrderAndMergesResults ( ) {
79+ public void MergeResults_PreservesRepeatedBoundaryTokensWithoutOverlap ( ) {
80+ var result = LongImageOcrSlicer . MergeResults ( [
81+ ( new OcrImageSlice ( 0 , 3072 , false ) , "第一段 2026" ) ,
82+ ( new OcrImageSlice ( 3072 , 3928 , false ) , "2026 第二段" )
83+ ] ) ;
84+
85+ Assert . Equal ( "第一段 2026 2026 第二段" , result ) ;
86+ }
87+
88+ [ Fact ]
89+ public async Task ExecuteAsync_LongImage_PreservesRepeatedTokensAcrossSafeCut ( ) {
6990 var calls = new List < ( int Width , int Height ) > ( ) ;
7091 var responses = new Queue < string > ( [ "第一段 重叠块" , "重叠块 第二段" ] ) ;
7192 var service = new PaddleOCRService (
@@ -82,6 +103,19 @@ public async Task ExecuteAsync_LongImage_RunsSlicesInOrderAndMergesResults() {
82103 Assert . Equal ( 2 , calls . Count ) ;
83104 Assert . All ( calls , call => Assert . Equal ( 1000 , call . Width ) ) ;
84105 Assert . All ( calls , call => Assert . InRange ( call . Height , 1 , LongImageOcrSlicer . LongImageHeightThreshold ) ) ;
106+ Assert . Equal ( "第一段 重叠块 重叠块 第二段" , result ) ;
107+ }
108+
109+ [ Fact ]
110+ public async Task ExecuteAsync_OverlappingSlicesRemoveRepeatedBoundaryTokens ( ) {
111+ var responses = new Queue < string > ( [ "第一段 重叠块" , "重叠块 第二段" ] ) ;
112+ var service = new PaddleOCRService (
113+ Mock . Of < IConnectionMultiplexer > ( ) ,
114+ payload => Task . FromResult ( responses . Dequeue ( ) ) ) ;
115+ using var stream = Encode ( CreateDenseImage ( 1000 , 5000 ) ) ;
116+
117+ var result = await service . ExecuteAsync ( stream ) ;
118+
85119 Assert . Equal ( "第一段 重叠块 第二段" , result ) ;
86120 }
87121
@@ -121,11 +155,11 @@ public async Task ExecuteAsync_WhenSliceFails_StopsProcessing() {
121155 }
122156
123157 private static SKBitmap CreateDenseImage ( int width , int height ) {
124- var image = new SKBitmap ( width , height ) ;
125- for ( var y = 0 ; y < height ; y ++ ) {
126- for ( var x = 0 ; x < width ; x ++ ) {
127- image . SetPixel ( x , y , x % 16 < 8 ? SKColors . Black : SKColors . White ) ;
128- }
158+ var image = CreateWhiteImage ( width , height ) ;
159+ using var canvas = new SKCanvas ( image ) ;
160+ using var paint = new SKPaint { Color = SKColors . Black } ;
161+ for ( var x = 0 ; x < width ; x += 16 ) {
162+ canvas . DrawRect ( x , 0 , 8 , height , paint ) ;
129163 }
130164 return image ;
131165 }
@@ -137,11 +171,9 @@ private static SKBitmap CreateWhiteImage(int width, int height) {
137171 }
138172
139173 private static void FillRows ( SKBitmap image , int start , int end , SKColor color ) {
140- for ( var y = start ; y < end ; y ++ ) {
141- for ( var x = 0 ; x < image . Width ; x ++ ) {
142- image . SetPixel ( x , y , color ) ;
143- }
144- }
174+ using var canvas = new SKCanvas ( image ) ;
175+ using var paint = new SKPaint { Color = color } ;
176+ canvas . DrawRect ( 0 , start , image . Width , end - start , paint ) ;
145177 }
146178
147179 private static MemoryStream Encode ( SKBitmap image ) {
0 commit comments