diff --git a/mimview/image.c b/mimview/image.c new file mode 100644 index 0000000..cca8678 --- /dev/null +++ b/mimview/image.c @@ -0,0 +1,117 @@ +#include "mimview.h" + +#include +#include + +image_t* images = NULL; +static int oldw = 0, oldh = 0; +static unsigned char* buffer = NULL; + +void image_init(void) { + unsigned char* d = ((MwLLCommonPixmap)pxdata)->raw; + int w = ((MwLLCommonPixmap)pxdata)->width; + int h = ((MwLLCommonPixmap)pxdata)->height; + if(oldw != w || oldh != h) { + int y, x; + if(buffer != NULL) free(buffer); + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + unsigned char* px = &d[(y * w + x) * 4]; + if(((y / 16) + (x / 16)) % 2) { + px[0] = px[1] = px[2] = 128; + } else { + px[0] = px[1] = px[2] = 64; + } + px[3] = 255; + } + } + buffer = malloc(w * h * 4); + memcpy(buffer, d, w * h * 4); + } else { + memcpy(d, buffer, w * h * 4); + } + oldw = w; + oldh = h; + + MwLLPixmapUpdate(pxdata); + MwForceRender(image); +} + +void image_add(const char* path) { + image_t img; + img.path = MDEStringDuplicate(path); + img.data = NULL; + img.width = 0; + img.height = 0; + img.x = 0; + img.y = 0; + img.scale = 0; + arrput(images, img); +} + +void image_render(void) { + if(current < arrlen(images) && images[current].data == NULL) { + int w, h, ch; + unsigned char* d; + again:; + d = stbi_load(images[current].path, &w, &h, &ch, 4); + if(d != NULL) { + int pw = ((MwLLCommonPixmap)pxdata)->width; + int ph = ((MwLLCommonPixmap)pxdata)->height; + double sw = (double)w / pw; + double sh = (double)h / ph; + + images[current].data = d; + images[current].width = w; + images[current].height = h; + images[current].scale = sw > sh ? sw : sh; + } else { + free(images[current].path); + arrdel(images, current); + if(arrlen(images) <= current) { + current = 0; + } + goto again; + } + } + + if(current < arrlen(images)) { + unsigned char* d = ((MwLLCommonPixmap)pxdata)->raw; + int y; + int x; + int w = ((MwLLCommonPixmap)pxdata)->width; + int h = ((MwLLCommonPixmap)pxdata)->height; + int ox = (w - images[current].width / images[current].scale) / 2 - images[current].x / images[current].scale; + int oy = (h - images[current].height / images[current].scale) / 2 - images[current].y / images[current].scale; + char str[128]; + + sprintf(str, "mimview [%d of %d] %s", current + 1, arrlen(images), images[current].path); + + MwVaApply(window, + MwNtitle, str, + NULL); + + for(y = (oy < 0 ? 0 : 0); y < h + (oy < 0 ? -oy : 0); y++) { + for(x = (ox < 0 ? 0 : 0); x < w + (ox < 0 ? -ox : 0); x++) { + if(0 <= (y + oy) && (y + oy) < h && 0 <= (x + ox) && (x + ox) < w) { + int ix = x * images[current].scale; + int iy = y * images[current].scale; + unsigned char* opx; + unsigned char* ipx; + if(0 <= iy && iy < images[current].height && 0 <= ix && ix < images[current].width) { + int i; + opx = &d[((y + oy) * w + x + ox) * 4]; + ipx = &images[current].data[(iy * images[current].width + ix) * 4]; + + for(i = 0; i < 3; i++) { + opx[i] *= (255 - ipx[3]) / 255.0; + opx[i] += ipx[i] * (ipx[3] / 255.0); + } + } + } + } + } + MwLLPixmapUpdate(pxdata); + MwForceRender(image); + } +} diff --git a/mimview/main.c b/mimview/main.c index d0cd6ef..9371835 100644 --- a/mimview/main.c +++ b/mimview/main.c @@ -1,12 +1,15 @@ #include "mimview.h" +#include + #define ButtonWidth 32 #define ButtonHeight 24 MwWidget window, menu, image; +MwWidget bprev, bnext, bzoomin, bzoomout; MwLLPixmap pxprojector, pxdata = NULL; static MwLLPixmap pxprev, pxnext, pxzoomin, pxzoomout; -static MwWidget bprev, bnext, sep, bzoomin, bzoomout; +static MwWidget sep; static void resize(MwWidget handle, void* user, void* client) { int y = MwGetInteger(menu, MwNheight); @@ -18,17 +21,18 @@ static void resize(MwWidget handle, void* user, void* client) { if(pxdata != NULL) MwLLDestroyPixmap(pxdata); iw = ww - 10; - ih = wh - 5 - ButtonHeight - 5; + ih = wh - 5 - 5 - ButtonHeight - 5; data = malloc(iw * ih * 4); memset(data, 0, iw * ih * 4); pxdata = MwLoadRaw(window, data, iw, ih); free(data); + image_init(); MwVaApply(image, MwNpixmap, pxdata, MwNx, 5, MwNy, y + 5, MwNwidth, ww - 10, - MwNheight, wh - 5 - ButtonHeight - 5, + MwNheight, wh - 5 - 5 - ButtonHeight - 5, NULL); bx = (ww - 10 - (ButtonWidth * 2 + 5) * 2) / 2; @@ -62,13 +66,18 @@ static void resize(MwWidget handle, void* user, void* client) { MwNwidth, ButtonWidth, MwNheight, ButtonHeight, NULL); + + if(current < arrlen(images)) { + image_render(); + } } int main(int argc, char** argv) { int pad; + int i; MwLibraryInit(); - window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, 320, 240, + window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, 320, 320, MwNtitle, "mimview", NULL); menu = MwCreateWidget(MwMenuClass, "menu", window, 0, 0, 0, 0); @@ -100,20 +109,26 @@ int main(int argc, char** argv) { NULL); MwVaApply(bzoomin, - MwNpixmap, pxzoomout, + MwNpixmap, pxzoomin, MwNpadding, pad, NULL); MwVaApply(bzoomout, - MwNpixmap, pxzoomin, + MwNpixmap, pxzoomout, MwNpadding, pad, NULL); MwAddUserHandler(window, MwNresizeHandler, resize, NULL); - ui_init(); - resize(window, NULL, NULL); + for(i = 1; i < argc; i++) { + image_add(argv[i]); + } + + image_render(); + + ui_init(); + MwLoop(window); } diff --git a/mimview/mimview.h b/mimview/mimview.h index 98041d7..7504cd1 100644 --- a/mimview/mimview.h +++ b/mimview/mimview.h @@ -16,11 +16,29 @@ #include #include +typedef struct image { + char* path; + unsigned char* data; + int width; + int height; + int x; + int y; + double scale; +} image_t; + /* main.c */ -extern MwWidget window, menu; -extern MwLLPixmap pxprojector; +extern MwWidget window, menu, image; +extern MwLLPixmap pxprojector, pxdata; +extern MwWidget bprev, bnext, bzoomin, bzoomout; /* ui.c */ -void ui_init(void); +extern int current; +void ui_init(void); + +/* image.c */ +extern image_t* images; +void image_init(void); +void image_add(const char* path); +void image_render(void); #endif diff --git a/mimview/ui.c b/mimview/ui.c index 586aa70..2d95081 100644 --- a/mimview/ui.c +++ b/mimview/ui.c @@ -1,6 +1,9 @@ #include "mimview.h" +#include + static void* help_about; +int current = 0; static void menu_menu(MwWidget handle, void* user, void* client) { if(client == help_about) { @@ -8,6 +11,43 @@ static void menu_menu(MwWidget handle, void* user, void* client) { } } +static void bprev_activate(MwWidget handle, void* user, void* client) { + current--; + if(current == -1) current = arrlen(images) - 1; + if(current == -1) current = 0; + if(current < arrlen(images)) { + image_init(); + image_render(); + } +} + +static void bnext_activate(MwWidget handle, void* user, void* client) { + current++; + if(current == arrlen(images)) current = 0; + if(current < arrlen(images)) { + image_init(); + image_render(); + } +} + +static void bzoomin_activate(MwWidget handle, void* user, void* client) { + if(current < arrlen(images)) { + if(images[current].scale >= 0.2) { + images[current].scale /= 2; + } + image_init(); + image_render(); + } +} + +static void bzoomout_activate(MwWidget handle, void* user, void* client) { + if(current < arrlen(images)) { + images[current].scale *= 2; + image_init(); + image_render(); + } +} + void ui_init(void) { void* m; @@ -15,4 +55,8 @@ void ui_init(void) { help_about = MwMenuAdd(menu, m, "About"); MwAddUserHandler(menu, MwNmenuHandler, menu_menu, NULL); + MwAddUserHandler(bprev, MwNactivateHandler, bprev_activate, NULL); + MwAddUserHandler(bnext, MwNactivateHandler, bnext_activate, NULL); + MwAddUserHandler(bzoomin, MwNactivateHandler, bzoomin_activate, NULL); + MwAddUserHandler(bzoomout, MwNactivateHandler, bzoomout_activate, NULL); }