|
29 | 29 | ***********************************************************************/
|
30 | 30 |
|
31 | 31 | #include "sys-core.h"
|
| 32 | +#include "reb-codec.h" |
| 33 | + |
32 | 34 |
|
33 | 35 | typedef struct REBCLR {
|
34 | 36 | union {
|
@@ -170,3 +172,164 @@ typedef struct REBCLR {
|
170 | 172 |
|
171 | 173 | return R_ARG1;
|
172 | 174 | }
|
| 175 | + |
| 176 | +/*********************************************************************** |
| 177 | +** |
| 178 | +*/ REBNATIVE(image) |
| 179 | +/* |
| 180 | +// image: native [ |
| 181 | +// "Interface to basic image encoding/decoding (only on Windows so far!)" |
| 182 | +// /load "Image file to load or binary to decode" |
| 183 | +// src-file [file! binary!] |
| 184 | +// /save "Encodes image to file or binary" |
| 185 | +// dst-file [none! file! binary!] "If NONE is used, binary is made internally" |
| 186 | +// dst-image [none! image!] "If NONE, loaded image may be used if there is any" |
| 187 | +// /frame "Some image formats may contain multiple images" |
| 188 | +// num [integer!] "1-based index of the image to receive" |
| 189 | +// /as "Used to define which codec should be used" |
| 190 | +// type [word!] "One of: [PNG JPEG JPEGXR BMP DDS GIF TIFF] read only: [DNG ICO HEIF]" |
| 191 | +// /scale |
| 192 | +// sc [pair! percent!] |
| 193 | +// ] |
| 194 | +***********************************************************************/ |
| 195 | +{ |
| 196 | + REBOOL ref_load = D_REF(1); |
| 197 | + REBVAL *val_src_file = D_ARG(2); |
| 198 | + REBOOL ref_save = D_REF(3); |
| 199 | + REBVAL *val_dest = D_ARG(4); |
| 200 | + REBVAL *val_dst_img = D_ARG(5); |
| 201 | + REBOOL ref_frame = D_REF(6); |
| 202 | + REBVAL *val_frame = D_ARG(7); |
| 203 | + REBOOL ref_as = D_REF(8); |
| 204 | + REBVAL *val_type = D_ARG(9); |
| 205 | + REBOOL ref_scale = D_REF(10); |
| 206 | + REBVAL *val_scale = D_ARG(11); |
| 207 | + |
| 208 | + REBCDI codi; |
| 209 | + REBSER *ser = NULL; |
| 210 | + REBCNT frm = ref_frame ? VAL_INT32(val_frame) - 1 : 0; |
| 211 | + REBVAL *ret = D_RET; |
| 212 | + REBCNT length; |
| 213 | + |
| 214 | + |
| 215 | +#if defined(TO_WINDOWS) && defined(USE_NATIVE_IMAGE_CODECS) |
| 216 | + CLEARS(&codi); |
| 217 | + if (ref_as) { |
| 218 | + switch (VAL_WORD_CANON(val_type)) { |
| 219 | + case SYM_PNG: codi.type = CODI_IMG_PNG; break; |
| 220 | + case SYM_JPEG: |
| 221 | + case SYM_JPG: codi.type = CODI_IMG_JPEG; break; |
| 222 | + case SYM_JPEGXR: |
| 223 | + case SYM_HDP: |
| 224 | + case SYM_JXR: codi.type = CODI_IMG_JXR; break; |
| 225 | + case SYM_BMP: codi.type = CODI_IMG_BMP; break; |
| 226 | + case SYM_GIF: codi.type = CODI_IMG_GIF; break; |
| 227 | + case SYM_DDS: codi.type = CODI_IMG_DDS; break; |
| 228 | + case SYM_DNG: codi.type = CODI_IMG_DNG; break; |
| 229 | + case SYM_TIFF: codi.type = CODI_IMG_TIFF; break; |
| 230 | + case SYM_HEIF: codi.type = CODI_IMG_HEIF; break; |
| 231 | + case SYM_WEBP: codi.type = CODI_IMG_WEBP; break; |
| 232 | + case SYM_ICO: codi.type = CODI_IMG_ICO; break; |
| 233 | + default: |
| 234 | + Trap1(RE_BAD_FUNC_ARG, val_type); |
| 235 | + } |
| 236 | + } |
| 237 | + if (ref_load) { |
| 238 | + |
| 239 | + if (IS_FILE(val_src_file)) { |
| 240 | + ser = Value_To_Local_Path(val_src_file, TRUE); |
| 241 | + } else { |
| 242 | + // raw binary data |
| 243 | + codi.data = VAL_BIN(val_src_file); |
| 244 | + codi.len = VAL_LEN(val_src_file); |
| 245 | + } |
| 246 | + |
| 247 | + OS_Load_Image(ser ? SERIES_DATA(ser) : NULL, frm, &codi); |
| 248 | + |
| 249 | + if(codi.error) { |
| 250 | + switch (codi.error) { |
| 251 | + case WINCODEC_ERR_COMPONENTNOTFOUND: |
| 252 | + Trap1(RE_NO_CODEC, val_type); |
| 253 | + break; |
| 254 | + default: |
| 255 | + SET_INTEGER(D_RET, codi.error); |
| 256 | + if (IS_BINARY(val_src_file)) { |
| 257 | + Trap1(RE_NO_CODEC, D_RET); |
| 258 | + } else { |
| 259 | + Trap2(RE_CANNOT_OPEN, val_src_file, D_RET); // need better!!! |
| 260 | + } |
| 261 | + } |
| 262 | + } else { |
| 263 | + ser = Make_Image(codi.w, codi.h, TRUE); |
| 264 | + memcpy(IMG_DATA(ser), codi.data, codi.w * codi.h * 4); |
| 265 | + SET_IMAGE(D_RET, ser); |
| 266 | + free(codi.data); |
| 267 | + codi.data = NULL; |
| 268 | + } |
| 269 | + } |
| 270 | + if (ref_save) { |
| 271 | + codi.bits = VAL_IMAGE_BITS(val_dst_img); |
| 272 | + codi.w = VAL_IMAGE_WIDE(val_dst_img); |
| 273 | + codi.h = VAL_IMAGE_HIGH(val_dst_img); |
| 274 | + |
| 275 | + if (IS_FILE(val_dest)) { |
| 276 | + ser = Value_To_Local_Path(val_dest, TRUE); |
| 277 | + } else { |
| 278 | + // raw binary data... |
| 279 | + // ... predict number of bytes large enough to hold the result |
| 280 | + length = (codi.w * codi.h * 4) + 1024; |
| 281 | + if (IS_NONE(val_dest)) { |
| 282 | + ser = Make_Binary(length); |
| 283 | + SET_BINARY(val_dest, ser); |
| 284 | + codi.len = length; |
| 285 | + } else { |
| 286 | + ser = VAL_SERIES(val_dest); |
| 287 | + REBCNT avail = SERIES_REST(ser) - VAL_INDEX(val_dest); |
| 288 | + if (length > avail) { |
| 289 | + Extend_Series(ser, length - avail); |
| 290 | + avail = SERIES_REST(ser) - VAL_INDEX(val_dest); |
| 291 | + } |
| 292 | + codi.len = avail; |
| 293 | + } |
| 294 | + codi.data = VAL_BIN_AT(val_dest); |
| 295 | + } |
| 296 | + |
| 297 | + //if (ref_scale) { |
| 298 | + // if (IS_PERCENT(val_scale)) { |
| 299 | + // codi.w *= VAL_DECIMAL(val_scale); |
| 300 | + // codi.h *= VAL_DECIMAL(val_scale); |
| 301 | + // } else { |
| 302 | + // codi.w = VAL_PAIR_X_INT(val_scale); |
| 303 | + // codi.h = VAL_PAIR_Y_INT(val_scale); |
| 304 | + // } |
| 305 | + //} |
| 306 | + |
| 307 | + OS_Save_Image(IS_FILE(val_dest) ? SERIES_DATA(ser) : NULL, &codi); |
| 308 | + |
| 309 | + if(codi.error) { |
| 310 | + switch (codi.error) { |
| 311 | + case WINCODEC_ERR_COMPONENTNOTFOUND: |
| 312 | + Trap1(RE_NO_CODEC, val_type); |
| 313 | + break; |
| 314 | + default: |
| 315 | + SET_INTEGER(D_RET, codi.error); |
| 316 | + if (IS_BINARY(val_dest)) { |
| 317 | + Trap1(RE_NO_CODEC, D_RET); |
| 318 | + } else { |
| 319 | + Trap2(RE_CANNOT_OPEN, val_dest, D_RET); // need better!!! |
| 320 | + } |
| 321 | + } |
| 322 | + } |
| 323 | + |
| 324 | + if (IS_BINARY(val_dest)) { |
| 325 | + REBCNT tail = codi.len + VAL_INDEX(val_dest); |
| 326 | + if (tail > SERIES_TAIL(ser)) |
| 327 | + SERIES_TAIL(ser) = tail; |
| 328 | + } |
| 329 | + *D_RET = *val_dest; |
| 330 | + } |
| 331 | +#else |
| 332 | + Trap0(RE_FEATURE_NA); |
| 333 | +#endif |
| 334 | + return R_RET; |
| 335 | +} |
0 commit comments