aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile16
-rw-r--r--src/meh.h6
-rw-r--r--src/scale.c34
-rw-r--r--src/xlib.c5
-rw-r--r--test/test.c62
-rw-r--r--test/test.h6
6 files changed, 104 insertions, 25 deletions
diff --git a/Makefile b/Makefile
index d2e183b..4455b14 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,12 @@
+TARGET := meh
+TESTTARGET := test/test
+
SRCFILES := $(wildcard src/*.c)
OBJFILES := $(SRCFILES:%.c=%.o)
DEPFILES := $(OBJFILES:%.o=%.d)
-CLEANFILES := $(CLEANFILES) $(DEPFILES) $(OBJFILES) meh
+TESTCLEAN := $(TESTTARGET) $(TESTTARGET).d $(TESTTARGET).o
+CLEANFILES := $(CLEANFILES) $(DEPFILES) $(OBJFILES) test/test.o test/test.d test/test $(TARGET)
LIBS ?= -lX11 -lXext -ljpeg -lpng -lgif
PREFIX ?= /usr/local
BINDIR = $(PREFIX)/bin
@@ -14,7 +18,13 @@ CONFIG ?= ../config
CFLAGS ?= -O3 -DNDEBUG
meh: $(OBJFILES)
- $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJFILES) $(LIBS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+test: $(TESTTARGET)
+ ./$(TESTTARGET)
+
+test/test: test/test.o $(filter-out src/main.o, $(OBJFILES))
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
-include $(DEPFILES)
@@ -28,5 +38,5 @@ install:
clean:
$(RM) $(CLEANFILES)
-.PHONY: clean
+.PHONY: clean test
diff --git a/src/meh.h b/src/meh.h
index 4333f51..f2d5e3c 100644
--- a/src/meh.h
+++ b/src/meh.h
@@ -31,6 +31,12 @@ struct image{
XImage *ximg;
};
+
+/* scale */
+void scale(struct image *img, int width, int height, int bytesperline, char* __restrict__ newBuf);
+void nearestscale(struct image *img, int width, int height, int bytesperline, char* __restrict__ newBuf);
+
+/* XLib */
void setaspect(unsigned int w, unsigned int h);
void xinit();
void drawimage(XImage *ximg, unsigned int width, unsigned int height);
diff --git a/src/scale.c b/src/scale.c
index 4cd62f3..21fa505 100644
--- a/src/scale.c
+++ b/src/scale.c
@@ -16,7 +16,7 @@
) * (v)) >> 20)
#define XLOOP(F) \
- for(x = 0; x < ximg->width*4;){ \
+ for(x = 0; x < width*4;){ \
const unsigned int x0 = a[x++];\
const unsigned int x1 = a[x++];\
const unsigned int u = a[x++];\
@@ -28,29 +28,28 @@
}
#define YITER \
- const unsigned int bufy = (y << 10) * img->bufheight / ximg->height;\
+ const unsigned int bufy = (y << 10) * img->bufheight / height;\
const unsigned int v = (bufy & 1023);\
const unsigned int vr = 1023^v;\
- ibuf = &img->buf[y * img->bufheight / ximg->height * img->bufwidth * 3];\
+ ibuf = &img->buf[y * img->bufheight / height * img->bufwidth * 3];\
ibufn = ibuf + dy;
-void scale(struct image *img, XImage *ximg){
+void scale(struct image *img, int width, int height, int bytesperline, char* __restrict__ newBuf){
int x, y;
const unsigned char * __restrict__ ibuf;
const unsigned char * __restrict__ ibufn;
const unsigned char * const bufend = &img->buf[img->bufwidth * img->bufheight * 3];
- char* __restrict__ newBuf = ximg->data;
- const unsigned int jdy = ximg->bytes_per_line / 4 - ximg->width;
+ const unsigned int jdy = bytesperline / 4 - width;
const unsigned int dy = img->bufwidth * 3;
TDEBUG_START
- unsigned int a[ximg->width * 4];
+ unsigned int a[width * 4];
{
- unsigned int dx = (img->bufwidth << 10) / ximg->width;
- unsigned int bufx = img->bufwidth / ximg->width;
- for(x = 0; x < ximg->width * 4;){
+ unsigned int dx = (img->bufwidth << 10) / width;
+ unsigned int bufx = img->bufwidth / width;
+ for(x = 0; x < width * 4;){
if((bufx >> 10) >= img->bufwidth - 1){
a[x++] = (img->bufwidth - 1) * 3;
a[x++] = (img->bufwidth - 1) * 3;
@@ -90,20 +89,19 @@ void scale(struct image *img, XImage *ximg){
TDEBUG_END("scale")
}
-void linearscale(struct image *img, XImage *ximg){
+void nearestscale(struct image *img, int width, int height, int bytesperline, char* __restrict__ newBuf){
int x, y;
unsigned char * __restrict__ ibuf;
- char* __restrict__ newBuf = ximg->data;
- unsigned int jdy = ximg->bytes_per_line / 4 - ximg->width;
- unsigned int dx = (img->bufwidth << 10) / ximg->width;
+ unsigned int jdy = bytesperline / 4 - width;
+ unsigned int dx = (img->bufwidth << 10) / width;
TDEBUG_START
- for(y = 0; y < ximg->height; y++){
- unsigned int bufx = img->bufwidth / ximg->width;
- ibuf = &img->buf[y * img->bufheight / ximg->height * img->bufwidth * 3];
+ for(y = 0; y < height; y++){
+ unsigned int bufx = img->bufwidth / width;
+ ibuf = &img->buf[y * img->bufheight / height * img->bufwidth * 3];
- for(x = 0; x < ximg->width; x++){
+ for(x = 0; x < width; x++){
*newBuf++ = (ibuf[(bufx >> 10)*3+2]);
*newBuf++ = (ibuf[(bufx >> 10)*3+1]);
*newBuf++ = (ibuf[(bufx >> 10)*3+0]);
diff --git a/src/xlib.c b/src/xlib.c
index ca0a1b5..a407f15 100644
--- a/src/xlib.c
+++ b/src/xlib.c
@@ -21,9 +21,6 @@ GC gc;
int xshm = 0;
-void scale(struct image *img, XImage *ximg);
-void linearscale(struct image *img, XImage *ximg);
-
XShmSegmentInfo *shminfo;
XImage *ximage(struct image *img, unsigned int width, unsigned int height, int fast){
int depth;
@@ -71,7 +68,7 @@ XImage *ximage(struct image *img, unsigned int width, unsigned int height, int f
ximg->data = malloc(ximg->bytes_per_line * ximg->height);
XInitImage(ximg);
}
- (fast ? linearscale : scale)(img, ximg);
+ (fast ? nearestscale : scale)(img, ximg->width, ximg->height, ximg->bytes_per_line, ximg->data);
}else{
/* TODO other depths */
fprintf(stderr, "This program does not yet support display depths <24.\n");
diff --git a/test/test.c b/test/test.c
new file mode 100644
index 0000000..926d5c2
--- /dev/null
+++ b/test/test.c
@@ -0,0 +1,62 @@
+#include "stdio.h"
+#include "stdlib.h"
+#include "sys/time.h"
+
+#include "../src/meh.h"
+
+#define TESTRUNS 20
+#define STARTTEST(name) int test_##name(){ testname = #name; testsrun++; do
+#define ENDTEST while(0); testspassed++; return 0;}
+#define STARTTIME struct timeval tvs[2];int _i, _j; for(_i = 0; _i < 2; gettimeofday(&tvs[_i], NULL), _i++){for(_j = 0; _j < (_i ? TESTRUNS : 3); _j++)
+#define ENDTIME }long int mselapsed = (tvs[1].tv_sec - tvs[0].tv_sec) * 1000000L + (tvs[1].tv_usec - tvs[0].tv_usec); printf("%s: average time: %li.%.3li ms\n", testname, mselapsed/1000/TESTRUNS, (mselapsed/TESTRUNS)%1000);
+#define assert(x) if(!(x)){fprintf(stderr, "test \"%s\" failed\n assert(%s) was false\n at %s:%i\n\n", testname, #x, __FILE__ ,__LINE__);return -1;}
+
+char *testname = NULL;
+int testsrun = 0, testspassed = 0;
+
+typedef int (*test_t)();
+
+STARTTEST(scale){
+ struct image img;
+ img.bufwidth = 1280*2;
+ img.bufheight = 1024*2;
+ img.buf = malloc(img.bufwidth*img.bufheight*4);
+ char *to = malloc(1280*1024*4);
+ STARTTIME{
+ scale(&img, 1280, 1024, 1280, to);
+ }ENDTIME
+ free(to);
+ free(img.buf);
+}ENDTEST
+
+STARTTEST(nearestscale){
+ struct image img;
+ img.bufwidth = 1280*2;
+ img.bufheight = 1024*2;
+ img.buf = malloc(img.bufwidth*img.bufheight*4);
+ char *to = malloc(1280*1024*4);
+ STARTTIME{
+ nearestscale(&img, 1280, 1024, 1280, to);
+ }ENDTIME
+ free(to);
+ free(img.buf);
+}ENDTEST
+
+test_t tests[] = {
+ test_scale,
+ test_nearestscale,
+ NULL
+};
+
+void summary(){
+ printf("%i tests run: %i passed %i failed\n", testsrun, testspassed, testsrun - testspassed);
+}
+
+int main(){
+ test_t *test = tests;
+ for(; *test; test++)
+ (*test)();
+ summary();
+ return 0;
+}
+
diff --git a/test/test.h b/test/test.h
new file mode 100644
index 0000000..1f2e7a0
--- /dev/null
+++ b/test/test.h
@@ -0,0 +1,6 @@
+
+#define STARTTIME
+#define ENDTIME
+
+#define
+