Skip to content

Commit f7528be

Browse files
authored
Merge pull request #202 from Joe7M/master
Improvements for image.save()
2 parents f69893e + 5eca11d commit f7528be

File tree

4 files changed

+174
-74
lines changed

4 files changed

+174
-74
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Initial setup on linux
1313
$ sudo apt-get install git autotools-dev automake gcc g++ libsdl2-dev libfreetype6-dev libfontconfig1-dev xxd
1414
$ git clone https://github.com/smallbasic/SmallBASIC.git
1515
$ cd SmallBASIC
16+
$ git submodule update --init
1617
$ sh autogen.sh
1718
```
1819
Build in linux

src/common/file.c

Lines changed: 28 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -112,34 +112,6 @@ int dev_fstatus(int handle) {
112112
return (f->handle != -1);
113113
}
114114

115-
/**
116-
* terminal speed
117-
* select the correct system constant
118-
*/
119-
#if USE_TERM_IO
120-
int select_unix_serial_speed(int n) {
121-
switch (n) {
122-
case 300:
123-
return B300;
124-
case 600:
125-
return B600;
126-
case 1200:
127-
return B1200;
128-
case 2400:
129-
return B2400;
130-
case 4800:
131-
return B4800;
132-
case 9600:
133-
return B9600;
134-
case 19200:
135-
return B19200;
136-
case 38400:
137-
return B38400;
138-
}
139-
return B9600;
140-
}
141-
#endif
142-
143115
/**
144116
* opens a file
145117
*
@@ -183,19 +155,14 @@ int dev_fopen(int sb_handle, const char *name, int flags) {
183155
}
184156
if (strncmp(f->name, "COM", 3) == 0) {
185157
f->type = ft_serial_port;
186-
f->port = f->name[3] - '1';
158+
f->devspeed = 9600;
159+
f->port = f->name[3] - '0';
187160
if (f->port < 0) {
188161
f->port = 10;
189162
}
190163
if (strlen(f->name) > 5) {
191164
f->devspeed = xstrtol(f->name + 5);
192-
} else {
193-
f->devspeed = 9600;
194165
}
195-
196-
#if USE_TERM_IO
197-
f->devspeed = select_unix_serial_speed(f->devspeed);
198-
#endif
199166
} else if (strncmp(f->name, "SOCL:", 5) == 0) {
200167
f->type = ft_socket_client;
201168
} else if (strncasecmp(f->name, "HTTP:", 5) == 0) {
@@ -217,6 +184,32 @@ int dev_fopen(int sb_handle, const char *name, int flags) {
217184
strcpy(f->name, "SDIN:");
218185
f->type = ft_stream;
219186
}
187+
} else if (strncmp(f->name, "/dev/tty", 8) == 0) {
188+
f->type = ft_serial_port;
189+
f->devspeed = 9600;
190+
const char *ptrSpeed = strchr(f->name, ':');
191+
if(ptrSpeed) {
192+
if(strlen(ptrSpeed) > 1) {
193+
f->devspeed = xstrtol(ptrSpeed + 1);
194+
}
195+
f->name[ptrSpeed - f->name] = '\0';
196+
}
197+
}
198+
if (f->name[5] == ':') {
199+
for (int i = 0; i < 4; i++) {
200+
f->name[i] = to_upper(f->name[i]);
201+
}
202+
if (strncmp(f->name, "COM", 3) == 0) {
203+
f->type = ft_serial_port;
204+
f->devspeed = 9600;
205+
f->port = (f->name[3] - '0') * 10 + (f->name[4] - '0');
206+
if (f->port < 0) {
207+
f->port = 10;
208+
}
209+
if (strlen(f->name) > 6) {
210+
f->devspeed = xstrtol(f->name + 6);
211+
}
212+
}
220213
}
221214
} // device
222215

src/common/fs_serial.c

Lines changed: 86 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,75 @@
2020
#include <sys/select.h>
2121
#include <errno.h>
2222

23+
/**
24+
* terminal speed
25+
* select the correct system constant
26+
*/
27+
long select_unix_serial_speed(long n) {
28+
switch (n) {
29+
case 300:
30+
return B300;
31+
case 600:
32+
return B600;
33+
case 1200:
34+
return B1200;
35+
case 2400:
36+
return B2400;
37+
case 4800:
38+
return B4800;
39+
case 9600:
40+
return B9600;
41+
case 19200:
42+
return B19200;
43+
case 38400:
44+
return B38400;
45+
// extra baud rates (but not posix)
46+
case 57600:
47+
return B57600;
48+
case 115200:
49+
return B115200;
50+
case 230400:
51+
return B230400;
52+
case 460800:
53+
return B460800;
54+
case 500000:
55+
return B500000;
56+
case 576000:
57+
return B576000;
58+
case 921600:
59+
return B921600;
60+
case 1000000:
61+
return B1000000;
62+
case 1152000:
63+
return B1152000;
64+
case 1500000:
65+
return B1500000;
66+
case 2000000:
67+
return B2000000;
68+
case 2500000:
69+
return B2500000;
70+
case 3000000:
71+
return B3000000;
72+
case 3500000:
73+
return B3500000;
74+
case 4000000:
75+
return B4000000;
76+
}
77+
return B9600;
78+
}
79+
2380
int serial_open(dev_file_t *f) {
24-
sprintf(f->name, "/dev/ttyS%d", f->port);
81+
if (strncmp(f->name, "COM", 3) == 0) {
82+
sprintf(f->name, "/dev/ttyS%d", f->port);
83+
}
2584

2685
f->handle = open(f->name, O_RDWR | O_NOCTTY);
2786
if (f->handle < 0) {
2887
err_file((f->last_error = errno));
2988
}
89+
90+
f->devspeed = select_unix_serial_speed(f->devspeed);
91+
3092
// save current port settings
3193
tcgetattr(f->handle, &f->oldtio);
3294
bzero(&f->newtio, sizeof(f->newtio));
@@ -83,33 +145,52 @@ int serial_open(dev_file_t *f) {
83145
HANDLE hCom;
84146
DWORD dwer;
85147

86-
sprintf(f->name, "COM%d", f->port);
148+
if (strncmp(f->name, "COM", 3) != 0) {
149+
rt_raise("SERIALFS: Linux serial port was specified. Use COM instead.");
150+
}
87151

152+
// Bug when opening COM-Port > 9: https://support.microsoft.com/en-us/topic/howto-specify-serial-ports-larger-than-com9-db9078a5-b7b6-bf00-240f-f749ebfd913e
153+
sprintf(f->name, "\\\\.\\COM%d", f->port);
154+
88155
hCom = CreateFile(f->name, GENERIC_READ | GENERIC_WRITE,
89156
0, NULL, OPEN_EXISTING, 0, NULL);
90157

91158
if (hCom == INVALID_HANDLE_VALUE) {
92159
dwer = GetLastError();
93160
if (dwer != 5) {
94-
rt_raise("SERIALFS: CreateFile() failed (%d)", dwer);
161+
rt_raise("SERIALFS: CreateFile() failed (Error %d)", dwer);
95162
} else {
96163
rt_raise("SERIALFS: ACCESS DENIED");
97164
}
98165
return 0;
99166
}
100167

101168
if (!GetCommState(hCom, &dcb)) {
102-
rt_raise("SERIALFS: GetCommState() failed (%d)", GetLastError());
169+
rt_raise("SERIALFS: GetCommState() failed (Error %d)", GetLastError());
103170
return 0;
104171
}
105172

173+
// Default settings from Putty
174+
dcb.fBinary = TRUE;
175+
dcb.fDtrControl = DTR_CONTROL_ENABLE; // This is needed for Raspberry Pi PICO
176+
dcb.fDsrSensitivity = FALSE;
177+
dcb.fTXContinueOnXoff = FALSE;
178+
dcb.fOutX = FALSE;
179+
dcb.fInX = FALSE;
180+
dcb.fErrorChar = FALSE;
181+
dcb.fNull = FALSE;
182+
dcb.fRtsControl = RTS_CONTROL_ENABLE;
183+
dcb.fAbortOnError = FALSE;
184+
dcb.fOutxCtsFlow = FALSE;
185+
dcb.fOutxDsrFlow = FALSE;
186+
// Settings SmallBASIC
106187
dcb.BaudRate = f->devspeed;
107188
dcb.ByteSize = 8;
108189
dcb.Parity = NOPARITY;
109190
dcb.StopBits = ONESTOPBIT;
110191

111192
if (!SetCommState(hCom, &dcb)) {
112-
rt_raise("SERIALFS: SetCommState() failed (%d)", GetLastError());
193+
rt_raise("SERIALFS: SetCommState() failed (Error %d)", GetLastError());
113194
return 0;
114195
}
115196

src/ui/image.cpp

Lines changed: 59 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -450,17 +450,19 @@ void cmd_image_hide(var_s *self, var_s *) {
450450
}
451451

452452
//
453-
// Output the image to a PNG file
453+
// Output the image to a PNG file or an array
454454
//
455455
// png.save("horse1.png")
456456
// png.save(#1)
457+
// png.save(byref var)
458+
// file = "abc.png" : png.save(file)
457459
//
458460
void cmd_image_save(var_s *self, var_s *) {
459461
unsigned id = map_get_int(self, IMG_BID, -1);
460462
ImageBuffer *image = get_image(id);
461463
dev_file_t *file;
462-
var_t *array;
463-
var_t var;
464+
var_t *var;
465+
var_t str;
464466
bool saved = false;
465467
if (!prog_error && image != nullptr) {
466468
unsigned w = image->_width;
@@ -473,37 +475,54 @@ void cmd_image_save(var_s *self, var_s *) {
473475
saved = true;
474476
}
475477
break;
476-
case kwTYPE_VAR:
477-
array = par_getvar_ptr();
478-
v_tomatrix(array, h, w);
479-
// x0 x1 x2 (w=3,h=2)
480-
// y0 rgba rgba rgba ypos=0
481-
// y1 rgba rgba rgba ypos=12
482-
//
483-
for (unsigned y = 0; y < h; y++) {
484-
unsigned yoffs = (y * w * 4);
485-
for (unsigned x = 0; x < w; x++) {
486-
uint8_t a, r, g, b;
487-
GET_IMAGE_ARGB(image->_image, yoffs + (x * 4), a, r, g, b);
488-
pixel_t px = v_get_argb_px(a, r, g, b);
489-
unsigned pos = y * w + x;
490-
v_setint(v_elem(array, pos), px);
491-
}
492-
}
493-
saved = true;
478+
case kwTYPE_STR:
479+
par_getstr(&str);
480+
if (!prog_error &&
481+
!encode_png_file(str.v.p.ptr, image->_image, w, h)) {
482+
saved = true;
483+
}
484+
v_free(&str);
494485
break;
495486
default:
496-
v_init(&var);
497-
eval(&var);
498-
if (var.type == V_STR && !prog_error &&
499-
!lodepng_encode32_file(var.v.p.ptr, image->_image, w, h)) {
487+
var = par_getvar_ptr();
488+
if (var->type == V_STR && !prog_error &&
489+
!encode_png_file(var->v.p.ptr, image->_image, w, h)) {
500490
saved = true;
501-
}
502-
v_free(&var);
503-
break;
491+
} else if (!prog_error) {
492+
uint32_t offsetLeft = map_get_int(self, IMG_OFFSET_LEFT, 0);
493+
uint32_t offsetTop = map_get_int(self, IMG_OFFSET_TOP, 0);
494+
uint32_t wClip = map_get_int(self, IMG_WIDTH, w);
495+
uint32_t hClip = map_get_int(self, IMG_HEIGHT, h);
496+
497+
if (offsetTop < h && offsetLeft < w) {
498+
if (offsetTop + hClip > h) {
499+
hClip = h - offsetTop;
500+
}
501+
if (offsetLeft + wClip > w) {
502+
wClip = w - offsetLeft;
503+
}
504+
v_tomatrix(var, hClip, wClip);
505+
// x0 x1 x2 (w=3,h=2)
506+
// y0 rgba rgba rgba ypos=0
507+
// y1 rgba rgba rgba ypos=12
508+
//
509+
for (unsigned y = offsetTop; y < offsetTop + hClip; y++) {
510+
unsigned yoffs = (y * w * 4);
511+
for (unsigned x = offsetLeft; x < offsetLeft + wClip; x++) {
512+
uint8_t a, r, g, b;
513+
GET_IMAGE_ARGB(image->_image, yoffs + (x * 4), a, r, g, b);
514+
pixel_t px = v_get_argb_px(a, r, g, b);
515+
unsigned pos = (y - offsetTop ) * wClip + (x - offsetLeft);
516+
v_setint(v_elem(var, pos), px);
517+
}
518+
}
519+
} else {
520+
v_tomatrix(var, hClip, wClip);
521+
}
522+
saved = true;
523+
}
504524
}
505525
}
506-
507526
if (!saved) {
508527
err_throw(ERR_IMAGE_SAVE);
509528
}
@@ -512,7 +531,7 @@ void cmd_image_save(var_s *self, var_s *) {
512531

513532
//
514533
// Reduces the size of the image
515-
// arguments: left, top, right, bottom
534+
// arguments: left, top, width, height
516535
//
517536
// png.clip(10, 10, 10, 10)
518537
//
@@ -521,12 +540,18 @@ void cmd_image_clip(var_s *self, var_s *) {
521540
int bid = map_get_int(self, IMG_BID, -1);
522541
if (bid != -1) {
523542
ImageBuffer *image = get_image((unsigned)bid);
524-
var_int_t left, top, right, bottom;
525-
if (image != nullptr && par_massget("iiii", &left, &top, &right, &bottom)) {
543+
var_int_t left, top, width, heigth;
544+
if (image != nullptr && par_massget("iiii", &left, &top, &width, &heigth)) {
545+
if (left < 0) {
546+
left = 0;
547+
}
548+
if (top < 0) {
549+
top = 0;
550+
}
526551
map_set_int(self, IMG_OFFSET_LEFT, left);
527552
map_set_int(self, IMG_OFFSET_TOP, top);
528-
map_set_int(self, IMG_WIDTH, right);
529-
map_set_int(self, IMG_HEIGHT, bottom);
553+
map_set_int(self, IMG_WIDTH, width);
554+
map_set_int(self, IMG_HEIGHT, heigth);
530555
}
531556
}
532557
}

0 commit comments

Comments
 (0)