@@ -1659,8 +1659,8 @@ wtiff_layer_write_strip( Wtiff *wtiff, Layer *layer, VipsRegion *strip )
1659
1659
int y ;
1660
1660
1661
1661
#ifdef DEBUG_VERBOSE
1662
- printf ( "Writing %d pixel strip at height %d to image %s\n" ,
1663
- height , area -> top , TIFFFileName ( layer -> tif ) );
1662
+ printf ( "wtiff_layer_write_strip: top %d, height %d, file %s\n" ,
1663
+ area -> top , height , TIFFFileName ( layer -> tif ) );
1664
1664
#endif /*DEBUG_VERBOSE*/
1665
1665
1666
1666
for ( y = 0 ; y < height ; y ++ ) {
@@ -1842,23 +1842,29 @@ layer_strip_arrived( Layer *layer )
1842
1842
return ( 0 );
1843
1843
}
1844
1844
1845
- /* Another strip of image pixels from vips_sink_disc(). Write into the top
1846
- * pyramid layer.
1845
+ /* Another few scanlines of pixels. We know the scanlines are all within the
1846
+ * current page.
1847
1847
*/
1848
1848
static int
1849
- write_strip ( VipsRegion * region , VipsRect * area , void * a )
1849
+ wtiff_write_lines ( Wtiff * wtiff , VipsRegion * region , VipsRect * lines )
1850
1850
{
1851
- Wtiff * wtiff = (Wtiff * ) a ;
1852
1851
Layer * layer = wtiff -> layer ;
1852
+ int page_top = wtiff -> page_number * wtiff -> page_height ;
1853
1853
1854
1854
#ifdef DEBUG_VERBOSE
1855
- printf ( "write_strip: strip at %d, height %d\n" ,
1856
- area -> top , area -> height );
1855
+ printf ( "wtiff_write_lines: top %d, height %d\n" ,
1856
+ lines -> top , lines -> height );
1857
1857
#endif /*DEBUG_VERBOSE*/
1858
1858
1859
+ /* Keep filling the current strip of the top layer. Each time it
1860
+ * fills, write a chunk of pyramid.
1861
+ *
1862
+ * lines is in
1863
+ */
1859
1864
for (;;) {
1860
1865
VipsRect * to = & layer -> strip -> valid ;
1861
1866
VipsRect target ;
1867
+ VipsRect page_lines ;
1862
1868
1863
1869
/* The bit of strip that needs filling.
1864
1870
*/
@@ -1868,9 +1874,15 @@ write_strip( VipsRegion *region, VipsRect *area, void *a )
1868
1874
target .height = to -> height ;
1869
1875
vips_rect_intersectrect ( & target , to , & target );
1870
1876
1871
- /* Clip against what we have available.
1877
+ /* region and lines are in world coordinates, we must subtract
1878
+ * the top of the current page to get layer coordinates.
1872
1879
*/
1873
- vips_rect_intersectrect ( & target , area , & target );
1880
+ page_lines = * lines ;
1881
+ page_lines .top -= page_top ;
1882
+
1883
+ /* Clip against the lines we've been given.
1884
+ */
1885
+ vips_rect_intersectrect ( & target , & page_lines , & target );
1874
1886
1875
1887
/* Are we empty? All done.
1876
1888
*/
@@ -1883,8 +1895,9 @@ write_strip( VipsRegion *region, VipsRect *area, void *a )
1883
1895
* received, we could skip the copy. Will this happen very
1884
1896
* often? Unclear.
1885
1897
*/
1898
+ target .top += page_top ;
1886
1899
vips_region_copy ( region , layer -> strip ,
1887
- & target , target .left , target .top );
1900
+ & target , target .left , target .top - page_top );
1888
1901
1889
1902
layer -> write_y += target .height ;
1890
1903
@@ -2113,20 +2126,18 @@ wtiff_gather( Wtiff *wtiff )
2113
2126
return ( 0 );
2114
2127
}
2115
2128
2116
- /* Write one page from our input image, optionally pyramiding it.
2117
- */
2118
2129
static int
2119
- wtiff_write_page ( Wtiff * wtiff , VipsImage * page )
2130
+ wtiff_page_start ( Wtiff * wtiff )
2120
2131
{
2121
2132
#ifdef DEBUG
2122
- printf ( "wtiff_write_page: \n" );
2133
+ printf ( "wtiff_page_start: page %d \n" , wtiff -> page_number );
2123
2134
#endif /*DEBUG*/
2124
2135
2125
2136
/* Init the pyramid framework for this page. This will just make a
2126
2137
* single layer if we're not pyramiding.
2127
2138
*/
2128
2139
wtiff_layer_init ( wtiff , & wtiff -> layer , NULL ,
2129
- page -> Xsize , page -> Ysize );
2140
+ wtiff -> ready -> Xsize , wtiff -> page_height );
2130
2141
2131
2142
/* Fill all the layers and write the TIFF headers.
2132
2143
*/
@@ -2158,8 +2169,15 @@ wtiff_write_page( Wtiff *wtiff, VipsImage *page )
2158
2169
g_free ( subifd_offsets );
2159
2170
}
2160
2171
2161
- if ( vips_sink_disc ( page , write_strip , wtiff ) )
2162
- return ( -1 );
2172
+ return ( 0 );
2173
+ }
2174
+
2175
+ static int
2176
+ wtiff_page_end ( Wtiff * wtiff )
2177
+ {
2178
+ #ifdef DEBUG
2179
+ printf ( "wtiff_page_end: page %d\n" , wtiff -> page_number );
2180
+ #endif /*DEBUG*/
2163
2181
2164
2182
if ( !TIFFWriteDirectory ( wtiff -> layer -> tif ) )
2165
2183
return ( -1 );
@@ -2188,35 +2206,70 @@ wtiff_write_page( Wtiff *wtiff, VipsImage *page )
2188
2206
VIPS_FREEF ( layer_free_all , wtiff -> layer -> below );
2189
2207
}
2190
2208
2209
+ wtiff -> page_number += 1 ;
2210
+
2191
2211
return ( 0 );
2192
2212
}
2193
2213
2194
- /* Write all pages.
2214
+ /* A strip of pixels has come in from libvips. Split these strips into pages,
2215
+ * and run the page start / end code.
2195
2216
*/
2196
2217
static int
2197
- wtiff_write_image ( Wtiff * wtiff )
2218
+ wtiff_sink_disc_strip ( VipsRegion * region , VipsRect * area , void * a )
2198
2219
{
2199
- int y ;
2220
+ Wtiff * wtiff = ( Wtiff * ) a ;
2200
2221
2201
- for ( y = 0 ; y < wtiff -> ready -> Ysize ; y += wtiff -> page_height ) {
2202
- VipsImage * page ;
2222
+ VipsRect pixels ;
2203
2223
2204
2224
#ifdef DEBUG
2205
- printf ( "writing page %d ...\n" , wtiff -> page_number );
2225
+ printf ( "wtiff_sink_disc_strip: top %d, height %d\n" ,
2226
+ area -> top , area -> height );
2206
2227
#endif /*DEBUG*/
2207
2228
2208
- if ( vips_crop ( wtiff -> ready , & page ,
2209
- 0 , y , wtiff -> ready -> Xsize , wtiff -> page_height ,
2210
- NULL ) )
2211
- return ( -1 );
2212
- if ( wtiff_write_page ( wtiff , page ) ) {
2213
- g_object_unref ( page );
2229
+ g_assert ( area -> width == wtiff -> ready -> Xsize );
2230
+
2231
+ /* Loop down this as we write scanlines into pages.
2232
+ */
2233
+ pixels = * area ;
2234
+
2235
+ do {
2236
+ VipsRect page ;
2237
+ VipsRect lines ;
2238
+
2239
+ /* The rect for the current page.
2240
+ */
2241
+ page .left = 0 ;
2242
+ page .top = wtiff -> page_height * wtiff -> page_number ;
2243
+ page .width = wtiff -> ready -> Xsize ;
2244
+ page .height = wtiff -> page_height ;
2245
+
2246
+ /* The scanlines we have for this page.
2247
+ */
2248
+ vips_rect_intersectrect ( & page , & pixels , & lines );
2249
+
2250
+ /* At the top of the page? Run the page start code.
2251
+ */
2252
+ if ( lines .top == page .top &&
2253
+ wtiff_page_start ( wtiff ) )
2214
2254
return ( -1 );
2215
- }
2216
- g_object_unref ( page );
2217
2255
2218
- wtiff -> page_number += 1 ;
2219
- }
2256
+ /* Write the scanlines into the page.
2257
+ */
2258
+ if ( wtiff_write_lines ( wtiff , region , & lines ) )
2259
+ return ( -1 );
2260
+
2261
+ /* Hit the end of the page? Run the page end code.
2262
+ */
2263
+ if ( VIPS_RECT_BOTTOM ( & page ) == VIPS_RECT_BOTTOM ( & lines ) &&
2264
+ wtiff_page_end ( wtiff ) )
2265
+ return ( -1 );
2266
+
2267
+ /* Remove the pixels we've written and loop if we have some
2268
+ * still to write.
2269
+ */
2270
+ pixels .top += lines .height ;
2271
+ pixels .height -= lines .height ;
2272
+ } while ( !vips_rect_isempty ( & pixels ) );
2220
2273
2221
2274
return ( 0 );
2222
2275
}
@@ -2257,7 +2310,7 @@ vips__tiff_write( VipsImage *input, const char *filename,
2257
2310
subifd , premultiply )) )
2258
2311
return ( -1 );
2259
2312
2260
- if ( wtiff_write_image ( wtiff ) ) {
2313
+ if ( vips_sink_disc ( wtiff -> ready , wtiff_sink_disc_strip , wtiff ) ) {
2261
2314
wtiff_free ( wtiff );
2262
2315
return ( -1 );
2263
2316
}
@@ -2303,7 +2356,7 @@ vips__tiff_write_buf( VipsImage *input,
2303
2356
wtiff -> obuf = obuf ;
2304
2357
wtiff -> olen = olen ;
2305
2358
2306
- if ( wtiff_write_image ( wtiff ) ) {
2359
+ if ( vips_sink_disc ( wtiff -> ready , wtiff_sink_disc_strip , wtiff ) ) {
2307
2360
wtiff_free ( wtiff );
2308
2361
return ( -1 );
2309
2362
}
0 commit comments