Skip to content

Commit cc4d147

Browse files
authored
Add jp2kload oneshot (#4432)
* add oneshot to jp2kload improves compatibility with some images thanks mbklein see #4205 * revise docs and comments
1 parent d2b025c commit cc4d147

File tree

2 files changed

+42
-17
lines changed

2 files changed

+42
-17
lines changed

ChangeLog

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
master
2+
13
8.17.0
24

35
- add `keep_duplicate_frames` option to GIF save [dloebl]
@@ -16,6 +18,7 @@
1618
- convi: ensure double sum precision for floats [lovell]
1719
- improve guard against corrupt ICC profiles with older lcms2 versions [kleisauke]
1820
- heifload: improve detection of seek beyond EOF [lovell]
21+
- add "oneshot" option to jp2kload [mbklein]
1922

2023
8.16.1
2124

libvips/foreign/jp2kload.c

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ typedef struct _VipsForeignLoadJp2k {
8080
int page;
8181
int shrink;
8282

83+
/* Load images a frame at a time rather than a tile at a time.
84+
*/
85+
gboolean oneshot;
86+
8387
/* Decompress state.
8488
*/
8589
opj_stream_t *stream; /* Source as an opj stream */
@@ -279,7 +283,12 @@ vips_foreign_load_jp2k_is_a_source(VipsSource *source)
279283
static VipsForeignFlags
280284
vips_foreign_load_jp2k_get_flags(VipsForeignLoad *load)
281285
{
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;
283292
}
284293

285294
/* The openjpeg info and warning callbacks are incredibly chatty.
@@ -1147,9 +1156,9 @@ vips_foreign_load_jp2k_load(VipsForeignLoad *load)
11471156
VipsImage **t = (VipsImage **)
11481157
vips_object_local_array(VIPS_OBJECT(load), 3);
11491158

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;
11531162

11541163
#ifdef DEBUG
11551164
printf("vips_foreign_load_jp2k_load:\n");
@@ -1161,23 +1170,21 @@ vips_foreign_load_jp2k_load(VipsForeignLoad *load)
11611170

11621171
/* Untiled jp2k images need a different read API.
11631172
*/
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;
11711178

11721179
if (vips_image_generate(t[0],
11731180
NULL, vips_foreign_load_jp2k_generate_untiled, NULL,
11741181
jp2k, NULL))
11751182
return -1;
11761183
}
11771184
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;
11811188

11821189
if (vips_image_generate(t[0],
11831190
NULL, vips_foreign_load_jp2k_generate_tiled, NULL,
@@ -1189,9 +1196,9 @@ vips_foreign_load_jp2k_load(VipsForeignLoad *load)
11891196
* rows, plus 50%.
11901197
*/
11911198
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,
11951202
NULL))
11961203
return -1;
11971204

@@ -1231,6 +1238,14 @@ vips_foreign_load_jp2k_class_init(VipsForeignLoadJp2kClass *class)
12311238
VIPS_ARGUMENT_OPTIONAL_INPUT,
12321239
G_STRUCT_OFFSET(VipsForeignLoadJp2k, page),
12331240
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+
12341249
}
12351250

12361251
static void
@@ -1612,6 +1627,7 @@ vips__foreign_load_jp2k_decompress(VipsImage *out,
16121627
* Optional arguments:
16131628
*
16141629
* * @page: %gint, load this page
1630+
* * @oneshot: %gboolean, load pages in one-shot mode
16151631
* * @fail_on: #VipsFailOn, types of read error to fail on
16161632
*
16171633
* 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,
16241640
* image and higher-numbered pages are x2 reductions. Use the metadata item
16251641
* "n-pages" to find the number of pyramid layers.
16261642
*
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+
*
16271647
* Use @fail_on to set the type of error that will cause load to fail. By
16281648
* default, loaders are permissive, that is, #VIPS_FAIL_ON_NONE.
16291649
*
@@ -1654,6 +1674,7 @@ vips_jp2kload(const char *filename, VipsImage **out, ...)
16541674
* Optional arguments:
16551675
*
16561676
* * @page: %gint, load this page
1677+
* * @oneshot: %gboolean, load pages in one-shot mode
16571678
* * @fail_on: #VipsFailOn, types of read error to fail on
16581679
*
16591680
* Exactly as vips_jp2kload(), but read from a buffer.
@@ -1692,6 +1713,7 @@ vips_jp2kload_buffer(void *buf, size_t len, VipsImage **out, ...)
16921713
* Optional arguments:
16931714
*
16941715
* * @page: %gint, load this page
1716+
* * @oneshot: %gboolean, load pages in one-shot mode
16951717
* * @fail_on: #VipsFailOn, types of read error to fail on
16961718
*
16971719
* Exactly as vips_jp2kload(), but read from a source.

0 commit comments

Comments
 (0)