Puppy In-House Development

Under development: PCMCIA, wireless, etc.
Message
Author
User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#391 Post by technosaurus »

In my quest to minimalize jwm (replace, cairo, librsvg, libjpeg and libpng with stb_image and nanosvg), I ended up writing this minimal image viewer:

Note: nanosvg uses zlib license, the rest is public domain

Code: Select all

#include <xcb/xcb.h>
#include <xcb/xcb_image.h>
#define STBI_NO_HDR
#define STBI_NO_LINEAR
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define NANOSVG_IMPLEMENTATION
#include "nanosvg.h"
#define NANOSVGRAST_IMPLEMENTATION
#include "nanosvgrast.h"

int main(int argc, char **argv){
	xcb_connection_t *c = xcb_connect(0, 0);
	xcb_screen_t *s = xcb_setup_roots_iterator(xcb_get_setup(c)).data;
	int w, h, n,
		depth = s->root_depth,
		win_class = XCB_WINDOW_CLASS_INPUT_OUTPUT,
		format = XCB_IMAGE_FORMAT_Z_PIXMAP;
	xcb_colormap_t colormap = s->default_colormap;
	xcb_drawable_t win = xcb_generate_id(c);
	xcb_gcontext_t gc = xcb_generate_id(c);
	xcb_pixmap_t pixmap = xcb_generate_id(c);
	xcb_generic_event_t *ev;
	xcb_image_t *image;
	NSVGimage *shapes = NULL;
	NSVGrasterizer *rast = NULL;
	char *data = NULL;
	unsigned *dp;
	size_t i, len;
	uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
		value_mask = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS,
		values[] = { s->black_pixel, value_mask };

	if (argc<2) return -1;
	if ((data = stbi_load(argv[1], &w, &h, &n, 4)))
		;
	else if ((shapes = nsvgParseFromFile(argv[1], "px", 96.0f))) {
		w = (int)shapes->width;
		h = (int)shapes->height;
		rast = nsvgCreateRasterizer();
		data = malloc(w*h*4);
		nsvgRasterize(rast, shapes, 0,0,1, data, w, h, w*4);
	}else return -1;
	for(i=0,len=w*h,dp=(unsigned *)data;i<len;i++) //rgba to bgra
		dp[i]=dp[i]&0xff00ff00|((dp[i]>>16)&0xFF)|((dp[i]<<16)&0xFF0000);
	xcb_create_window(c,depth,win,s->root,0,0,w,h,1,win_class,s->root_visual,mask,values);
	xcb_create_pixmap(c,depth,pixmap,win,w,h);
	xcb_create_gc(c,gc,pixmap,0,NULL);
	image = xcb_image_create_native(c,w,h,format,depth,data,w*h*4,data);
	xcb_image_put(c, pixmap, gc, image, 0, 0, 0);
	xcb_image_destroy(image);
	xcb_map_window(c, win);
	xcb_flush(c);
	while ((ev = xcb_wait_for_event(c))) {
		switch (ev->response_type & ~0x80){
		case XCB_EXPOSE: {
			xcb_expose_event_t *x = (xcb_expose_event_t *)ev;
			xcb_copy_area(c,pixmap,win,gc,x->x,x->y,x->x,x->y,x->width,x->height);
			xcb_flush(c);
		}break;
		case XCB_BUTTON_PRESS: goto end;
		default: break;
		}
	}
end:
	xcb_free_pixmap(c, pixmap);
	xcb_disconnect(c);
	return 0;
}
90% of the code is just the verbosity of dealing with an xcb window.


An up to date gist to lighten jwm image loading is available at:
https://gist.github.com/technosaurus/36 ... f83d670546
Attachments
image.c.gz
replace jwm's image.c with this and compile with extra CFLAGS:
-DUSE_STB_IMAGE and -DUSE_NANOSVG -Wl,-lm
(with svg, png and jpeg disabled)
supports jpeg,png,gif,svg,tga,bmp and others
(4.41 KiB) Downloaded 291 times
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#392 Post by technosaurus »

I have posted my minimalistic libc implemenatation to github and named it Brad's Quixotic C
I wrote a little test program to test extremely low overhead threads and it only takes up 156 bytes of RAM on x86_64 (would probably be less on x86)
... something to think about for long running daemon processes.
It's not a full C implementation by any means, but let me know if there are any priority functions anyone would like to see implemented for their projects.
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

goingnuts
Posts: 932
Joined: Sun 07 Dec 2008, 13:33
Contact:

#393 Post by goingnuts »

Xlib version of technosaurus xcb based image-viewer two post back:

Code: Select all

