#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;
}
|