@@ -80,6 +80,10 @@ typedef struct _VipsForeignLoadJp2k {
80
80
int page ;
81
81
int shrink ;
82
82
83
+ /* Load images a frame at a time rather than a tile at a time.
84
+ */
85
+ gboolean oneshot ;
86
+
83
87
/* Decompress state.
84
88
*/
85
89
opj_stream_t * stream ; /* Source as an opj stream */
@@ -279,7 +283,12 @@ vips_foreign_load_jp2k_is_a_source(VipsSource *source)
279
283
static VipsForeignFlags
280
284
vips_foreign_load_jp2k_get_flags (VipsForeignLoad * load )
281
285
{
282
- return VIPS_FOREIGN_PARTIAL ;
286
+ VipsForeignLoadJp2k * jp2k = (VipsForeignLoadJp2k * ) load ;
287
+
288
+ if (jp2k -> oneshot )
289
+ return VIPS_FOREIGN_SEQUENTIAL ;
290
+ else
291
+ return VIPS_FOREIGN_PARTIAL ;
283
292
}
284
293
285
294
/* The openjpeg info and warning callbacks are incredibly chatty.
@@ -1147,9 +1156,9 @@ vips_foreign_load_jp2k_load(VipsForeignLoad *load)
1147
1156
VipsImage * * t = (VipsImage * * )
1148
1157
vips_object_local_array (VIPS_OBJECT (load ), 3 );
1149
1158
1150
- int vips_tile_width ;
1151
- int vips_tile_height ;
1152
- int vips_tiles_across ;
1159
+ int tile_width ;
1160
+ int tile_height ;
1161
+ int tiles_across ;
1153
1162
1154
1163
#ifdef DEBUG
1155
1164
printf ("vips_foreign_load_jp2k_load:\n" );
@@ -1161,23 +1170,21 @@ vips_foreign_load_jp2k_load(VipsForeignLoad *load)
1161
1170
1162
1171
/* Untiled jp2k images need a different read API.
1163
1172
*/
1164
- if (jp2k -> info -> tw == 1 &&
1165
- jp2k -> info -> th == 1 ) {
1166
- vips_tile_width = 512 ;
1167
- vips_tile_height = 512 ;
1168
- vips_tiles_across =
1169
- VIPS_ROUND_UP (t [0 ]-> Xsize , vips_tile_width ) /
1170
- vips_tile_width ;
1173
+ if (jp2k -> oneshot ||
1174
+ (jp2k -> info -> tw == 1 && jp2k -> info -> th == 1 )) {
1175
+ tile_width = jp2k -> width ;
1176
+ tile_height = jp2k -> height ;
1177
+ tiles_across = 1 ;
1171
1178
1172
1179
if (vips_image_generate (t [0 ],
1173
1180
NULL , vips_foreign_load_jp2k_generate_untiled , NULL ,
1174
1181
jp2k , NULL ))
1175
1182
return -1 ;
1176
1183
}
1177
1184
else {
1178
- vips_tile_width = jp2k -> info -> tdx ;
1179
- vips_tile_height = jp2k -> info -> tdy ;
1180
- vips_tiles_across = jp2k -> info -> tw ;
1185
+ tile_width = jp2k -> info -> tdx ;
1186
+ tile_height = jp2k -> info -> tdy ;
1187
+ tiles_across = jp2k -> info -> tw ;
1181
1188
1182
1189
if (vips_image_generate (t [0 ],
1183
1190
NULL , vips_foreign_load_jp2k_generate_tiled , NULL ,
@@ -1189,9 +1196,9 @@ vips_foreign_load_jp2k_load(VipsForeignLoad *load)
1189
1196
* rows, plus 50%.
1190
1197
*/
1191
1198
if (vips_tilecache (t [0 ], & t [1 ],
1192
- "tile_width" , vips_tile_width ,
1193
- "tile_height" , vips_tile_height ,
1194
- "max_tiles" , 3 * vips_tiles_across ,
1199
+ "tile_width" , tile_width ,
1200
+ "tile_height" , tile_height ,
1201
+ "max_tiles" , 3 * tiles_across ,
1195
1202
NULL ))
1196
1203
return -1 ;
1197
1204
@@ -1231,6 +1238,14 @@ vips_foreign_load_jp2k_class_init(VipsForeignLoadJp2kClass *class)
1231
1238
VIPS_ARGUMENT_OPTIONAL_INPUT ,
1232
1239
G_STRUCT_OFFSET (VipsForeignLoadJp2k , page ),
1233
1240
0 , 100000 , 0 );
1241
+
1242
+ VIPS_ARG_BOOL (class , "oneshot" , 21 ,
1243
+ _ ("One-shot" ),
1244
+ _ ("Load images a frame at a time" ),
1245
+ VIPS_ARGUMENT_OPTIONAL_INPUT ,
1246
+ G_STRUCT_OFFSET (VipsForeignLoadJp2k , oneshot ),
1247
+ FALSE);
1248
+
1234
1249
}
1235
1250
1236
1251
static void
@@ -1612,6 +1627,7 @@ vips__foreign_load_jp2k_decompress(VipsImage *out,
1612
1627
* Optional arguments:
1613
1628
*
1614
1629
* * @page: %gint, load this page
1630
+ * * @oneshot: %gboolean, load pages in one-shot mode
1615
1631
* * @fail_on: #VipsFailOn, types of read error to fail on
1616
1632
*
1617
1633
* Read a JPEG2000 image. The loader supports 8, 16 and 32-bit int pixel
@@ -1624,6 +1640,10 @@ vips__foreign_load_jp2k_decompress(VipsImage *out,
1624
1640
* image and higher-numbered pages are x2 reductions. Use the metadata item
1625
1641
* "n-pages" to find the number of pyramid layers.
1626
1642
*
1643
+ * Some versions of openjpeg can fail to decode some tiled images correctly.
1644
+ * Setting @oneshot will force the loader to decode tiled images in a single
1645
+ * operation and can improve compatibility.
1646
+ *
1627
1647
* Use @fail_on to set the type of error that will cause load to fail. By
1628
1648
* default, loaders are permissive, that is, #VIPS_FAIL_ON_NONE.
1629
1649
*
@@ -1654,6 +1674,7 @@ vips_jp2kload(const char *filename, VipsImage **out, ...)
1654
1674
* Optional arguments:
1655
1675
*
1656
1676
* * @page: %gint, load this page
1677
+ * * @oneshot: %gboolean, load pages in one-shot mode
1657
1678
* * @fail_on: #VipsFailOn, types of read error to fail on
1658
1679
*
1659
1680
* Exactly as vips_jp2kload(), but read from a buffer.
@@ -1692,6 +1713,7 @@ vips_jp2kload_buffer(void *buf, size_t len, VipsImage **out, ...)
1692
1713
* Optional arguments:
1693
1714
*
1694
1715
* * @page: %gint, load this page
1716
+ * * @oneshot: %gboolean, load pages in one-shot mode
1695
1717
* * @fail_on: #VipsFailOn, types of read error to fail on
1696
1718
*
1697
1719
* Exactly as vips_jp2kload(), but read from a source.
0 commit comments