shithub: view

Download patch

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);