Skip to content

rename thumbnail's profile arguments #4488

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ master
- share and reuse openslide connections
- drop support for openslide 3.3
- fix vips_quadratic()
- rename `thumbnail`'s export/import profile options as input/output for
consistency
- restore vips_remosaic(), it was not being linked

8.16.1
Expand Down
6 changes: 3 additions & 3 deletions doc/using-vipsthumbnail.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ Now transform to sRGB and don't attach a profile (you can also use
`keep=none`, though that will remove *all* metadata from the image):

```bash
$ vipsthumbnail shark.jpg --export-profile srgb -o tn_shark.jpg[profile=none]
$ vipsthumbnail shark.jpg --output-profile srgb -o tn_shark.jpg[profile=none]
$ ls -l tn_shark.jpg
-rw-r–r– 1 john john 4229 Nov  9 14:33 tn_shark.jpg
```
Expand All @@ -291,7 +291,7 @@ space, even though it has no embedded profile.


```bash
$ vipsthumbnail kgdev.jpg --import-profile /my/profiles/a98.icm
$ vipsthumbnail kgdev.jpg --input-profile /my/profiles/a98.icm
```

## Final suggestion
Expand All @@ -301,6 +301,6 @@ Putting all this together, I suggest this as a sensible set of options:
```bash
$ vipsthumbnail fred.jpg \
--size 128 \
--export-profile srgb \
--output-profile srgb \
-o tn_%s.jpg[optimize_coding,keep=none]
```
92 changes: 55 additions & 37 deletions libvips/resample/thumbnail.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ typedef struct _VipsThumbnail {
gboolean no_rotate;
VipsInteresting crop;
gboolean linear;
char *export_profile;
char *import_profile;
char *output_profile;
char *input_profile;
VipsIntent intent;
VipsFailOn fail_on;

Expand Down Expand Up @@ -695,8 +695,8 @@ vips_thumbnail_build(VipsObject *object)
*/
preshrunk_page_height = vips_image_get_page_height(in);

needs_icc_transform = thumbnail->export_profile &&
(thumbnail->import_profile ||
needs_icc_transform = thumbnail->output_profile &&
(thumbnail->input_profile ||
vips_image_get_typeof(in, VIPS_META_ICC_NAME));

/* RAD needs special unpacking.
Expand All @@ -716,20 +716,20 @@ vips_thumbnail_build(VipsObject *object)
*/
have_imported = FALSE;
if (thumbnail->linear) {
/* If we are doing colour management (there's an import
/* If we are doing colour management (there's an input
* profile), then we can use XYZ PCS as the resize space.
*/
if (in->Coding == VIPS_CODING_NONE &&
(in->BandFmt == VIPS_FORMAT_UCHAR ||
in->BandFmt == VIPS_FORMAT_USHORT) &&
(vips_image_get_typeof(in, VIPS_META_ICC_NAME) ||
thumbnail->import_profile)) {
thumbnail->input_profile)) {
g_info("importing to XYZ PCS");
if (thumbnail->import_profile)
g_info("fallback input profile %s", thumbnail->import_profile);
if (thumbnail->input_profile)
g_info("fallback input profile %s", thumbnail->input_profile);

if (vips_icc_import(in, &t[2],
"input_profile", thumbnail->import_profile,
"input_profile", thumbnail->input_profile,
"embedded", TRUE,
"intent", thumbnail->intent,
"pcs", VIPS_PCS_XYZ,
Expand Down Expand Up @@ -844,11 +844,11 @@ vips_thumbnail_build(VipsObject *object)
if (have_imported) {
/* We are in PCS. Export with the output profile, if any (this
* will export with the embedded input profile if there's no
* export profile).
* output profile).
*/
g_info("exporting to device space with a profile");
if (vips_icc_export(in, &t[9],
"output_profile", thumbnail->export_profile,
"output_profile", thumbnail->output_profile,
"intent", thumbnail->intent,
"depth", 8,
NULL))
Expand All @@ -859,8 +859,8 @@ vips_thumbnail_build(VipsObject *object)
/* We can transform to the output with a pair of ICC profiles.
*/
g_info("transforming with supplied profiles");
if (vips_icc_transform(in, &t[9], thumbnail->export_profile,
"input_profile", thumbnail->import_profile,
if (vips_icc_transform(in, &t[9], thumbnail->output_profile,
"input_profile", thumbnail->input_profile,
"intent", thumbnail->intent,
"embedded", TRUE,
"depth", 8,
Expand All @@ -869,14 +869,14 @@ vips_thumbnail_build(VipsObject *object)

in = t[9];
}
else if (thumbnail->export_profile) {
else if (thumbnail->output_profile) {
/* We are in one of the resize space (sRGB, scRGB, B_W, GREY16, etc.)
* and need to go to PCS, then export.
*/
g_info("exporting with %s", thumbnail->export_profile);
g_info("exporting with %s", thumbnail->output_profile);
if (vips_colourspace(in, &t[9], VIPS_INTERPRETATION_XYZ, NULL) ||
vips_icc_export(t[9], &t[10],
"output_profile", thumbnail->export_profile,
"output_profile", thumbnail->output_profile,
"intent", thumbnail->intent,
"depth", 8,
NULL))
Expand All @@ -885,7 +885,7 @@ vips_thumbnail_build(VipsObject *object)
}
else if (thumbnail->linear) {
/* We are in one of the scRGB or GREY16 spaces and there's
* no export profile. Output to sRGB or B_W.
* no output profile. Output to sRGB or B_W.
*/
VipsInterpretation interpretation;

Expand Down Expand Up @@ -1012,18 +1012,18 @@ vips_thumbnail_class_init(VipsThumbnailClass *class)
G_STRUCT_OFFSET(VipsThumbnail, linear),
FALSE);

VIPS_ARG_STRING(class, "import_profile", 118,
_("Import profile"),
_("Fallback import profile"),
VIPS_ARG_STRING(class, "input_profile", 118,
_("Input profile"),
_("Fallback input profile"),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET(VipsThumbnail, import_profile),
G_STRUCT_OFFSET(VipsThumbnail, input_profile),
NULL);

VIPS_ARG_STRING(class, "export_profile", 119,
_("Export profile"),
_("Fallback export profile"),
VIPS_ARG_STRING(class, "output_profile", 119,
_("Output profile"),
_("Fallback output profile"),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET(VipsThumbnail, export_profile),
G_STRUCT_OFFSET(VipsThumbnail, output_profile),
NULL);

VIPS_ARG_ENUM(class, "intent", 120,
Expand All @@ -1046,12 +1046,30 @@ vips_thumbnail_class_init(VipsThumbnailClass *class)
* This is now replaced (though still functional) with "no-rotate",
* see above.
*/
VIPS_ARG_BOOL(class, "auto_rotate", 121,
VIPS_ARG_BOOL(class, "auto_rotate", 130,
_("Auto rotate"),
_("Use orientation tags to rotate image upright"),
VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED,
G_STRUCT_OFFSET(VipsThumbnail, auto_rotate),
TRUE);

/* Renamed as input-profile and output-profile for consistency with the
* rest of the API.
*/

VIPS_ARG_STRING(class, "import_profile", 131,
_("Import profile"),
_("Fallback import profile"),
VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED,
G_STRUCT_OFFSET(VipsThumbnail, input_profile),
NULL);

VIPS_ARG_STRING(class, "export_profile", 132,
_("Export profile"),
_("Fallback export profile"),
VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED,
G_STRUCT_OFFSET(VipsThumbnail, output_profile),
NULL);
}

static void
Expand Down Expand Up @@ -1217,7 +1235,7 @@ vips_thumbnail_file_init(VipsThumbnailFile *file)
* Make a thumbnail from a file.
*
* Shrinking is done in three stages: using any
* shrink-on-load features available in the file import library, using a block
* shrink-on-load features available in the image load library, using a block
* shrink, and using a lanczos3 shrink. At least the final 200% is done with
* lanczos3. The output should be high quality, and the operation should be
* quick.
Expand Down Expand Up @@ -1256,9 +1274,9 @@ vips_thumbnail_file_init(VipsThumbnailFile *file)
* also be far slower, since tricks like JPEG shrink-on-load cannot be used in
* linear space.
*
* If you set @export_profile to the filename of an ICC profile, the image
* If you set @output_profile to the filename of an ICC profile, the image
* will be transformed to the target colourspace before writing to the
* output. You can also give an @import_profile which will be used if the
* output. You can also give an @input_profile which will be used if the
* input image has no ICC profile, or if the profile embedded in the
* input image is broken.
*
Expand All @@ -1274,8 +1292,8 @@ vips_thumbnail_file_init(VipsThumbnailFile *file)
* * @no_rotate: %gboolean, don't rotate upright using orientation tag
* * @crop: [enum@Interesting], shrink and crop to fill target
* * @linear: %gboolean, perform shrink in linear light
* * @import_profile: %gchararray, fallback import ICC profile
* * @export_profile: %gchararray, export ICC profile
* * @input_profile: %gchararray, fallback input ICC profile
* * @output_profile: %gchararray, output ICC profile
* * @intent: [enum@Intent], rendering intent
* * @fail_on: [enum@FailOn], load error types to fail on
*
Expand Down Expand Up @@ -1482,8 +1500,8 @@ vips_thumbnail_buffer_init(VipsThumbnailBuffer *buffer)
* * @no_rotate: %gboolean, don't rotate upright using orientation tag
* * @crop: [enum@Interesting], shrink and crop to fill target
* * @linear: %gboolean, perform shrink in linear light
* * @import_profile: %gchararray, fallback import ICC profile
* * @export_profile: %gchararray, export ICC profile
* * @input_profile: %gchararray, fallback input ICC profile
* * @output_profile: %gchararray, output ICC profile
* * @intent: [enum@Intent], rendering intent
* * @fail_on: [enum@FailOn], load error types to fail on
* * @option_string: %gchararray, extra loader options
Expand Down Expand Up @@ -1696,8 +1714,8 @@ vips_thumbnail_source_init(VipsThumbnailSource *source)
* * @no_rotate: %gboolean, don't rotate upright using orientation tag
* * @crop: [enum@Interesting], shrink and crop to fill target
* * @linear: %gboolean, perform shrink in linear light
* * @import_profile: %gchararray, fallback import ICC profile
* * @export_profile: %gchararray, export ICC profile
* * @input_profile: %gchararray, fallback input ICC profile
* * @output_profile: %gchararray, output ICC profile
* * @intent: [enum@Intent], rendering intent
* * @fail_on: [enum@FailOn], load error types to fail on
* * @option_string: %gchararray, extra loader options
Expand Down Expand Up @@ -1815,8 +1833,8 @@ vips_thumbnail_image_init(VipsThumbnailImage *image)
* * @no_rotate: %gboolean, don't rotate upright using orientation tag
* * @crop: [enum@Interesting], shrink and crop to fill target
* * @linear: %gboolean, perform shrink in linear light
* * @import_profile: %gchararray, fallback import ICC profile
* * @export_profile: %gchararray, export ICC profile
* * @input_profile: %gchararray, fallback input ICC profile
* * @output_profile: %gchararray, output ICC profile
* * @intent: [enum@Intent], rendering intent
* * @fail_on: [enum@FailOn], load error types to fail on
*
Expand Down
44 changes: 22 additions & 22 deletions man/vipsthumbnail.1
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ vipsthumbnail \- make thumbnails of image files
.B vipsthumbnail [flags] imagefile1 imagefile2 ...
.SH DESCRIPTION
.B vipsthumbnail(1)
processes each
processes each
.B imagefile
in turn, shrinking each image to fit within a 128 by 128 pixel square.
The shrunk image is written to a new file named
Expand All @@ -17,9 +17,9 @@ For example:

$ vipsthumbnail fred.png jim.tif

will read image files
will read image files
.B fred.png
and
and
.B jim.tif
and write thumbnails to the files
.B tn_fred.jpg
Expand All @@ -30,36 +30,36 @@ and

will read image file
.B fred.jpg
and write a 64 x 64 pixel thumbnail to the file
and write a 64 x 64 pixel thumbnail to the file
.B thumbnails/fred.png.

.SH OPTIONS
.TP
.B -s N, --size=N
Set the output thumbnail size to
.B N
x
.B N
pixels.
Set the output thumbnail size to
.B N
x
.B N
pixels.

You can use "MxN" to specify a rectangular bounding box.
The image is shrunk so that it just fits within this area, images
which are smaller than this are expanded.
which are smaller than this are expanded.

Use "xN" or "Mx" to just resize on
one axis.
one axis.

Append "<" to only resize if the input image is smaller than the
target, append ">" to only resize if the input image is larger than the target.

.TP
.B -o FORMAT, --output=FORMAT
.B -o FORMAT, --output=FORMAT
Set the output format string. The input filename has any file type suffix
removed, then that value is substituted into
removed, then that value is substituted into
.B FORMAT
replacing
.B %s.
If
.B %s.
If
.B FORMAT
is a relative path, the name of the input directory is prepended. In other
words, any path in
Expand All @@ -75,16 +75,16 @@ prepended. You can add format options too, for example
will write JPEG images with Q set to 20.

.TP
.B -e PROFILE, --eprofile=PROFILE
.B -e PROFILE, --eprofile=PROFILE
Export thumbnails with this ICC profile. Images are only colour-transformed if
there is both an output and an input profile available. The input profile can
either be embedded in the input image or supplied with the
.B --iprofile
option.

.TP
.B -i PROFILE, --iprofile=PROFILE
Import images with this ICC profile, if no profile is embedded in the image.
.B -i PROFILE, --iprofile=PROFILE
Import images with this ICC profile, if no profile is embedded in the image.
Images are only colour-transformed if
there is both an output and an input profile available. The output profile
should be supplied with the
Expand All @@ -94,20 +94,20 @@ option.
.TP
.B -c, --crop
Crop the output image down. The image is shrunk so as to completely fill the
bounding box in both axes, then any excess is cropped off.
bounding box in both axes, then any excess is cropped off.

.TP
.B -d, --delete
Delete the output profile from the image. This can save a small amount of
space.
space.

.TP
.B -t, --rotate
Auto-rotate images using EXIF orientation tags.
Auto-rotate images using EXIF orientation tags.

.TP
.B -a, --linear
Shrink images in linear light colour space. This can be much slower.
Shrink images in linear light colour space. This can be much slower.

.SH RETURN VALUE
returns 0 on success and non-zero on error. Error can mean one or more
Expand Down
2 changes: 1 addition & 1 deletion test/test-suite/test_resample.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ def test_thumbnail(self):
@pytest.mark.skipif(not pyvips.at_least_libvips(8, 5),
reason="requires libvips >= 8.5")
def test_thumbnail_icc(self):
im = pyvips.Image.thumbnail(JPEG_FILE_XYB, 442, export_profile="srgb")
im = pyvips.Image.thumbnail(JPEG_FILE_XYB, 442, output_profile="srgb")

assert im.width == 290
assert im.height == 442
Expand Down
Loading
Loading