Skip to content

Commit f4a1fc6

Browse files
committed
FEAT: new resize native function for resizing images (without any external dependency)
The code was ported from GraphicsMagick (www.graphicsmagick.org). Basic usage example: ``` original-image: load %some-image.jpg resized-image-1: resize original-image 25% resized-image-2: resize original-image 100x200 ;- resized to exact size resized-image-3: resize original-image 100 ;- resized to width 100 (height is computed) resized-image-4: resize original-image 0x200 ;- resized to height 200 (width is computed) ``` By default, `Lanczos` resize filter is used. It is possible to use one of filters, which are listed in `system/catalog/filters`: Here is example how to resize the original using width 250 with all filters. Results are saved as PNG files: ``` foreach filter system/catalog/filters [ save join %image- [filter %.png] resize/filter original-image 250 filter ] ```
1 parent a55673f commit f4a1fc6

File tree

6 files changed

+1014
-5
lines changed

6 files changed

+1014
-5
lines changed

make/make-settings.r

+5-4
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ Defines: [
1212
USE_PNG_CODEC
1313
USE_GIF_CODEC
1414
USE_JPG_CODEC
15-
;USE_WAV_CODEC ;-- deprecated; using Rebol codec instead
16-
;USE_NO_INFINITY ;-- use when you don't want to support IEEE infinity
17-
USE_LZMA ;-- adds support for LZMA [de]compression
18-
USE_MIDI_DEVICE ;-- includes MIDI device when possible (Windows & macOS)
15+
;USE_WAV_CODEC ;-- deprecated; using Rebol codec instead
16+
;USE_NO_INFINITY ;-- use when you don't want to support IEEE infinity
17+
USE_LZMA ;-- adds support for LZMA [de]compression
18+
USE_MIDI_DEVICE ;-- includes MIDI device when possible (Windows & macOS)
19+
USE_IMAGE_NATIVES ;-- additional image native functions (for example `resize`)
1920

2021
;INCLUDE_TASK ;-- tasks are not implemented yet, so include it only on demand
2122
INCLUDE_BASE85 ;-- adds support for enbase/debase with base 85 (ASCII85)

src/boot/words.r

+17
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,23 @@ double
163163
control
164164
shift
165165

166+
; Filters (used in image resizing so far)
167+
point
168+
box
169+
triangle
170+
hermite
171+
hanning
172+
hamming
173+
blackman
174+
gaussian
175+
quadratic
176+
cubic
177+
catrom
178+
mitchell
179+
lanczos
180+
bessel
181+
sinc
182+
166183
; Checksum
167184
sha1
168185
sha256

src/core/n-image.c

+79-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#ifdef USE_IMAGE_NATIVES
12
/***********************************************************************
23
**
34
** REBOL [R3] Language Interpreter and Run-time Environment
@@ -30,6 +31,7 @@
3031

3132
#include "sys-core.h"
3233
#include "reb-codec.h"
34+
#include "sys-magick.h" // used for `resize` native
3335

3436

3537
typedef struct REBCLR {
@@ -196,7 +198,7 @@ typedef struct REBCLR {
196198
g2 = rgb->g;
197199
b2 = rgb->b;
198200

199-
amount0 = Clip_Dec(IS_INTEGER(val_amount) ? (REBDEC)VAL_INT64(val_amount) : VAL_DECIMAL(val_amount), 0.0, 1.0);
201+
amount0 = Clip_Dec(AS_DECIMAL(val_amount), 0.0, 1.0);
200202
amount1 = 1.0 - amount0;
201203

202204
if (IS_TUPLE(val_trg)) {
@@ -228,6 +230,80 @@ typedef struct REBCLR {
228230
return R_ARG1;
229231
}
230232

233+
/***********************************************************************
234+
**
235+
*/ REBNATIVE(resize)
236+
/*
237+
// resize: native [
238+
// "Resizes an image to the given size."
239+
// image [image!] "Image to resize"
240+
// size [pair! percent! integer!]
241+
// "Size of the new image (integer value is used as width)"
242+
// /filter "Using given filter type (default is Lanczos)"
243+
// name [word! integer!] "One of: system/catalog/filters"
244+
// /blur
245+
// factor [number!] "The blur factor where > 1 is blurry, < 1 is sharp"
246+
// ]
247+
***********************************************************************/
248+
{
249+
REBVAL *val_img = D_ARG(1);
250+
REBVAL *val_size = D_ARG(2);
251+
// REBOOL ref_filter = D_REF(3);
252+
REBVAL *val_filter = D_ARG(4);
253+
REBOOL ref_blur = D_REF(5);
254+
REBVAL *val_blur = D_ARG(6);
255+
REBSER *result;
256+
REBCNT filter = 0;
257+
REBDEC blur = 1.0;
258+
REBOOL has_alpha = Image_Has_Alpha(val_img, FALSE);
259+
REBINT wide, high;
260+
261+
if (IS_INTEGER(val_filter))
262+
filter = VAL_INT32(val_filter);
263+
else if (IS_WORD(val_filter)) {
264+
filter = VAL_WORD_CANON(val_filter) - SYM_POINT + 1;
265+
}
266+
267+
if (filter < 0 || filter > 15)
268+
Trap1(RE_INVALID_ARG, val_filter);
269+
270+
if (ref_blur) {
271+
blur = AS_DECIMAL(val_blur);
272+
blur = MIN(blur, MAX_RESIZE_BLUR);
273+
}
274+
275+
if (IS_PAIR(val_size)) {
276+
wide = VAL_PAIR_X_INT(val_size);
277+
high = VAL_PAIR_Y_INT(val_size);
278+
}
279+
else if (IS_INTEGER(val_size)) {
280+
wide = VAL_INT32(val_size);
281+
high = 0; // will be computed later
282+
}
283+
else if (IS_PERCENT(val_size)) {
284+
wide = ROUND_TO_INT(VAL_DECIMAL(val_size) * VAL_IMAGE_WIDE(val_img));
285+
high = ROUND_TO_INT(VAL_DECIMAL(val_size) * VAL_IMAGE_HIGH(val_img));
286+
}
287+
if (wide < 0 || high < 0 || (wide == 0 && high == 0))
288+
Trap1(RE_INVALID_ARG, val_size);
289+
290+
if (wide == 0) {
291+
wide = ROUND_TO_INT( VAL_IMAGE_WIDE(val_img) * high / VAL_IMAGE_HIGH(val_img) );
292+
}
293+
if (high == 0) {
294+
high = ROUND_TO_INT( VAL_IMAGE_HIGH(val_img) * wide / VAL_IMAGE_WIDE(val_img) );
295+
}
296+
297+
result = ResizeImage(VAL_SERIES(val_img), wide, high, filter, blur, has_alpha);
298+
299+
if (result == NULL) {
300+
Trap1(RE_NO_CREATE, Get_Type_Word(REB_IMAGE));
301+
}
302+
303+
SET_IMAGE(D_RET, result);
304+
return R_RET;
305+
}
306+
231307
/***********************************************************************
232308
**
233309
*/ REBNATIVE(image)
@@ -388,3 +464,5 @@ typedef struct REBCLR {
388464
#endif
389465
return R_RET;
390466
}
467+
468+
#endif // USE_IMAGE_NATIVES

0 commit comments

Comments
 (0)