ref: 1a8a22e01213a86f6d9950cf68fea688979966ad
parent: 5345ff12ba5438c42ec65668310cab94524e48d9
author: phil9 <telephil9@gmail.com>
date: Mon Nov 29 01:00:27 EST 2021
added save and export functions `save` saves the current image in 9 format `export` save the current image in png format
--- a/a.h
+++ b/a.h
@@ -8,6 +8,9 @@
BMP,
};
+Image* load(char*);
+int save(Image*, char*);
+int export(Image*, char*);
void* emalloc(ulong);
void* erealloc(void*, ulong);
Image* eallocimage(int, int, ulong, int, ulong);
--- /dev/null
+++ b/io.c
@@ -1,0 +1,132 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <thread.h>
+#include <mouse.h>
+#include <keyboard.h>
+#include <stb.h>
+#include "a.h"
+
+Image*
+load9(char *filename)
+{
+ Image *i;
+ int fd;
+
+ fd = open(filename, OREAD);
+ if(fd < 0)
+ sysfatal("open: %r");
+ i = readimage(display, fd, 1);
+ if(i == nil)
+ sysfatal("readimage: %r");
+ close(fd);
+ return i;
+}
+
+Image*
+loadany(char *filename)
+{
+ Image *i;
+ uchar *buf, *out;
+ int n, w, h, c;
+ ulong chan;
+
+ buf = readfile(filename, &n);
+ if(buf == nil)
+ sysfatal("readfile: %r");
+ out = stbi_load_from_memory(buf, n, &w, &h, &c, 4);
+ free(buf);
+ if(out==nil)
+ sysfatal("stbi_load_from_memory: %r");
+ chan = c==3 ? XBGR32 : ABGR32;
+ lockdisplay(display);
+ i = eallocimage(w, h, chan, 0, DNofill);
+ if(loadimage(i, i->r, out, 4*w*h)<0)
+ sysfatal("loadimage: %r");
+ unlockdisplay(display);
+ return i;
+}
+
+Image*
+load(char *filename)
+{
+ Image *i;
+ int f;
+
+ i = nil;
+ f = fileformat(filename);
+ if(f < 0)
+ sysfatal("load: %r");
+ switch(f){
+ case SVG:
+ fprint(2, "SVG files not handled\n");
+ threadexitsall("SVG files not handled");
+ case NINE:
+ i = load9(filename);
+ break;
+ case GIF:
+ case JPEG:
+ case PNG:
+ case BMP:
+ i = loadany(filename);
+ break;
+ }
+ return i;
+}
+
+int
+save(Image *i, char *f)
+{
+ int fd, r;
+
+ if(access(f, 0) < 0)
+ fd = create(f, OWRITE, 0644);
+ else
+ fd = open(f, OWRITE|OTRUNC);
+ if(fd < 0)
+ return -1;
+ r = writeimage(fd, i, 1);
+ close(fd);
+ return r;
+}
+
+int
+export(Image *i, char *f)
+{
+ int fd, pfd[2], r;
+ Waitmsg *m;
+
+ r = -1;
+ if(access(f, 0) < 0)
+ fd = create(f, OWRITE, 0644);
+ else
+ fd = open(f, OWRITE|OTRUNC);
+ if(fd < 0)
+ return -1;
+ if(pipe(pfd) < 0){
+ close(fd);
+ return -1;
+ }
+ switch(rfork(RFFDG|RFPROC)){
+ case -1:
+ goto Err;
+ case 0:
+ dup(pfd[1], 0);
+ dup(fd, 1);
+ close(pfd[1]);
+ close(pfd[0]);
+ execl("/bin/rc", "rc", "-c", "topng", nil);
+ _exits("exec");
+ }
+ if(writeimage(pfd[0], i, 1) < 0)
+ goto Err;
+ m = wait();
+ if(m->msg[0] == 0)
+ r = 0;
+Err:
+ close(fd);
+ close(pfd[1]);
+ close(pfd[0]);
+ return r;
+}
+
--- a/mkfile
+++ b/mkfile
@@ -3,7 +3,7 @@
BIN=/$objtype/bin
TARG=view
CFLAGS=-FTVw -p -Istb
-OFILES=view.$O sepmenuhit.$O utils.$O
+OFILES=view.$O io.$O sepmenuhit.$O utils.$O
HFILES=a.h stb/stb.h
</sys/src/cmd/mkone
--- a/view.c
+++ b/view.c
@@ -6,7 +6,6 @@
#include <keyboard.h>
#include <cursor.h>
#include <plumb.h>
-#include <stb.h>
#include "a.h"
enum
@@ -79,7 +78,7 @@
"flip",
"flop",
"_Misc",
- "pipe...",
+ "pipe",
nil,
};
Menu menu2 = { menu2str };
@@ -87,11 +86,15 @@
enum
{
Mopen,
+ Msave,
+ Mexport,
Mexit,
};
char *menu3str[] =
{
"open",
+ "save",
+ "export",
"exit",
nil,
};
@@ -99,73 +102,6 @@
void redraw(void);
-Image*
-load9(char *filename)
-{
- Image *i;
- int fd;
-
- fd = open(filename, OREAD);
- if(fd < 0)
- sysfatal("open: %r");
- i = readimage(display, fd, 1);
- if(i == nil)
- sysfatal("readimage: %r");
- close(fd);
- return i;
-}
-
-Image*
-loadany(char *filename)
-{
- Image *i;
- uchar *buf, *out;
- int n, w, h, c;
- ulong chan;
-
- buf = readfile(filename, &n);
- if(buf == nil)
- sysfatal("readfile: %r");
- out = stbi_load_from_memory(buf, n, &w, &h, &c, 4);
- free(buf);
- if(out==nil)
- sysfatal("stbi_load_from_memory: %r");
- chan = c==3 ? XBGR32 : ABGR32;
- lockdisplay(display);
- i = eallocimage(w, h, chan, 0, DNofill);
- if(loadimage(i, i->r, out, 4*w*h)<0)
- sysfatal("loadimage: %r");
- unlockdisplay(display);
- return i;
-}
-
-Image*
-load(char *filename)
-{
- Image *i;
- int f;
-
- i = nil;
- f = fileformat(filename);
- if(f < 0)
- sysfatal("load: %r");
- switch(f){
- case SVG:
- fprint(2, "SVG files not handled\n");
- threadexitsall("SVG files not handled");
- case NINE:
- i = load9(filename);
- break;
- case GIF:
- case JPEG:
- case PNG:
- case BMP:
- i = loadany(filename);
- break;
- }
- return i;
-}
-
int
loadfromfile(char *filename)
{
@@ -388,7 +324,7 @@
return;
}
freeimage(img);
- img = i;
+ orig = img = i;
pos = subpt(ZP, img->r.min);
redraw();
}
@@ -396,7 +332,7 @@
void
menu3hit(void)
{
- char buf[255];
+ char buf[255] = {0};
int n;
n = menuhit(3, mctl, &menu3, nil);
@@ -407,6 +343,18 @@
fprint(2, "cannot open file '%s': %r\n", buf);
}
break;
+ case Msave:
+ if(enter("save:", buf, sizeof buf, mctl, kctl, nil) > 0){
+ if(save(orig, buf) < 0)
+ fprint(2, "cannot save file '%s': %r\n", buf);
+ }
+ break;
+ case Mexport:
+ if(enter("export:", buf, sizeof buf, mctl, kctl, nil) > 0){
+ if(export(orig, buf) < 0)
+ fprint(2, "cannot export file '%s': %r\n", buf);
+ }
+ break;
case Mexit:
threadexitsall(nil);
break;
@@ -495,7 +443,7 @@
initbg();
proccreate(plumbproc, plumbc, 8192);
if(*argv != nil){
- img = load(*argv);
+ orig = img = load(*argv);
pos = subpt(ZP, img->r.min);
}
evtresize(0);