void i_box(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,const i_color *val) { i_img_dim x,y; dIMCTXim(im); im_log((aIMCTX, 1,"i_box(im* %p, p1(" i_DFp "), p2(" i_DFp "),val %p)\n", im, i_DFcp(x1,y1), i_DFcp(x2,y2), val)); for(x=x1;x<x2+1;x++) { i_ppix(im,x,y1,val); i_ppix(im,x,y2,val); } for(y=y1;y<y2+1;y++) { i_ppix(im,x1,y,val); i_ppix(im,x2,y,val); } }
undef_int i_flood_fill_border(i_img *im, i_img_dim seedx, i_img_dim seedy, const i_color *dcol, const i_color *border) { i_img_dim bxmin, bxmax, bymin, bymax; struct i_bitmap *btm; i_img_dim x, y; dIMCTXim(im); im_log((aIMCTX, 1, "i_flood_cfill(im %p, seed(" i_DFp "), dcol %p, border %p)", im, i_DFcp(seedx, seedy), dcol, border)); im_clear_error(aIMCTX); if (seedx < 0 || seedx >= im->xsize || seedy < 0 || seedy >= im->ysize) { im_push_error(aIMCTX, 0, "i_flood_cfill: Seed pixel outside of image"); return 0; } btm = i_flood_fill_low(im, seedx, seedy, &bxmin, &bxmax, &bymin, &bymax, border, i_ccomp_border); for(y=bymin;y<=bymax;y++) for(x=bxmin;x<=bxmax;x++) if (btm_test(btm,x,y)) i_ppix(im,x,y,dcol); btm_destroy(btm); return 1; }
void i_line_dda(i_img *im, i_img_dim x1, i_img_dim y1, i_img_dim x2, i_img_dim y2, i_color *val) { double dy; i_img_dim x; for(x=x1; x<=x2; x++) { dy = y1+ (x-x1)/(double)(x2-x1)*(y2-y1); i_ppix(im, x, (i_img_dim)(dy+0.5), val); } }
static void i_tt_dump_raster_map_channel( i_img* im, TT_Raster_Map* bit, i_img_dim xb, i_img_dim yb, int channel, int smooth ) { unsigned char *bmap; i_color val; int c; i_img_dim x,y; int old_mask = im->ch_mask; im->ch_mask = 1 << channel; mm_log((1,"i_tt_dump_raster_channel(im %p, bit %p, xb %" i_DF ", yb %" i_DF ", channel %d)\n", im, bit, i_DFc(xb), i_DFc(yb), channel)); bmap = bit->bitmap; if ( smooth ) { for(y=0;y<bit->rows;y++) for(x=0;x<bit->width;x++) { c = bmap[y*(bit->cols)+x]; val.channel[channel] = c; i_ppix(im,x+xb,y+yb,&val); } } else { for(y=0;y<bit->rows;y++) { unsigned mask = 0x80; unsigned char *p = bmap + y * bit->cols; for(x=0;x<bit->width;x++) { val.channel[channel] = (*p & mask) ? 255 : 0; i_ppix(im,x+xb,y+yb,&val); mask >>= 1; if (!mask) { ++p; mask = 0x80; } } } } im->ch_mask = old_mask; }
i_img* i_transform2(i_img_dim width, i_img_dim height, int channels, struct rm_op *ops, int ops_count, double *n_regs, int n_regs_count, i_color *c_regs, int c_regs_count, i_img **in_imgs, int in_imgs_count) { i_img *new_img; i_img_dim x, y; i_color val; int i; int need_images; i_clear_error(); /* since the number of images is variable and the image numbers for getp? are fixed, we can check them here instead of in the register machine - this will help performance */ need_images = 0; for (i = 0; i < ops_count; ++i) { switch (ops[i].code) { case rbc_getp1: case rbc_getp2: case rbc_getp3: if (ops[i].code - rbc_getp1 + 1 > need_images) { need_images = ops[i].code - rbc_getp1 + 1; } } } if (need_images > in_imgs_count) { i_push_errorf(0, "not enough images, code requires %d, %d supplied", need_images, in_imgs_count); return NULL; } new_img = i_img_empty_ch(NULL, width, height, channels); for (x = 0; x < width; ++x) { for (y = 0; y < height; ++y) { n_regs[0] = x; n_regs[1] = y; val = i_rm_run(ops, ops_count, n_regs, n_regs_count, c_regs, c_regs_count, in_imgs, in_imgs_count); i_ppix(new_img, x, y, &val); } } return new_img; }
void lin_stretch(i_img *im, int a, int b) { i_color rcolor; i_img_dim x,y; int i; /* fprintf(stderr,"parameters: (im 0x%x,a %d,b %d)\n",im,a,b);*/ for(y=0;y<im->ysize;y++) for(x=0;x<im->xsize;x++) { i_gpix(im,x,y,&rcolor); for(i=0;i<im->channels;i++) rcolor.channel[i]=saturate((255*(rcolor.channel[i]-a))/(b-a)); i_ppix(im,x,y,&rcolor); } }
void mandlebrot(void *INP) { i_img *im; int i; i_img_dim x,y; int idx; double xs, ys; double div; i_color icl[256]; srand(12235); for(i=1;i<256; i++) { icl[i].rgb.r = 100+(int) (156.0*rand()/(RAND_MAX+1.0)); icl[i].rgb.g = 100+(int) (156.0*rand()/(RAND_MAX+1.0)); icl[i].rgb.b = 100+(int) (156.0*rand()/(RAND_MAX+1.0)); } icl[0].rgb.r = 0; icl[0].rgb.g = 0; icl[0].rgb.b = 0; if ( !getOBJ("image","Imager::ImgRaw",&im) ) { fprintf(stderr,"Error: image is missing\n"); } fprintf(stderr,"mandlebrot: parameters: (im %p)\n",im); fprintf(stderr, "mandlebrot: image info:\n size (" i_DFp ")\n channels (%d)\n", i_DFcp(im->xsize,im->ysize),im->channels); div = 2.5; xs = 0.8*div; ys = 0.5*div; div /= im->xsize; fprintf(stderr, "Divider: %f \n", div); for(y = 0; y < im->ysize; y ++) { for(x = 0; x < im->xsize; x ++ ) { idx = mandel(x*div-xs , y*div-ys); idx = (idx>255)?255:idx; i_ppix(im,x,y,&icl[idx]); } } }
/* =item i_circle_aa(im, x, y, rad, color) =category Drawing =synopsis i_circle_aa(im, 50, 50, 45, &color); Anti-alias fills a circle centered at (x,y) for radius I<rad> with color. =cut */ void i_circle_aa(i_img *im, double x, double y, double rad, const i_color *val) { i_mmarray dot; i_color temp; i_img_dim ly; dIMCTXim(im); im_log((aIMCTX, 1, "i_circle_aa(im %p, centre(" i_DFp "), rad %.2f, val %p)\n", im, i_DFcp(x, y), rad, val)); i_mmarray_cr(&dot,16*im->ysize); make_minmax_list(aIMCTX, &dot, x, y, rad); for(ly = 0; ly<im->ysize; ly++) { int ix, cy, minx = INT_MAX, maxx = INT_MIN; /* Find the left/rightmost set subpixels */ for(cy = 0; cy<16; cy++) { frac tmin = dot.data[ly*16+cy].min; frac tmax = dot.data[ly*16+cy].max; if (tmax == -1) continue; if (minx > tmin) minx = tmin; if (maxx < tmax) maxx = tmax; } if (maxx == INT_MIN) continue; /* no work to be done for this row of pixels */ minx /= 16; maxx /= 16; for(ix=minx; ix<=maxx; ix++) { int cnt = i_pixel_coverage(&dot, ix, ly); if (cnt>255) cnt = 255; if (cnt) { /* should never be true */ int ch; float ratio = (float)cnt/255.0; i_gpix(im, ix, ly, &temp); for(ch=0;ch<im->channels; ch++) temp.channel[ch] = (unsigned char)((float)val->channel[ch]*ratio + (float)temp.channel[ch]*(1.0-ratio)); i_ppix(im, ix, ly, &temp); } } } i_mmarray_dst(&dot); }
void mandelbrot(i_img *im, double minx, double miny, double maxx, double maxy, int max_iter) { int i; i_img_dim x,y; int idx; double divx, divy; i_color icl[256]; srand(12235); for(i=1;i<256; i++) { icl[i].rgb.r = 100+(int) (156.0*rand()/(RAND_MAX+1.0)); icl[i].rgb.g = 100+(int) (156.0*rand()/(RAND_MAX+1.0)); icl[i].rgb.b = 100+(int) (156.0*rand()/(RAND_MAX+1.0)); } icl[0].rgb.r = 0; icl[0].rgb.g = 0; icl[0].rgb.b = 0; if (maxx <= minx) maxx = minx + 1.0; if (maxy <= miny) maxy = miny + 1.0; divx = (maxx - minx) / im->xsize; divy = (maxy - miny) / im->ysize; for(y = 0; y < im->ysize; y ++) { for(x = 0; x < im->xsize; x ++ ) { idx = mandel(minx + x*divx , miny + y*divy, max_iter); idx = idx % 256; i_ppix(im,x,y,&icl[idx]); } } }
/* unused? */ void i_mmarray_render(i_img *im,i_mmarray *ar,i_color *val) { i_img_dim i,x; for(i=0;i<ar->lines;i++) if (ar->data[i].max!=-1) for(x=ar->data[i].min;x<ar->data[i].max;x++) i_ppix(im,x,i,val); }
void i_line_aa(i_img *im, i_img_dim x1, i_img_dim y1, i_img_dim x2, i_img_dim y2, const i_color *val, int endp) { i_img_dim x, y; i_img_dim dx, dy; i_img_dim p; dx = x2 - x1; dy = y2 - y1; /* choose variable to iterate on */ if (i_abs(dx) > i_abs(dy)) { i_img_dim dx2, dy2, cpy; /* sort by x */ if (x1 > x2) { i_img_dim t; t = x1; x1 = x2; x2 = t; t = y1; y1 = y2; y2 = t; } dx = i_abs(dx); dx2 = dx*2; dy = y2 - y1; if (dy<0) { dy = -dy; cpy = -1; } else { cpy = 1; } dy2 = dy*2; p = dy2 - dx2; /* this has to be like this for AA */ y = y1; for(x=x1; x<x2-1; x++) { int ch; i_color tval; double t = (dy) ? -(float)(p)/(float)(dx2) : 1; double t1, t2; if (t<0) t = 0; t1 = 1-t; t2 = t; i_gpix(im,x+1,y,&tval); for(ch=0;ch<im->channels;ch++) tval.channel[ch]=(unsigned char)(t1*(float)tval.channel[ch]+t2*(float)val->channel[ch]); i_ppix(im,x+1,y,&tval); i_gpix(im,x+1,y+cpy,&tval); for(ch=0;ch<im->channels;ch++) tval.channel[ch]=(unsigned char)(t2*(float)tval.channel[ch]+t1*(float)val->channel[ch]); i_ppix(im,x+1,y+cpy,&tval); if (p<0) { p += dy2; } else { y += cpy; p += dy2-dx2; } } } else { i_img_dim dy2, dx2, cpx; /* sort bx y */ if (y1 > y2) { i_img_dim t; t = x1; x1 = x2; x2 = t; t = y1; y1 = y2; y2 = t; } dy = i_abs(dy); dx = x2 - x1; dy2 = dy*2; if (dx<0) { dx = -dx; cpx = -1; } else { cpx = 1; } dx2 = dx*2; p = dx2 - dy2; /* this has to be like this for AA */ x = x1; for(y=y1; y<y2-1; y++) { int ch; i_color tval; double t = (dx) ? -(double)(p)/(double)(dy2) : 1; double t1, t2; if (t<0) t = 0; t1 = 1-t; t2 = t; i_gpix(im,x,y+1,&tval); for(ch=0;ch<im->channels;ch++) tval.channel[ch]=(unsigned char)(t1*(double)tval.channel[ch]+t2*(double)val->channel[ch]); i_ppix(im,x,y+1,&tval); i_gpix(im,x+cpx,y+1,&tval); for(ch=0;ch<im->channels;ch++) tval.channel[ch]=(unsigned char)(t2*(double)tval.channel[ch]+t1*(double)val->channel[ch]); i_ppix(im,x+cpx,y+1,&tval); if (p<0) { p += dx2; } else { x += cpx; p += dx2-dy2; } } } if (endp) { i_ppix(im, x1, y1, val); i_ppix(im, x2, y2, val); } else { if (x1 != x2 || y1 != y2) i_ppix(im, x1, y1, val); } }
void i_line(i_img *im, i_img_dim x1, i_img_dim y1, i_img_dim x2, i_img_dim y2, const i_color *val, int endp) { i_img_dim x, y; i_img_dim dx, dy; i_img_dim p; dx = x2 - x1; dy = y2 - y1; /* choose variable to iterate on */ if (i_abs(dx) > i_abs(dy)) { i_img_dim dx2, dy2, cpy; /* sort by x */ if (x1 > x2) { i_img_dim t; t = x1; x1 = x2; x2 = t; t = y1; y1 = y2; y2 = t; } dx = i_abs(dx); dx2 = dx*2; dy = y2 - y1; if (dy<0) { dy = -dy; cpy = -1; } else { cpy = 1; } dy2 = dy*2; p = dy2 - dx; y = y1; for(x=x1; x<x2-1; x++) { if (p<0) { p += dy2; } else { y += cpy; p += dy2-dx2; } i_ppix(im, x+1, y, val); } } else { i_img_dim dy2, dx2, cpx; /* sort bx y */ if (y1 > y2) { i_img_dim t; t = x1; x1 = x2; x2 = t; t = y1; y1 = y2; y2 = t; } dy = i_abs(dy); dx = x2 - x1; dy2 = dy*2; if (dx<0) { dx = -dx; cpx = -1; } else { cpx = 1; } dx2 = dx*2; p = dx2 - dy; x = x1; for(y=y1; y<y2-1; y++) { if (p<0) { p += dx2; } else { x += cpx; p += dx2-dy2; } i_ppix(im, x, y+1, val); } } if (endp) { i_ppix(im, x1, y1, val); i_ppix(im, x2, y2, val); } else { if (x1 != x2 || y1 != y2) i_ppix(im, x1, y1, val); } }
int (i_ppix)(i_img *im, i_img_dim x, i_img_dim y, const i_color *val) { return i_ppix(im, x, y, val); }
int i_ppix_norm(i_img *im, i_img_dim x, i_img_dim y, i_color const *col) { i_color src; i_color work; int dest_alpha; int remains; if (!col->channel[3]) return 0; switch (im->channels) { case 1: work = *col; i_adapt_colors(2, 4, &work, 1); i_gpix(im, x, y, &src); remains = 255 - work.channel[1]; src.channel[0] = (src.channel[0] * remains + work.channel[0] * work.channel[1]) / 255; return i_ppix(im, x, y, &src); case 2: work = *col; i_adapt_colors(2, 4, &work, 1); i_gpix(im, x, y, &src); remains = 255 - work.channel[1]; dest_alpha = work.channel[1] + remains * src.channel[1] / 255; if (work.channel[1] == 255) { return i_ppix(im, x, y, &work); } else { src.channel[0] = (work.channel[1] * work.channel[0] + remains * src.channel[0] * src.channel[1] / 255) / dest_alpha; src.channel[1] = dest_alpha; return i_ppix(im, x, y, &src); } case 3: work = *col; i_gpix(im, x, y, &src); remains = 255 - work.channel[3]; src.channel[0] = (src.channel[0] * remains + work.channel[0] * work.channel[3]) / 255; src.channel[1] = (src.channel[1] * remains + work.channel[1] * work.channel[3]) / 255; src.channel[2] = (src.channel[2] * remains + work.channel[2] * work.channel[3]) / 255; return i_ppix(im, x, y, &src); case 4: work = *col; i_gpix(im, x, y, &src); remains = 255 - work.channel[3]; dest_alpha = work.channel[3] + remains * src.channel[3] / 255; if (work.channel[3] == 255) { return i_ppix(im, x, y, &work); } else { src.channel[0] = (work.channel[3] * work.channel[0] + remains * src.channel[0] * src.channel[3] / 255) / dest_alpha; src.channel[1] = (work.channel[3] * work.channel[1] + remains * src.channel[1] * src.channel[3] / 255) / dest_alpha; src.channel[2] = (work.channel[3] * work.channel[2] + remains * src.channel[2] * src.channel[3] / 255) / dest_alpha; src.channel[3] = dest_alpha; return i_ppix(im, x, y, &src); } } return 0; }
int i_arc_out(i_img *im, i_img_dim xc, i_img_dim yc, i_img_dim r, double d1, double d2, const i_color *col) { i_img_dim x, y; i_img_dim dx, dy; int error; i_img_dim segs[2][2]; int seg_count; i_img_dim sin_th; i_img_dim seg_d1, seg_d2; int seg_num; i_img_dim scale = r + 1; i_img_dim seg1 = scale * 2; i_img_dim seg2 = scale * 4; i_img_dim seg3 = scale * 6; i_img_dim seg4 = scale * 8; dIMCTXim(im); im_log((aIMCTX,1,"i_arc_out(im %p,centre(" i_DFp "), rad %" i_DF ", d1 %f, d2 %f, col %p)", im, i_DFcp(xc, yc), i_DFc(r), d1, d2, col)); im_clear_error(aIMCTX); if (r <= 0) { im_push_error(aIMCTX, 0, "arc: radius must be non-negative"); return 0; } if (d1 + 360 <= d2) return i_circle_out(im, xc, yc, r, col); if (d1 < 0) d1 += 360 * floor((-d1 + 359) / 360); if (d2 < 0) d2 += 360 * floor((-d2 + 359) / 360); d1 = fmod(d1, 360); d2 = fmod(d2, 360); seg_d1 = arc_seg(d1, scale); seg_d2 = arc_seg(d2, scale); if (seg_d2 < seg_d1) { /* split into two segments */ segs[0][0] = 0; segs[0][1] = seg_d2; segs[1][0] = seg_d1; segs[1][1] = seg4; seg_count = 2; } else { segs[0][0] = seg_d1; segs[0][1] = seg_d2; seg_count = 1; } for (seg_num = 0; seg_num < seg_count; ++seg_num) { i_img_dim seg_start = segs[seg_num][0]; i_img_dim seg_end = segs[seg_num][1]; if (seg_start == 0) i_ppix(im, xc+r, yc, col); if (seg_start <= seg1 && seg_end >= seg1) i_ppix(im, xc, yc+r, col); if (seg_start <= seg2 && seg_end >= seg2) i_ppix(im, xc-r, yc, col); if (seg_start <= seg3 && seg_end >= seg3) i_ppix(im, xc, yc-r, col); y = 0; x = r; dy = 1; dx = -2 * r; error = 1 - r; while (y < x) { if (error >= 0) { --x; dx += 2; error += dx; } ++y; dy += 2; error += dy; sin_th = y; if (seg_start <= sin_th && seg_end >= sin_th) i_ppix(im, xc + x, yc + y, col); if (seg_start <= seg1 - sin_th && seg_end >= seg1 - sin_th) i_ppix(im, xc + y, yc + x, col); if (seg_start <= seg1 + sin_th && seg_end >= seg1 + sin_th) i_ppix(im, xc - y, yc + x, col); if (seg_start <= seg2 - sin_th && seg_end >= seg2 - sin_th) i_ppix(im, xc - x, yc + y, col); if (seg_start <= seg2 + sin_th && seg_end >= seg2 + sin_th) i_ppix(im, xc - x, yc - y, col); if (seg_start <= seg3 - sin_th && seg_end >= seg3 - sin_th) i_ppix(im, xc - y, yc - x, col); if (seg_start <= seg3 + sin_th && seg_end >= seg3 + sin_th) i_ppix(im, xc + y, yc - x, col); if (seg_start <= seg4 - sin_th && seg_end >= seg4 - sin_th) i_ppix(im, xc + x, yc - y, col); } } return 1; }
int i_circle_out(i_img *im, i_img_dim xc, i_img_dim yc, i_img_dim r, const i_color *col) { i_img_dim x, y; i_img_dim dx, dy; int error; dIMCTXim(im); im_log((aIMCTX, 1, "i_circle_out(im %p, centre(" i_DFp "), rad %" i_DF ", col %p)\n", im, i_DFcp(xc, yc), i_DFc(r), col)); im_clear_error(aIMCTX); if (r < 0) { im_push_error(aIMCTX, 0, "circle: radius must be non-negative"); return 0; } i_ppix(im, xc+r, yc, col); i_ppix(im, xc-r, yc, col); i_ppix(im, xc, yc+r, col); i_ppix(im, xc, yc-r, col); x = 0; y = r; dx = 1; dy = -2 * r; error = 1 - r; while (x < y) { if (error >= 0) { --y; dy += 2; error += dy; } ++x; dx += 2; error += dx; i_ppix(im, xc + x, yc + y, col); i_ppix(im, xc + x, yc - y, col); i_ppix(im, xc - x, yc + y, col); i_ppix(im, xc - x, yc - y, col); if (x != y) { i_ppix(im, xc + y, yc + x, col); i_ppix(im, xc + y, yc - x, col); i_ppix(im, xc - y, yc + x, col); i_ppix(im, xc - y, yc - x, col); } } return 1; }
undef_int i_t1_cp(i_t1_font_t font, i_img *im,i_img_dim xb,i_img_dim yb,int channel,double points,char* str,size_t len,int align, int utf8, char const *flags, int aa) { GLYPH *glyph; int xsize,ysize,x,y; i_color val; int mod_flags = t1_get_flags(flags); int fontnum = font->font_id; unsigned int ch_mask_store; i_clear_error(); mm_log((1, "i_t1_cp(font %p (%d), im %p, (xb,yb)=" i_DFp ", channel %d, points %g, str %p, len %u, align %d, utf8 %d, flags '%s', aa %d)\n", font, fontnum, im, i_DFcp(xb, yb), channel, points, str, (unsigned)len, align, utf8, flags, aa)); if (im == NULL) { mm_log((1,"i_t1_cp: Null image in input\n")); i_push_error(0, "null image"); return(0); } i_mutex_lock(mutex); i_t1_set_aa(aa); if (utf8) { int worklen; char *work = t1_from_utf8(str, len, &worklen); if (work == NULL) { i_mutex_unlock(mutex); return 0; } glyph=T1_AASetString( fontnum, work, worklen, 0, mod_flags, points, NULL); myfree(work); } else { glyph=T1_AASetString( fontnum, str, len, 0, mod_flags, points, NULL); } if (glyph == NULL) { t1_push_error(); i_push_error(0, "i_t1_cp: T1_AASetString failed"); i_mutex_unlock(mutex); return 0; } mm_log((1,"metrics: ascent: %d descent: %d\n",glyph->metrics.ascent,glyph->metrics.descent)); mm_log((1," leftSideBearing: %d rightSideBearing: %d\n",glyph->metrics.leftSideBearing,glyph->metrics.rightSideBearing)); mm_log((1," advanceX: %d advanceY: %d\n",glyph->metrics.advanceX,glyph->metrics.advanceY)); mm_log((1,"bpp: %lu\n", (unsigned long)glyph->bpp)); xsize=glyph->metrics.rightSideBearing-glyph->metrics.leftSideBearing; ysize=glyph->metrics.ascent-glyph->metrics.descent; mm_log((1,"width: %d height: %d\n",xsize,ysize)); ch_mask_store=im->ch_mask; im->ch_mask=1<<channel; if (align==1) { xb+=glyph->metrics.leftSideBearing; yb-=glyph->metrics.ascent; } for(y=0;y<ysize;y++) for(x=0;x<xsize;x++) { val.channel[channel]=glyph->bits[y*xsize+x]; i_ppix(im,x+xb,y+yb,&val); } im->ch_mask=ch_mask_store; i_mutex_unlock(mutex); return 1; }