7
7
//
8
8
// Copyright(C) 2002-2019 Chris Warren-Smith.
9
9
10
+ #include " common/sberr.h"
10
11
#include " common/sys.h"
11
12
#include " common/messages.h"
12
13
#include " common/pproc.h"
13
14
#include " common/fs_socket_client.h"
15
+ #include " include/var.h"
14
16
#include " lib/maapi.h"
15
17
#include " lib/lodepng/lodepng.h"
16
18
#include " ui/image.h"
17
19
#include " ui/system.h"
18
20
#include " ui/rgb.h"
21
+ #include < cstdint>
19
22
20
23
#define IMG_X " x"
21
24
#define IMG_Y " y"
@@ -211,9 +214,47 @@ ImageBuffer *get_image(unsigned bid) {
211
214
return result;
212
215
}
213
216
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
+ return ;
232
+ }
233
+
234
+ uint32_t * image32bit = (uint32_t *)image->_image ;
235
+ uint32_t * scaledImage32bit = (uint32_t *)scaledImage;
236
+
237
+ for (yy = 0 ; yy < h; yy++) {
238
+ for (xx = 0 ; xx < w; xx++) {
239
+ offsetScaledImage = yy * w + xx;
240
+ offsetImage = floor ((var_num_t )yy / scaling) * image->_width + floor ((var_num_t )xx / scaling);
241
+ scaledImage32bit[offsetScaledImage] = image32bit[offsetImage];
242
+ }
243
+ }
244
+
245
+ free (image->_image );
246
+ image->_width = w;
247
+ image->_height = h;
248
+ image->_image = scaledImage;
249
+ }
250
+
251
+ //
252
+ // Copy from screen
253
+ //
214
254
ImageBuffer *load_image (var_int_t x) {
215
255
var_int_t y, w, h;
216
- int count = par_massget (" iii" , &y, &w, &h);
256
+ var_num_t scaling = 1.0 ;
257
+ int count = par_massget (" iiif" , &y, &w, &h, &scaling);
217
258
int width = g_system->getOutput ()->getWidth ();
218
259
int height = g_system->getOutput ()->getHeight ();
219
260
ImageBuffer *result = nullptr ;
@@ -238,49 +279,92 @@ ImageBuffer *load_image(var_int_t x) {
238
279
result->_height = h;
239
280
result->_filename = nullptr ;
240
281
result->_image = image;
282
+ scaleImage (result, scaling);
241
283
buffers.add (result);
242
284
}
243
285
}
244
286
return result;
245
287
}
246
288
289
+ //
247
290
// share image buffer from another image variable
291
+ //
248
292
ImageBuffer *load_image (var_t *var) {
249
293
ImageBuffer *result = nullptr ;
294
+ var_num_t scaling = 1.0 ;
295
+
296
+ if (code_peek () == kwTYPE_SEP) {
297
+ code_skipsep ();
298
+ scaling = par_getnum ();
299
+ }
300
+
250
301
if (var->type == V_MAP) {
251
302
int bid = map_get_int (var, IMG_BID, -1 );
252
303
if (bid != -1 ) {
253
- result = get_image ((unsigned )bid);
304
+ if (scaling == 1.0 || scaling <= 0.0 ) {
305
+ result = get_image ((unsigned )bid);
306
+ } else {
307
+ ImageBuffer *inputImage = nullptr ;
308
+ inputImage = get_image ((unsigned )bid);
309
+ uint8_t * imageData = (uint8_t *)malloc (inputImage->_width * inputImage->_height * 4 );
310
+ if (!imageData) {
311
+ err_throw (ERR_IMAGE_LOAD, " Failed to allocate RAM" );
312
+ return result;
313
+ }
314
+ result = new ImageBuffer;
315
+ result->_bid = ++nextId;
316
+ result->_width = inputImage->_width ;
317
+ result->_height = inputImage->_height ;
318
+ result->_filename = nullptr ;
319
+ memcpy (imageData, inputImage->_image , inputImage->_width * inputImage->_height * 4 );
320
+ result->_image = imageData;
321
+ scaleImage (result, scaling);
322
+ buffers.add (result);
323
+ }
254
324
}
255
325
} else if (var->type == V_ARRAY && v_maxdim (var) == 2 ) {
256
326
int h = ABS (v_ubound (var, 0 ) - v_lbound (var, 0 )) + 1 ;
257
327
int w = ABS (v_ubound (var, 1 ) - v_lbound (var, 1 )) + 1 ;
258
328
int size = w * h * 4 ;
259
- auto image = (uint8_t *)malloc (size);
329
+ auto imageData = (uint8_t *)malloc (size);
330
+ if (!imageData) {
331
+ err_throw (ERR_IMAGE_LOAD, " Failed to allocate RAM" );
332
+ return result;
333
+ }
260
334
for (int y = 0 ; y < h; y++) {
261
335
int yoffs = (y * w * 4 );
262
336
for (int x = 0 ; x < w; x++) {
263
337
int pos = y * w + x;
264
338
uint8_t a, r, g, b;
265
339
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);
340
+ SET_IMAGE_ARGB (imageData , yoffs + (x * 4 ), a, r, g, b);
267
341
}
268
342
}
269
343
result = new ImageBuffer ();
270
344
result->_bid = ++nextId;
271
345
result->_width = w;
272
346
result->_height = h;
273
347
result->_filename = nullptr ;
274
- result->_image = image;
348
+ result->_image = imageData;
349
+ scaleImage (result, scaling);
275
350
buffers.add (result);
276
351
}
277
352
return result;
278
353
}
279
354
355
+ //
356
+ // Load from file
357
+ //
280
358
ImageBuffer *load_image (const unsigned char *buffer, int32_t size) {
281
359
ImageBuffer *result = nullptr ;
282
360
unsigned w, h;
283
361
unsigned char *image;
362
+ var_num_t scaling = 1.0 ;
363
+
364
+ if (code_peek () == kwTYPE_SEP) {
365
+ code_skipsep ();
366
+ scaling = par_getnum ();
367
+ }
284
368
285
369
unsigned error = decode_png (&image, &w, &h, buffer, size);
286
370
if (!error) {
@@ -290,26 +374,38 @@ ImageBuffer *load_image(const unsigned char *buffer, int32_t size) {
290
374
result->_height = h;
291
375
result->_filename = nullptr ;
292
376
result->_image = image;
377
+ scaleImage (result, scaling);
293
378
buffers.add (result);
294
379
} else {
295
380
err_throw (ERR_IMAGE_LOAD, lodepng_error_text (error));
296
381
}
297
382
return result;
298
383
}
299
384
385
+ //
386
+ // Load from file
387
+ //
300
388
ImageBuffer *load_image (dev_file_t *filep) {
301
389
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
- }
390
+ var_num_t scaling = 1.0 ;
391
+
392
+ if (code_peek () == kwTYPE_SEP) {
393
+ code_skipsep ();
394
+ scaling = par_getnum ();
308
395
}
309
396
397
+ if (scaling == 1.0 || scaling <= 0.0 ) {
398
+ List_each (ImageBuffer *, it, buffers) {
399
+ ImageBuffer *next = (*it);
400
+ if (next->_filename != nullptr && strcmp (next->_filename , filep->name ) == 0 ) {
401
+ result = next;
402
+ break ;
403
+ }
404
+ }
405
+ }
310
406
if (result == nullptr ) {
311
407
unsigned w, h;
312
- unsigned char *image ;
408
+ unsigned char *imageData ;
313
409
unsigned error = 0 ;
314
410
unsigned network_error = 0 ;
315
411
var_t *var_p;
@@ -322,13 +418,13 @@ ImageBuffer *load_image(dev_file_t *filep) {
322
418
} else {
323
419
var_p = v_new ();
324
420
http_read (filep, var_p);
325
- error = decode_png (&image , &w, &h, (unsigned char *)var_p->v .p .ptr , var_p->v .p .length );
421
+ error = decode_png (&imageData , &w, &h, (unsigned char *)var_p->v .p .ptr , var_p->v .p .length );
326
422
v_free (var_p);
327
423
v_detach (var_p);
328
424
}
329
425
break ;
330
426
case ft_stream:
331
- error = decode_png_file (&image , &w, &h, filep->name );
427
+ error = decode_png_file (&imageData , &w, &h, filep->name );
332
428
break ;
333
429
default :
334
430
error = 1 ;
@@ -344,25 +440,37 @@ ImageBuffer *load_image(dev_file_t *filep) {
344
440
result->_width = w;
345
441
result->_height = h;
346
442
result->_filename = strdup (filep->name );
347
- result->_image = image;
443
+ result->_image = imageData;
444
+ scaleImage (result, scaling);
348
445
buffers.add (result);
349
446
}
350
447
}
351
448
return result;
352
449
}
353
450
451
+ //
452
+ // Create from XPM data
453
+ //
354
454
ImageBuffer *load_xpm_image (char **data) {
355
455
unsigned w, h;
356
456
unsigned char *image;
357
457
unsigned error = xpm_decode32 (&image, &w, &h, data);
358
458
ImageBuffer *result = nullptr ;
459
+ var_num_t scaling = 1.0 ;
460
+
461
+ if (code_peek () == kwTYPE_SEP) {
462
+ code_skipsep ();
463
+ scaling = par_getnum ();
464
+ }
465
+
359
466
if (!error) {
360
467
result = new ImageBuffer ();
361
468
result->_bid = ++nextId;
362
469
result->_width = w;
363
470
result->_height = h;
364
471
result->_filename = nullptr ;
365
472
result->_image = image;
473
+ scaleImage (result, scaling);
366
474
buffers.add (result);
367
475
} else {
368
476
err_throw (ERR_IMAGE_LOAD, ERR_XPM_IMAGE);
@@ -480,7 +588,7 @@ void cmd_image_save(var_s *self, var_s *) {
480
588
if (!prog_error &&
481
589
!encode_png_file (str.v .p .ptr , image->_image , w, h)) {
482
590
saved = true ;
483
- }
591
+ }
484
592
v_free (&str);
485
593
break ;
486
594
default :
@@ -493,7 +601,7 @@ void cmd_image_save(var_s *self, var_s *) {
493
601
uint32_t offsetTop = map_get_int (self, IMG_OFFSET_TOP, 0 );
494
602
uint32_t wClip = map_get_int (self, IMG_WIDTH, w);
495
603
uint32_t hClip = map_get_int (self, IMG_HEIGHT, h);
496
-
604
+
497
605
if (offsetTop < h && offsetLeft < w) {
498
606
if (offsetTop + hClip > h) {
499
607
hClip = h - offsetTop;
@@ -512,15 +620,15 @@ void cmd_image_save(var_s *self, var_s *) {
512
620
uint8_t a, r, g, b;
513
621
GET_IMAGE_ARGB (image->_image , yoffs + (x * 4 ), a, r, g, b);
514
622
pixel_t px = v_get_argb_px (a, r, g, b);
515
- unsigned pos = (y - offsetTop ) * wClip + (x - offsetLeft);
623
+ unsigned pos = (y - offsetTop ) * wClip + (x - offsetLeft);
516
624
v_setint (v_elem (var, pos), px);
517
625
}
518
626
}
519
627
} else {
520
628
v_tomatrix (var, hClip, wClip);
521
629
}
522
630
saved = true ;
523
- }
631
+ }
524
632
}
525
633
}
526
634
if (!saved) {
@@ -646,6 +754,16 @@ void screen_dump() {
646
754
}
647
755
}
648
756
757
+ /*
758
+ * I = Image(file [,scale])
759
+ * I = Image(image [,scale])
760
+ * I = Image(x1,y1,x2,y2 [,scale])
761
+ * I = Image(pixmap [,scale])
762
+ * I = Image(array [,scale])
763
+ * scale > 1: upscale
764
+ * scale < 1: downscale
765
+ * scale <=0: don't scale
766
+ */
649
767
extern " C" void v_create_image (var_p_t var) {
650
768
var_t arg;
651
769
ImageBuffer *image = nullptr ;
@@ -659,22 +777,23 @@ extern "C" void v_create_image(var_p_t var) {
659
777
image = load_image (filep);
660
778
}
661
779
break ;
662
-
663
780
case kwTYPE_LINE:
664
781
case kwTYPE_EOC:
665
782
break ;
666
-
667
783
default :
668
784
v_init (&arg);
669
785
eval (&arg);
786
+
670
787
if (arg.type == V_STR && !prog_error) {
788
+ // Img = Image(FileName)
671
789
dev_file_t file;
672
790
strlcpy (file.name , arg.v .p .ptr , sizeof (file.name ));
673
791
file.type = ft_stream;
674
792
image = load_image (&file);
675
793
} else if (arg.type == V_ARRAY && v_asize (&arg) > 0 && !prog_error) {
676
794
var_p_t elem0 = v_elem (&arg, 0 );
677
795
if (elem0->type == V_STR) {
796
+ // Img = Image(PixmapData)
678
797
char **data = new char *[v_asize (&arg)];
679
798
for (unsigned i = 0 ; i < v_asize (&arg); i++) {
680
799
var_p_t elem = v_elem (&arg, i);
@@ -683,9 +802,10 @@ extern "C" void v_create_image(var_p_t var) {
683
802
image = load_xpm_image (data);
684
803
delete [] data;
685
804
} else if (v_maxdim (&arg) == 2 ) {
686
- // load from 2d array
805
+ // Img = Image(Array2D)
687
806
image = load_image (&arg);
688
807
} else if (elem0->type == V_INT) {
808
+ // Create from buffer?
689
809
auto *data = new unsigned char [v_asize (&arg)];
690
810
for (unsigned i = 0 ; i < v_asize (&arg); i++) {
691
811
var_p_t elem = v_elem (&arg, i);
@@ -695,8 +815,10 @@ extern "C" void v_create_image(var_p_t var) {
695
815
delete [] data;
696
816
}
697
817
} else if (arg.type == V_INT && !prog_error) {
818
+ // Copy from screen
698
819
image = load_image (arg.v .i );
699
820
} else {
821
+ // Img2 = image(Img1) -> Img2 is pointer to existing buffer Img1
700
822
image = load_image (&arg);
701
823
}
702
824
v_free (&arg);
0 commit comments