Plan 9 from Bell Labs’s /usr/web/sources/contrib/maht/imgfs/ifslib.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include <draw.h>

#include "ifslib.h"

int
min_int(int a, int b) {
	if ( a < b ) return a;
	return b;
}

int
max_int(int a, int b) {
	if ( a > b ) return a;
	return b;
}

int
get_width(void) {
	return read_atoi_from_file("width") ;
}

int 
get_height(void) {
	return read_atoi_from_file("height");
}

int
set_width(int w) {
	return write_int_to_file("width", w);
}

int
set_height(int h) {
	return write_int_to_file("height", h);
}
	

int
write_int_to_file(char *filename, int i) {
	int fd;
	char *t;
	if(!filename) return 0;

	t = smprint("%d\n", i);
	fd = get_fd(filename, OWRITE|OTRUNC);
	write(fd, t, strlen(t));
	close(fd);
	return 1;
}


int
get_fd(char *fname, int mode) {
	int fd;
	if(!fname) {
		fprint(2, "open for read failed : <nil>\n");
		exits("open failed");
	}
	fd = open(fname, mode);
	if(fd < 0) {
		fprint(2, "open for read failed : %s\n", fname);
		exits("open failed");
	}

	return fd;
}

void
bail(char *msg) {
	if(msg) fprint(2, msg);
	exits(msg);
}

void *
emalloc(ulong size) {
	void* m;

	m = malloc(size);
	if(m) return m;

	exits("out of memory");
	return nil; // stop compiler warning

}

void *
emallocz(ulong size) {
	void* m;

	m = mallocz(size, 1);
	if(m) return m;

	exits("out of memory");
	return nil; // stop compiler warning

}

int
read_atoi_from_file(char *file) {
	int fd;
	char data[64]; // got more than 64 digits?  good luck
	
	fd = open(file, OREAD);
	if(fd < 0) return 0;
	read(fd, data, 64);
	close(fd);

	return atoi(data);  
}

uchar *
read_channel_data(char *filename, long datasize) {
	int fd;
	uchar *data;
	long readbytes;

	data = (uchar*) emalloc(datasize);

	fd = open(filename, OREAD);
	if(fd < 0) return nil;
	readbytes = readn(fd, data, datasize);
	close(fd);

	if (readbytes != datasize) {
		free(data);
		data = nil;
	}

	return data;
}

char *
write_channel_data(char *filename, long datasize, uchar* data) {
	int fd, written;

	if(!filename) return "no filename";

	fd = open(filename, OWRITE);
	if(fd < 0) return smprint("write: open failed : %s", filename);

	written = write(fd, data, datasize);
	if (written != datasize) return "not all bytes written";
	return nil;
}

uchar *
read_channel_rect(char *filename, Rectangle *r) {
	int fd;
	uchar *data, *inpoint;
	long readbytes, datasize;
	int width, y, dw, dh;

	if(!filename) return nil;
	if(!r) return nil;
	clip_rectangle_to_bitmap(r);

	dw = r->max.x - r->min.x;
	dh = r->max.y - r->min.y;

	datasize = dw * dh;
	inpoint = data = (uchar*) emalloc(datasize);

	fd = open(filename, OREAD);
	if(fd < 0) return nil;

	width = get_width();
	readbytes = 0;
	for(y = 0; y < dh; y++) {
		seek(fd, (y + r->min.y) * width + r->min.x, 0);
		readbytes += readn(fd, inpoint, dw);
		inpoint = &inpoint[dw];
	}


	close(fd);

	if (readbytes != datasize) {
		free(data);
		data = nil;
	}

	return data;
}

