#include #include #include #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 : \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; }