Skip to content

Commit f25c635

Browse files
committed
Add image rescaling
1 parent 5d8f044 commit f25c635

File tree

1 file changed

+131
-22
lines changed

1 file changed

+131
-22
lines changed

src/ui/image.cpp

Lines changed: 131 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,18 @@
77
//
88
// Copyright(C) 2002-2019 Chris Warren-Smith.
99

10+
#include "common/sberr.h"
1011
#include "common/sys.h"
1112
#include "common/messages.h"
1213
#include "common/pproc.h"
1314
#include "common/fs_socket_client.h"
15+
#include "include/var.h"
1416
#include "lib/maapi.h"
1517
#include "lib/lodepng/lodepng.h"
1618
#include "ui/image.h"
1719
#include "ui/system.h"
1820
#include "ui/rgb.h"
21+
#include <cstdint>
1922

2023
#define IMG_X "x"
2124
#define IMG_Y "y"
@@ -211,9 +214,46 @@ ImageBuffer *get_image(unsigned bid) {
211214
return result;
212215
}
213216

217+
void scaleImage(ImageBuffer* image, var_num_t scaling) {
218+
if(scaling == 1.0 || scaling <= 0.0) {
219+
return;
220+
}
221+
222+
uint16_t xx, yy, w, h;
223+
uint32_t offsetImage, offsetScaledImage;
224+
225+
w = round((var_num_t)image->_width * scaling);
226+
h = round((var_num_t)image->_height * scaling);
227+
228+
uint8_t* scaledImage = (uint8_t *)malloc(w * h * 4);
229+
if(!scaledImage) {
230+
err_throw(ERR_IMAGE_LOAD, "Failed to allocate RAM");
231+
}
232+
233+
uint32_t* image32bit = (uint32_t*)image->_image;
234+
uint32_t* scaledImage32bit = (uint32_t*)scaledImage;
235+
236+
for(yy = 0; yy < h; yy++) {
237+
for(xx = 0; xx < w; xx++) {
238+
offsetScaledImage = yy * w + xx;
239+
offsetImage = floor((var_num_t)yy / scaling) * image->_width + floor((var_num_t)xx / scaling);
240+
scaledImage32bit[offsetScaledImage] = image32bit[offsetImage];
241+
}
242+
}
243+
244+
free(image->_image);
245+
image->_width = w;
246+
image->_height = h;
247+
image->_image = scaledImage;
248+
}
249+
250+
//
251+
// Copy from screen
252+
//
214253
ImageBuffer *load_image(var_int_t x) {
215254
var_int_t y, w, h;
216-
int count = par_massget("iii", &y, &w, &h);
255+
var_num_t scaling = 1.0;
256+
int count = par_massget("iiif", &y, &w, &h, &scaling);
217257
int width = g_system->getOutput()->getWidth();
218258
int height = g_system->getOutput()->getHeight();
219259
ImageBuffer *result = nullptr;
@@ -238,49 +278,90 @@ ImageBuffer *load_image(var_int_t x) {
238278
result->_height = h;
239279
result->_filename = nullptr;
240280
result->_image = image;
281+
scaleImage(result, scaling);
241282
buffers.add(result);
242283
}
243284
}
244285
return result;
245286
}
246287

288+
//
247289
// share image buffer from another image variable
290+
//
248291
ImageBuffer *load_image(var_t *var) {
249292
ImageBuffer *result = nullptr;
293+
var_num_t scaling = 1.0;
294+
295+
if (code_peek() == kwTYPE_SEP) {
296+
code_skipsep();
297+
scaling = par_getnum();
298+
}
299+
250300
if (var->type == V_MAP) {
251301
int bid = map_get_int(var, IMG_BID, -1);
252302
if (bid != -1) {
253-
result = get_image((unsigned)bid);
303+
if(scaling == 1.0 || scaling <= 0.0) {
304+
result = get_image((unsigned)bid);
305+
} else {
306+
ImageBuffer *inputImage = nullptr;
307+
inputImage = get_image((unsigned)bid);
308+
uint8_t* imageData = (uint8_t *)malloc(inputImage->_width * inputImage->_height * 4);
309+
if(!imageData) {
310+
err_throw(ERR_IMAGE_LOAD, "Failed to allocate RAM");
311+
}
312+
result = new ImageBuffer;
313+
result->_bid = ++nextId;
314+
result->_width = inputImage->_width;
315+
result->_height = inputImage->_height;
316+
result->_filename = nullptr;
317+
memcpy(imageData, inputImage->_image, inputImage->_width * inputImage->_height * 4);
318+
result->_image = imageData;
319+
scaleImage(result, scaling);
320+
buffers.add(result);
321+
}
254322
}
255323
} else if (var->type == V_ARRAY && v_maxdim(var) == 2) {
256324
int h = ABS(v_ubound(var, 0) - v_lbound(var, 0)) + 1;
257325
int w = ABS(v_ubound(var, 1) - v_lbound(var, 1)) + 1;
258326
int size = w * h * 4;
259-
auto image = (uint8_t *)malloc(size);
327+
auto imageData = (uint8_t *)malloc(size);
328+
if(!imageData) {
329+
err_throw(ERR_IMAGE_LOAD, "Failed to allocate RAM");
330+
}
260331
for (int y = 0; y < h; y++) {
261332
int yoffs = (y * w * 4);
262333
for (int x = 0; x < w; x++) {
263334
int pos = y * w + x;
264335
uint8_t a, r, g, b;
265336
v_get_argb(v_getint(v_elem(var, pos)), a, r, g, b);
266-
SET_IMAGE_ARGB(image, yoffs + (x * 4), a, r, g, b);
337+
SET_IMAGE_ARGB(imageData, yoffs + (x * 4), a, r, g, b);
267338
}
268339
}
269340
result = new ImageBuffer();
270341
result->_bid = ++nextId;
271342
result->_width = w;
272343
result->_height = h;
273344
result->_filename = nullptr;
274-
result->_image = image;
345+
result->_image = imageData;
346+
scaleImage(result, scaling);
275347
buffers.add(result);
276348
}
277349
return result;
278350
}
279351