/*Inspired by 
*	xputjpeg by Gleicon S. Moraes - gleicon@terra.com.br
		from: https://searchcode.com/codesearch/raw/107558322/
*	unamed example by technosaurus
		from http://murga-linux.com/puppy/viewtopic.php?t=89272&start=390&sid=1f696000b4032a89e59e66135ce527b8

fun with stb_image...
goingnuts July 2017
compile: gcc xputimage.c -o xputimage -L/usr/lib -L/usr/X11/lib -lX11 -lm
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/xpm.h>
#include <X11/extensions/shape.h>
#include <math.h>

#ifndef sinf
float sinf (float x) { return (float) sin( (double)x ); }
#endif
#ifndef cosf
float cosf (float x) { return (float) cos( (double)x ); }
#endif
#ifndef tanf
float tanf  (float x){return (float) tan ( (double)x );}
#endif
#ifndef atan2f
float atan2f(float x, float y){return (float) atan2( (double)x, (double)y );}
#endif
#ifndef fmodf
float fmodf (float x, float y){return (float) fmod ( (double)x, (double)y );}
#endif
#ifndef acosf
float acosf (float x){return (float) acos( (double)x );}
#endif

#define STBI_NO_HDR
#define STBI_NO_LINEAR
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define NANOSVG_IMPLEMENTATION
#include "nanosvg.h"
#define NANOSVGRAST_IMPLEMENTATION
#include "nanosvgrast.h"

int main (int argc, char **argv) {

	int				i, len, w, h, n, bpl, depth, screen;
	Pixel			white, black;
	Window			Root, iconwin, win;
	XEvent 			x_event;
	XImage			*ximage;
	Display			*dpy;
	GC				gc;
	XGCValues		gcv;
	char			*data;
	unsigned 		*dp;
	NSVGimage *shapes = NULL;
	NSVGrasterizer *rast = NULL;
	
	if (argc < 2) {
		printf ("Use: %s path.to.image\n", argv[0]);
		exit(1);
	}
	
	if ((data = stbi_load(argv[1], &w, &h, &n, 4)))
		;
	else if ((shapes = nsvgParseFromFile(argv[1], "px", 96.0f))) {
		w = (int)shapes->width;
		h = (int)shapes->height;
		rast = nsvgCreateRasterizer();
		data = malloc(w*h*4);
		nsvgRasterize(rast, shapes, 0,0,1, data, w, h, w*4);
   } else {
   		printf("Unable to load image: %s\n", argv[0]);
		return -1;
	}
		
    for(i=0, len=w*h, dp=(unsigned *)data; i<len; i++) //rgba to bgra
      dp[i]=dp[i]&0xff00ff00|((dp[i]>>16)&0xFF)|((dp[i]<<16)&0xFF0000);
      
   	if (!(dpy = XOpenDisplay(NULL)))
		printf("can't open X display\n");
	
	screen = DefaultScreen(dpy);
	Root = RootWindow (dpy, screen);
	white = WhitePixel (dpy, screen);
	black = BlackPixel (dpy, screen);

	win = XCreateSimpleWindow (dpy, Root, 0, 0, w, h, 0, black, white);

	iconwin = XCreateSimpleWindow (dpy,	win, 0, 0, w, h, 0, black, white);

	XSelectInput(dpy, win, ExposureMask | KeyPressMask);
	XMapWindow (dpy, win);
	gc = XCreateGC (dpy, win, 0, &gcv);

	depth = DefaultDepth(dpy, screen);

	switch(depth) {
	
		case 24: 	
			bpl=4; break;
		case 16:
		case 15: 	
			bpl=2; break;
		default:
			bpl=1; break;
	}

	ximage = XCreateImage (dpy, 
        	CopyFromParent, depth, 
        	ZPixmap, 0, 
        	data, 
        	w, h, 
        	bpl*8, bpl * w);

	XFlush(dpy);

	while (1) {
		XNextEvent(dpy, &x_event);
			switch (x_event.type) {
				case Expose: 
					XPutImage (dpy, win, gc, ximage, 0,0,0,0, w, h);
 					XFlush (dpy);     
					break;
				case KeyPress:	goto end;
				default: break;	
			}
	}

end:
	free (data);
	close(ConnectionNumber(dpy));
	return 0;
}
All the #ifdef math stuff for compile with old uclibc.
One odd thing: If compiled with any CFLAGS like Os, O1 etc. results in svg not working. Static linked bin attached as fake .gz-file.
Attachments
xputimage.gz
remove .gz extension to get the static linked binary
(86.88 KiB) Downloaded 255 times
Last edited by goingnuts on Sun 02 Jul 2017, 20:44, edited 1 time in total.

User avatar
greengeek
Posts: 5789
Joined: Tue 20 Jul 2010, 09:34
Location: Republic of Novo Zelande

#394 Post by greengeek »

Tested ok on Slacko 5.6
Opens png and jpg fine, but did not work with a tif i made.

goingnuts
Posts: 932
Joined: Sun 07 Dec 2008, 13:33
Contact:

#395 Post by goingnuts »

Thanks for testing! No tiff support but jpg, png, bmp, gif, SVG and others.
Might have a look at https://github.com/jkriege2/TinyTIFF some time...
Update 20170810: Just realized that my code only works at depth 24 - :(

User avatar
greengeek
Posts: 5789
Joined: Tue 20 Jul 2010, 09:34
Location: Republic of Novo Zelande

#396 Post by greengeek »

technosaurus wrote:In my quest to minimalize jwm (replace, cairo, librsvg, libjpeg and libpng with stb_image and nanosvg), I ended up writing this minimal image viewer:

Note: nanosvg uses zlib license, the rest is public domain

Code: Select all

#include <xcb/xcb.h>
#include <xcb/xcb_image.h>
#define STBI_NO_HDR
#define STBI_NO_LINEAR
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define NANOSVG_IMPLEMENTATION
#include "nanosvg.h"
#define NANOSVGRAST_IMPLEMENTATION
#include "nanosvgrast.h"

int main(int argc, char **argv){
	xcb_connection_t *c = xcb_connect(0, 0);
	xcb_screen_t *s = xcb_setup_roots_iterator(xcb_get_setup(c)).data;
	int w, h, n,
		depth = s->root_depth,
		win_class = XCB_WINDOW_CLASS_INPUT_OUTPUT,
		format = XCB_IMAGE_FORMAT_Z_PIXMAP;
	xcb_colormap_t colormap = s->default_colormap;
	xcb_drawable_t win = xcb_generate_id(c);
	xcb_gcontext_t gc = xcb_generate_id(c);
	xcb_pixmap_t pixmap = xcb_generate_id(c);
	xcb_generic_event_t *ev;
	xcb_image_t *image;
	NSVGimage *shapes = NULL;
	NSVGrasterizer *rast = NULL;
	char *data = NULL;
	unsigned *dp;
	size_t i, len;
	uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
		value_mask = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS,
		values[] = { s->black_pixel, value_mask };

	if (argc<2) return -1;
	if ((data = stbi_load(argv[1], &w, &h, &n, 4)))
		;
	else if ((shapes = nsvgParseFromFile(argv[1], "px", 96.0f))) {
		w = (int)shapes->width;
		h = (int)shapes->height;
		rast = nsvgCreateRasterizer();
		data = malloc(w*h*4);
		nsvgRasterize(rast, shapes, 0,0,1, data, w, h, w*4);
	}else return -1;
	for(i=0,len=w*h,dp=(unsigned *)data;i<len;i++) //rgba to bgra
		dp[i]=dp[i]&0xff00ff00|((dp[i]>>16)&0xFF)|((dp[i]<<16)&0xFF0000);
	xcb_create_window(c,depth,win,s->root,0,0,w,h,1,win_class,s->root_visual,mask,values);
	xcb_create_pixmap(c,depth,pixmap,win,w,h);
	xcb_create_gc(c,gc,pixmap,0,NULL);
	image = xcb_image_create_native(c,w,h,format,depth,data,w*h*4,data);
	xcb_image_put(c, pixmap, gc, image, 0, 0, 0);
	xcb_image_destroy(image);
	xcb_map_window(c, win);
	xcb_flush(c);
	while ((ev = xcb_wait_for_event(c))) {
		switch (ev->response_type & ~0x80){
		case XCB_EXPOSE: {
			xcb_expose_event_t *x = (xcb_expose_event_t *)ev;
			xcb_copy_area(c,pixmap,win,gc,x->x,x->y,x->x,x->y,x->width,x->height);
			xcb_flush(c);
		}break;
		case XCB_BUTTON_PRESS: goto end;
		default: break;
		}
	}
end:
	xcb_free_pixmap(c, pixmap);
	xcb_disconnect(c);
	return 0;
}
90% of the code is just the verbosity of dealing with an xcb window.


An up to date gist to lighten jwm image loading is available at:
https://gist.github.com/technosaurus/36 ... f83d670546
Hi Technosaurus, I am interested in this tiny image viewer (and it's relatives on previous page). How do I potentially use them? Is it "C" code? I tried to stick it in a bash script but of course I am well out of my depth.

I am wanting to display (in a minimal window) jpg files that are accumulated from my webcam based "security camera".

Any suggestions appreciated.

cheers!

EDIT : Do I need to do a "git pull" or something from "technosaurus/jwm-image-lite.c" you linked above - or is that just jwm related?

User avatar
sc0ttman
Posts: 2812
Joined: Wed 16 Sep 2009, 05:44
Location: UK

#397 Post by sc0ttman »

technosaurus wrote:64 bit CPUs have been around for well over a decade now and it's tough to find a used PC that isn't 64 bit.

Puppy has long catered to these older systems, but added support for things like PAE for newer systems. One of the biggest reasons we still use x86 is the extra bloat added for x86_64 just for pointers and long. Since Linux3.4 and gcc 4.7 (and new versions of clang) there is a way to get the faster instructions and smaller function call overhead of x86_64 with 32 bit pointers and long called x32.

I think this is something we should consider. Any thoughts against it?
I came up against an npm install error today that said ia32 not supported, only x32 ... Seems like its a good thing to have, known for its excellent performance :)
[b][url=https://bit.ly/2KjtxoD]Pkg[/url], [url=https://bit.ly/2U6dzxV]mdsh[/url], [url=https://bit.ly/2G49OE8]Woofy[/url], [url=http://goo.gl/bzBU1]Akita[/url], [url=http://goo.gl/SO5ug]VLC-GTK[/url], [url=https://tiny.cc/c2hnfz]Search[/url][/b]

Post Reply