char *
write_channel_rect(uchar *dry, uchar *selection, char *filename, Rectangle *dst, uchar *wet, uchar *alpha) {
	int fd, written, datasize, x, y, width, dw, dh, i, p;
	float a, s;

	if(!dst) return "no destination rectangle specified";
	if(!filename) return "no filename";

	clip_rectangle_to_bitmap(dst);

	fd = open(filename, OWRITE);
	if(fd < 0) return smprint("write: open failed : %s", filename);

	dw = dst->max.x - dst->min.x;
	dh = dst->max.y - dst->min.y;
	datasize = dw * dh;
	written = 0;
	width = get_width();

	if(alpha == nil && selection == nil) {
		for(y = 0; y < dh; y++) {
			seek(fd, (y + dst->min.y) * width + dst->min.x, 0);
			written += write(fd, wet, dw);
			wet = &wet[dw];
		}
	} else if (selection == nil) {
		i = 0;
		for(y = 0; y < dh; y++) {
			for (x = 0; x < dw; x++) {
				a = (float)alpha[x] / 255.0 ;
				wet[x] = a * wet[x] + (1-a) *  dry[i];
				i++;
			}

			seek(fd, (y + dst->min.y) * width + dst->min.x, 0);
			written += write(fd, wet, dw);
			wet = &wet[dw];
			alpha = &alpha[dw];
		}
	} else if (alpha == nil) {
		i = 0;
		for(y = 0; y < dh; y++) {
			for (x = 0; x < dw; x++) {
				s = (float)selection[i] / 255.0 ;
				wet[x] = s * wet[x] + (1-s) * dry[i];
				i++;
			}
			seek(fd, (y + dst->min.y) * width + dst->min.x, 0);
			written += write(fd, wet, dw);
			wet = &wet[dw];
		}
	} else {
		i = 0;
		for(y = 0; y < dh; y++) {
			for (x = 0; x < dw; x++) {
				s = (float)selection[i] / 255.0 ;
				a = (float)alpha[i] / 255.0 ;
				p = s * a * wet[x] + (1- a * s) * dry[i];
				wet[x] = (uchar)p;
				i++;
			}

			seek(fd, (y + dst->min.y) * width + dst->min.x, 0);
			written += write(fd, wet, dw);
			wet = &wet[dw];
		}
	}
	close(fd);
	if (written != datasize) return "not all bytes written";
	return nil;
}

void
clip_rectangle_to_bitmap(Rectangle *r) {
	int m;

	if(!r) return;

	r->min.x = max_int(0, r->min.x);
	r->min.y = max_int(0, r->min.y);

	m = get_width() ;
	r->max.x = min_int(r->max.x, m);

	m = get_height();
	r->max.y = min_int(r->max.y, m);

	r->min.x = min_int(r->min.x, r->max.x);
	r->max.x = max_int(r->max.x, r->min.x);
	r->min.y = min_int(r->min.y, r->max.y);
	r->max.y = max_int(r->max.y, r->min.y);
	
}

Rectangle* 
rectangle_from_txt(char *txt)
{
	char *args[4];
	Rectangle *r=nil;

	if(!txt) return nil;
	if(getfields(txt, args, 4, 1, ".,-to") == 4) {
		r = (Rectangle*) emalloc(sizeof(Rectangle));
		r->min.x = atoi(args[0]);
		r->min.y = atoi(args[1]);
		r->max.x = atoi(args[2]);
		r->max.y = atoi(args[3]);
	}

	return r;
}

uchar 
get_pixel(uchar *data, int width, int height, float x, float y, int wrap_type) {
	int a,b,c,d;
	int fx, fy, cx, cy, fwy, cwy;
	float dax, day, dbx, dby, dcx, dcy, ddx, ddy;
	long lx, ly;
//print("x %0.2f\n", x);
//print("y %0.2f\n", y);
	switch(wrap_type) {
	case 2 : # 0-max-max-0 i.e. mirrored
		lx = (long) floor(x / width);
		ly = (long) floor(y / height);

		if (lx % 2 == 1)
			x = -x;
		if (ly % 2 == 1)
			y = - y;
	case 1 : # 0-max-0-max i,e, wrap around
		while (x >= width) {
			x -= fabs(floor(x / width)) * width;
		}
		while (x < 0) {
			x += fabs(floor(x / width)) * width;
		}
	
		while (y >= height) {
			y -= fabs(floor(y / height)) * height;
		}

		while (y < 0) {
			y += fabs(floor(y / height) )* height;
		}
		break;

	}
	fx = x;
	cx = fx + 1;
	fy = y;
	cy = fy + 1;

	cy = min_int(cy, height - 1);
	fy = min_int(fy, height - 1);
	cx = min_int(cx, width - 1);
	fx = min_int(fx, width - 1);
	cy = max_int(cy, 0);
	fy = max_int(fy, 0);
	cx = max_int(cx, 0);
	fx = max_int(fx, 0);

	dcx = dax = cx - x;
	dbx = ddx = 1 - dax;
	dby = day = cy - y;
	dcy = ddy = 1 - dby;

	fwy = width * fy;
	cwy = width * cy;

	a = data[fwy + fx];
	b = data[fwy + cx];
	c = data[cwy + fx];
	d = data[cwy + cx];

	return dax * day * a + dbx * dby * b + dcx * dcy * c + ddx * ddy * d;
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].