352+
//
353+
// Load from file
354+
//
280355
ImageBuffer *load_image(const unsigned char *buffer, int32_t size) {
281356
ImageBuffer *result = nullptr;
282357
unsigned w, h;
283358
unsigned char *image;
359+
var_num_t scaling = 1.0;
360+
361+
if (code_peek() == kwTYPE_SEP) {
362+
code_skipsep();
363+
scaling = par_getnum();
364+
}
284365

285366
unsigned error = decode_png(&image, &w, &h, buffer, size);
286367
if (!error) {
@@ -290,26 +371,38 @@ ImageBuffer *load_image(const unsigned char *buffer, int32_t size) {
290371
result->_height = h;
291372
result->_filename = nullptr;
292373
result->_image = image;
374+
scaleImage(result, scaling);
293375
buffers.add(result);
294376
} else {
295377
err_throw(ERR_IMAGE_LOAD, lodepng_error_text(error));
296378
}
297379
return result;
298380
}
299381

382+
//
383+
// Load from file
384+
//
300385
ImageBuffer *load_image(dev_file_t *filep) {
301386
ImageBuffer *result = nullptr;
302-
List_each(ImageBuffer *, it, buffers) {
303-
ImageBuffer *next = (*it);
304-
if (next->_filename != nullptr && strcmp(next->_filename, filep->name) == 0) {
305-
result = next;
306-
break;
307-
}
387+
var_num_t scaling = 1.0;
388+
389+
if (code_peek() == kwTYPE_SEP) {
390+
code_skipsep();
391+
scaling = par_getnum();
308392
}
309393

394+
if(scaling == 1.0 || scaling <= 0.0) {
395+
List_each(ImageBuffer *, it, buffers) {
396+
ImageBuffer *next = (*it);
397+
if (next->_filename != nullptr && strcmp(next->_filename, filep->name) == 0) {
398+
result = next;
399+
break;
400+
}
401+
}
402+
}
310403
if (result == nullptr) {
311404
unsigned w, h;
312-
unsigned char *image;
405+
unsigned char *imageData;
313406
unsigned error = 0;
314407
unsigned network_error = 0;
315408
var_t *var_p;
@@ -322,13 +415,13 @@ ImageBuffer *load_image(dev_file_t *filep) {
322415
} else {
323416
var_p = v_new();
324417
http_read(filep, var_p);
325-
error = decode_png(&image, &w, &h, (unsigned char *)var_p->v.p.ptr, var_p->v.p.length);
418+
error = decode_png(&imageData, &w, &h, (unsigned char *)var_p->v.p.ptr, var_p->v.p.length);
326419
v_free(var_p);
327420
v_detach(var_p);
328421
}
329422
break;
330423
case ft_stream:
331-
error = decode_png_file(&image, &w, &h, filep->name);
424+
error = decode_png_file(&imageData, &w, &h, filep->name);
332425
break;
333426
default:
334427
error = 1;
@@ -344,25 +437,37 @@ ImageBuffer *load_image(dev_file_t *filep) {
344437
result->_width = w;
345438
result->_height = h;
346439
result->_filename = strdup(filep->name);
347-
result->_image = image;
440+
result->_image = imageData;
441+
scaleImage(result, scaling);
348442
buffers.add(result);
349443
}
350444
}
351445
return result;
352446
}
353447

448+
//
449+
// Create from XPM data
450+
//
354451
ImageBuffer *load_xpm_image(char **data) {
355452
unsigned w, h;
356453
unsigned char *image;
357454
unsigned error = xpm_decode32(&image, &w, &h, data);
358455
ImageBuffer *result = nullptr;
456+
var_num_t scaling = 1.0;
457+
458+
if (code_peek() == kwTYPE_SEP) {
459+
code_skipsep();
460+
scaling = par_getnum();
461+
}
462+
359463
if (!error) {
360464
result = new ImageBuffer();
361465
result->_bid = ++nextId;
362466
result->_width = w;
363467
result->_height = h;
364468
result->_filename = nullptr;
365469
result->_image = image;
470+
scaleImage(result, scaling);
366471
buffers.add(result);
367472
} else {
368473
err_throw(ERR_IMAGE_LOAD, ERR_XPM_IMAGE);
@@ -480,7 +585,7 @@ void cmd_image_save(var_s *self, var_s *) {
480585
if (!prog_error &&
481586
!encode_png_file(str.v.p.ptr, image->_image, w, h)) {
482587
saved = true;
483-
}
588+
}
484589
v_free(&str);
485590
break;
486591
default:
@@ -493,7 +598,7 @@ void cmd_image_save(var_s *self, var_s *) {
493598
uint32_t offsetTop = map_get_int(self, IMG_OFFSET_TOP, 0);
494599
uint32_t wClip = map_get_int(self, IMG_WIDTH, w);
495600
uint32_t hClip = map_get_int(self, IMG_HEIGHT, h);
496-
601+
497602
if (offsetTop < h && offsetLeft < w) {
498603
if (offsetTop + hClip > h) {
499604
hClip = h - offsetTop;
@@ -512,15 +617,15 @@ void cmd_image_save(var_s *self, var_s *) {
512617
uint8_t a, r, g, b;
513618
GET_IMAGE_ARGB(image->_image, yoffs + (x * 4), a, r, g, b);
514619
pixel_t px = v_get_argb_px(a, r, g, b);
515-
unsigned pos = (y - offsetTop ) * wClip + (x - offsetLeft);
620+
unsigned pos = (y - offsetTop ) * wClip + (x - offsetLeft);
516621
v_setint(v_elem(var, pos), px);
517622
}
518623
}
519624
} else {
520625
v_tomatrix(var, hClip, wClip);
521626
}
522627
saved = true;
523-
}
628+
}
524629
}
525630
}
526631
if (!saved) {
@@ -659,22 +764,23 @@ extern "C" void v_create_image(var_p_t var) {
659764
image = load_image(filep);
660765
}
661766
break;
662-
663767
case kwTYPE_LINE:
664768
case kwTYPE_EOC:
665769
break;
666-
667770
default:
668771
v_init(&arg);
669772
eval(&arg);
773+
670774
if (arg.type == V_STR && !prog_error) {
775+
// Img = Image(FileName)
671776
dev_file_t file;
672777
strlcpy(file.name, arg.v.p.ptr, sizeof(file.name));
673778
file.type = ft_stream;
674779
image = load_image(&file);
675780
} else if (arg.type == V_ARRAY && v_asize(&arg) > 0 && !prog_error) {
676781
var_p_t elem0 = v_elem(&arg, 0);
677782
if (elem0->type == V_STR) {
783+
// Img = Image(PixmapData)
678784
char **data = new char*[v_asize(&arg)];
679785
for (unsigned i = 0; i < v_asize(&arg); i++) {
680786
var_p_t elem = v_elem(&arg, i);
@@ -683,9 +789,10 @@ extern "C" void v_create_image(var_p_t var) {
683789
image = load_xpm_image(data);
684790
delete [] data;
685791
} else if (v_maxdim(&arg) == 2) {
686-
// load from 2d array
792+
// Img = Image(Array2D)
687793
image = load_image(&arg);
688794
} else if (elem0->type == V_INT) {
795+
// Create from buffer?
689796
auto *data = new unsigned char[v_asize(&arg)];
690797
for (unsigned i = 0; i < v_asize(&arg); i++) {
691798
var_p_t elem = v_elem(&arg, i);
@@ -695,8 +802,10 @@ extern "C" void v_create_image(var_p_t var) {
695802
delete [] data;
696803
}
697804
} else if (arg.type == V_INT && !prog_error) {
805+
// Copy from screen
698806
image = load_image(arg.v.i);
699807
} else {
808+
// Img2 = image(Img1) -> Img2 is pointer to existing buffer Img1
700809
image = load_image(&arg);
701810
}
702811
v_free(&arg);

0 commit comments

Comments
 (0)