void TCOD_image_rotate90(TCOD_image_t image, int numRotations) { int px,py; int width,height; numRotations = numRotations % 4; if (numRotations == 0 ) return; if ( numRotations < 0 ) numRotations += 4; TCOD_image_get_size(image,&width,&height); if (numRotations == 1) { /* rotate 90 degrees */ TCOD_image_t newImg=TCOD_image_new(height,width); image_data_t *img=(image_data_t *)image; image_data_t *img2=(image_data_t *)newImg; for (px = 0; px < width; px++ ) { for (py = 0; py < height; py++ ) { TCOD_color_t col1=TCOD_image_get_pixel(image,px,py); TCOD_image_put_pixel(newImg,height-1-py,px,col1); } } TCOD_image_delete_internal(image); /* update img with the new image content */ img->mipmaps = img2->mipmaps; img->sys_img=NULL; img->nb_mipmaps=img2->nb_mipmaps; free(img2); } else if ( numRotations == 2 ) { /* rotate 180 degrees */ int maxy=height/2 + ((height & 1) == 1? 1 : 0 ); for (px = 0; px < width; px++ ) { for (py = 0; py < maxy; py++ ) { if ( py != height-1-py || px < width/2 ) { TCOD_color_t col1=TCOD_image_get_pixel(image,px,py); TCOD_color_t col2=TCOD_image_get_pixel(image,width-1-px,height-1-py); TCOD_image_put_pixel(image,px,py,col2); TCOD_image_put_pixel(image,width-1-px,height-1-py,col1); } } } } else if (numRotations == 3) { /* rotate 270 degrees */ TCOD_image_t newImg=TCOD_image_new(height,width); image_data_t *img=(image_data_t *)image; image_data_t *img2=(image_data_t *)newImg; for (px = 0; px < width; px++ ) { for (py = 0; py < height; py++ ) { TCOD_color_t col1=TCOD_image_get_pixel(image,px,py); TCOD_image_put_pixel(newImg,py,width-1-px,col1); } } TCOD_image_delete_internal(image); /* update img with the new image content */ img->mipmaps = img2->mipmaps; img->sys_img=NULL; img->nb_mipmaps=img2->nb_mipmaps; free(img2); } }
void TCOD_image_vflip(TCOD_image_t image) { int px,py; int width,height; TCOD_image_get_size(image,&width,&height); for (px = 0; px < width; px++ ) { for (py = 0; py < height/2; py++ ) { TCOD_color_t col1=TCOD_image_get_pixel(image,px,py); TCOD_color_t col2=TCOD_image_get_pixel(image,px,height-1-py); TCOD_image_put_pixel(image,px,py,col2); TCOD_image_put_pixel(image,px,height-1-py,col1); } } }
void TCOD_sys_update_char(int asciiCode, int fontx, int fonty, TCOD_image_t img, int x, int y) { int px,py; int iw,ih; static TCOD_color_t pink={255,0,255}; TCOD_sys_map_ascii_to_font(asciiCode,fontx,fonty); TCOD_image_get_size(img,&iw,&ih); for (px=0; px < fontWidth; px ++ ) { for (py=0;py < fontHeight; py++ ) { TCOD_color_t col=TCOD_white; Uint8 *pixel; Uint8 bpp; if ( (unsigned)(x+px) < (unsigned)iw && (unsigned)(y+py) < (unsigned)ih ) { col=TCOD_image_get_pixel(img,x+px,y+py); } pixel=(Uint8 *)(charmap->pixels) + (fonty*fontHeight+py) * charmap->pitch + (fontx*fontWidth+px) * charmap->format->BytesPerPixel; bpp = charmap->format->BytesPerPixel; if (bpp == 4 ) { *((pixel)+charmap->format->Ashift/8) = col.r; *((pixel)+charmap->format->Rshift/8)=255; *((pixel)+charmap->format->Gshift/8)=255; *((pixel)+charmap->format->Bshift/8)=255; } else { *((pixel)+charmap->format->Rshift/8)=col.r; *((pixel)+charmap->format->Gshift/8)=col.g; *((pixel)+charmap->format->Bshift/8)=col.b; } } } // TODO : improve this. Won't work if we want a pink portrait... charcols[asciiCode]=pink; ascii_updated[asciiCode]=true; any_ascii_updated=true; }
// render when no font is loaded (happens when using some TCODImage stuff without root console) void TCOD_sys_console_to_bitmap_nocharmap(void *vbitmap, TCOD_console_data_t *con, bool new_font) { int x,y; SDL_Surface *bitmap=(SDL_Surface *)vbitmap; Uint32 sdl_back=0; TCOD_color_t fading_color = TCOD_console_get_fading_color(); int fade = (int)TCOD_console_get_fade(); bool track_changes=(TCOD_old_fade == fade && con->oldbuf); for (y=0;y<con->h;y++) { for (x=0; x<con->w; x++) { SDL_Rect dstRect; bool changed=true; char_t *c=&con->buf[x+y*con->w]; TCOD_bitmap_char_t *bitmap_char=&TCOD_font_chars[c->c]; TCOD_color_t b=TCOD_image_get_pixel(con->backbuf,x,y); if ( c->cf == -1 ) c->cf = bitmap_char->ascii_to_tcod; if ( track_changes ) { TCOD_color_t oldb=TCOD_image_get_pixel(con->oldbackbuf,x,y); changed=false; if ( bitmap_char->updated || b.r != oldb.r || b.g != oldb.g || b.b != oldb.b ) { changed=true; } } if ( changed ) { dstRect.x=x*TCOD_font_width; dstRect.y=y*TCOD_font_height; dstRect.w=TCOD_font_width; dstRect.h=TCOD_font_height; // draw background if ( fade != 255 ) { b.r = ((int)b.r) * fade / 255 + ((int)fading_color.r) * (255-fade)/255; b.g = ((int)b.g) * fade / 255 + ((int)fading_color.g) * (255-fade)/255; b.b = ((int)b.b) * fade / 255 + ((int)fading_color.b) * (255-fade)/255; } sdl_back=SDL_MapRGB(bitmap->format,b.r,b.g,b.b); if ( bitmap == TCOD_screen && TCOD_fullscreen_on ) { dstRect.x+=TCOD_fullscreen_offsetx; dstRect.y+=TCOD_fullscreen_offsety; } SDL_FillRect(bitmap,&dstRect,sdl_back); } } } TCOD_old_fade=fade; }
bool TCOD_image_is_pixel_transparent(TCOD_image_t image, int x, int y) { image_data_t *img=(image_data_t *)image; TCOD_color_t col=TCOD_image_get_pixel(image,x,y); if ( img->has_key_color && img->key_color.r == col.r && img->key_color.g == col.g && img->key_color.b == col.b ) { return true; } if ( TCOD_image_get_alpha(image,x,y) == 0 ) return true; return false; }
colornum_t TCOD_image_get_pixel_wrapper(TCOD_image_t image, int x, int y) { return color_to_int(TCOD_image_get_pixel (image, x, y)); }
TCODColor TCODImage::getPixel(int x, int y) const { return TCOD_image_get_pixel(data,x,y); }
void TCOD_image_blit_2x(TCOD_image_t image, TCOD_console_t con, int dx, int dy, int sx, int sy, int w, int h) { TCOD_color_t grid[4]; TCOD_color_t cols[2]; int nbCols; int width,height,ascii,cx,cy; TCOD_console_data_t *dat; image_data_t *img=(image_data_t *)image; int maxx,maxy; TCOD_IFNOT(image != NULL) return; TCOD_image_get_size(image,&width,&height); if ( con == NULL ) dat = TCOD_root; else dat=(TCOD_console_data_t *)(con); if ( w == -1 ) w=width; if ( h == -1 ) h=height; // check that the sx,sy/w,h rectangle is inside the image TCOD_ASSERT(sx >= 0 && sy >= 0 && sx+w <= width && sy+h <= height); TCOD_IFNOT(w > 0 && h > 0) return; sx=MAX(0,sx); sy=MAX(0,sy); w = MIN(w,width-sx); h = MIN(h,height-sy); maxx=dx+w/2 <= dat->w ? w : (dat->w-dx)*2; maxy=dy+h/2 <= dat->h ? h : (dat->h-dy)*2; // check that the image is not blitted outside the console TCOD_IFNOT(dx+maxx/2 >= 0 && dy+maxy/2 >= 0 && dx < dat->w && dy < dat->h) return; maxx+=sx; maxy+=sy; for (cx=sx; cx < maxx; cx += 2) { for (cy=sy; cy < maxy; cy += 2) { // get the 2x2 super pixel colors from the image int conx=dx+(cx-sx)/2; int cony=dy+(cy-sy)/2; TCOD_color_t consoleBack=TCOD_console_get_back(con,conx,cony); grid[0]=TCOD_image_get_pixel(image,cx,cy); if ( img->has_key_color && grid[0].r == img->key_color.r && grid[0].g == img->key_color.g && grid[0].b == img->key_color.b) grid[0]=consoleBack; if ( cx < w-1 ) { grid[1]=TCOD_image_get_pixel(image,cx+1,cy); if ( img->has_key_color && grid[1].r == img->key_color.r && grid[1].g == img->key_color.g && grid[1].b == img->key_color.b) grid[1]=consoleBack; } else grid[1]=consoleBack; if ( cy < h-1 ) { grid[2]=TCOD_image_get_pixel(image,cx,cy+1); if ( img->has_key_color && grid[2].r == img->key_color.r && grid[2].g == img->key_color.g && grid[2].b == img->key_color.b) grid[2]=consoleBack; } else grid[2]=consoleBack; if ( cx < w-1 && cy < h-1 ) { grid[3]=TCOD_image_get_pixel(image,cx+1,cy+1); if ( img->has_key_color && grid[3].r == img->key_color.r && grid[3].g == img->key_color.g && grid[3].b == img->key_color.b) grid[3]=consoleBack; } else grid[3]=consoleBack; // analyse color, posterize, get pattern getPattern(grid,cols,&nbCols,&ascii); if ( nbCols == 1 ) { // single color TCOD_console_set_back(con,conx,cony,cols[0],TCOD_BKGND_SET); TCOD_console_set_char(con,conx,cony,' '); } else { if ( ascii >= 0 ) { TCOD_console_set_background_color(con,cols[0]); TCOD_console_set_foreground_color(con,cols[1]); TCOD_console_put_char(con,conx,cony,ascii,TCOD_BKGND_SET); } else { // negative ascii code means we need to invert back/fore colors TCOD_console_set_background_color(con,cols[1]); TCOD_console_set_foreground_color(con,cols[0]); TCOD_console_put_char(con,conx,cony,-ascii,TCOD_BKGND_SET); } } } } }
void TCOD_image_scale(TCOD_image_t image, int neww, int newh) { image_data_t *img=(image_data_t *)image; int px,py; int width,height; image_data_t *newimg; TCOD_image_get_size(image,&width,&height); if ( neww==width && newh==height ) return; if ( neww == 0 || newh == 0 ) return; newimg=(image_data_t *)TCOD_image_new(neww,newh); if ( neww < width && newh < height ) { // scale down image, using supersampling for (py = 0; py < newh; py++ ) { float y0 = (float)(py) * height / newh; float y0floor = (float)floor(y0); float y0weight = 1.0f - (y0 - y0floor); int iy0 = (int)y0floor; float y1 = (float)(py+1) * height / newh; float y1floor = (float)floor(y1-0.00001); float y1weight = (y1 - y1floor); int iy1 = (int)y1floor; for (px = 0; px < neww; px++ ) { TCOD_color_t col; float x0 = (float)(px) * width / neww; float x0floor = (float)floor(x0); float x0weight = 1.0f - (x0 - x0floor); int ix0 = (int)x0floor; float x1 = (float)(px+1) * width / neww; float x1floor = (float)floor(x1- 0.00001); float x1weight = (x1 - x1floor); int ix1 = (int)x1floor; float r=0,g=0,b=0,sumweight=0.0f; int srcx,srcy; // left & right fractional edges for (srcy=(int)(y0+1); srcy < (int)y1; srcy++) { TCOD_color_t col_left=TCOD_image_get_pixel(image,ix0,srcy); TCOD_color_t col_right=TCOD_image_get_pixel(image,ix1,srcy); r += col_left.r * x0weight + col_right.r * x1weight; g += col_left.g * x0weight + col_right.g * x1weight; b += col_left.b * x0weight + col_right.b * x1weight; sumweight += x0weight+x1weight; } // top & bottom fractional edges for (srcx = (int)(x0+1); srcx < (int)x1; srcx++) { TCOD_color_t col_top=TCOD_image_get_pixel(image,srcx,iy0); TCOD_color_t col_bottom=TCOD_image_get_pixel(image,srcx,iy1); r += col_top.r * y0weight + col_bottom.r * y1weight; g += col_top.g * y0weight + col_bottom.g * y1weight; b += col_top.b * y0weight + col_bottom.b * y1weight; sumweight += y0weight+y1weight; } // center for (srcy=(int)(y0+1); srcy < (int)y1; srcy++) { for (srcx = (int)(x0+1); srcx < (int)x1; srcx++) { TCOD_color_t col=TCOD_image_get_pixel(image,srcx,srcy); r += col.r; g += col.g; b += col.b; sumweight += 1.0f; } } // corners col=TCOD_image_get_pixel(image,ix0,iy0); r += col.r * (x0weight * y0weight); g += col.g * (x0weight * y0weight); b += col.b * (x0weight * y0weight); sumweight += x0weight * y0weight; col=TCOD_image_get_pixel(image,ix0,iy1); r += col.r * (x0weight * y1weight); g += col.g * (x0weight * y1weight); b += col.b * (x0weight * y1weight); sumweight += x0weight * y1weight; col=TCOD_image_get_pixel(image,ix1,iy1); r += col.r * (x1weight * y1weight); g += col.g * (x1weight * y1weight); b += col.b * (x1weight * y1weight); sumweight += x1weight * y1weight; col=TCOD_image_get_pixel(image,ix1,iy0); r += col.r * (x1weight * y0weight); g += col.g * (x1weight * y0weight); b += col.b * (x1weight * y0weight); sumweight += x1weight * y0weight; sumweight = 1.0f / sumweight; r = r*sumweight + 0.5f; g = g*sumweight + 0.5f; b = b*sumweight + 0.5f; col.r=(int)r; col.g=(int)g; col.b=(int)b; TCOD_image_put_pixel(newimg,px,py,col); } } } else { // scale up image, using nearest neightbor for (py = 0; py < newh; py++ ) { int srcy = py * height / newh; for (px = 0; px < neww; px++ ) { int srcx = px * width / neww; TCOD_color_t col=TCOD_image_get_pixel(image,srcx,srcy); TCOD_image_put_pixel(newimg,px,py,col); } } } // destroy old image if ( img->mipmaps ) { int i; for ( i=0; i < img->nb_mipmaps; i++) { if ( img->mipmaps[i].buf ) free(img->mipmaps[i].buf); } free(img->mipmaps); } if ( img->sys_img ) { TCOD_sys_delete_bitmap(img->sys_img); } // update img with the new image content img->mipmaps = newimg->mipmaps; img->sys_img=NULL; img->nb_mipmaps=newimg->nb_mipmaps; free(newimg); }
void TCOD_image_blit(TCOD_image_t image, TCOD_console_t console, float x, float y, TCOD_bkgnd_flag_t bkgnd_flag, float scalex, float scaley, float angle) { int width,height; image_data_t *img=(image_data_t *)image; if ( scalex == 0.0f || scaley == 0.0f || bkgnd_flag == TCOD_BKGND_NONE ) return; TCOD_image_get_size(image,&width,&height); if ( scalex == 1.0f && scaley == 1.0f && angle == 0.0f && x-((int)x) == 0.0f && y-((int)y)==0.0f) { // clip the image int ix = (int)(x - width*0.5f); int iy = (int)(y - height*0.5f); int minx=MAX(ix,0); int miny=MAX(iy,0); int maxx=MIN(ix+width,TCOD_console_get_width(console)); int maxy=MIN(iy+height,TCOD_console_get_height(console)); int offx=0,offy=0; int cx,cy; if ( ix < 0 ) offx=-ix; if ( iy < 0 ) offy=-iy; for (cx=minx; cx < maxx; cx ++) { for (cy=miny; cy < maxy; cy ++) { TCOD_color_t col=TCOD_image_get_pixel(image,cx-minx+offx,cy-miny+offy); if ( !img->has_key_color || img->key_color.r != col.r || img->key_color.g != col.g || img->key_color.b != col.b ) { TCOD_console_set_back(console,cx,cy,col,bkgnd_flag); } } } } else { float iw=width/2*scalex; float ih=height/2*scaley; // get the coordinates of the image corners in the console float newx_x = cosf(angle); float newx_y = -sinf(angle); float newy_x = newx_y; float newy_y = -newx_x; float x0,y0,x1,y1,x2,y2,x3,y3; // image corners coordinates int rx,ry,rw,rh; // rectangular area in the console int cx,cy; int minx,miny,maxx,maxy; float invscalex,invscaley; // 0 = P - w/2 x' +h/2 y' x0 = x-iw*newx_x+ih*newy_x; y0 = y-iw*newx_y+ih*newy_y; // 1 = P + w/2 x' + h/2 y' x1 = x+iw*newx_x+ih*newy_x; y1 = y+iw*newx_y+ih*newy_y; // 2 = P + w/2 x' - h/2 y' x2 = x+iw*newx_x-ih*newy_x; y2 = y+iw*newx_y-ih*newy_y; // 3 = P - w/2 x' - h/2 y' x3 = x-iw*newx_x-ih*newy_x; y3 = y-iw*newx_y-ih*newy_y; // get the affected rectangular area in the console rx=(int)(MIN(MIN(x0,x1),MIN(x2,x3))); ry=(int)(MIN(MIN(y0,y1),MIN(y2,y3))); rw=(int)(MAX(MAX(x0,x1),MAX(x2,x3))) - rx; rh=(int)(MAX(MAX(y0,y1),MAX(y2,y3))) - ry; // clip it minx=MAX(rx,0); miny=MAX(ry,0); maxx=MIN(rx+rw,TCOD_console_get_width(console)); maxy=MIN(ry+rh,TCOD_console_get_height(console)); invscalex=1.0f / scalex; invscaley=1.0f / scaley; for (cx=minx; cx < maxx; cx ++) { for (cy=miny; cy < maxy; cy ++) { float ix,iy; TCOD_color_t col; // map the console pixel to the image world ix = (iw+ (cx-x) * newx_x + (cy-y) *(-newy_x))*invscalex; iy = (ih + (cx-x) * (newx_y) - (cy-y)*newy_y)*invscaley; col = TCOD_image_get_pixel(image,(int)(ix),(int)(iy)); if ( !img->has_key_color || img->key_color.r != col.r || img->key_color.g != col.g || img->key_color.b != col.b ) { if ( scalex < 1.0f || scaley < 1.0f ) { col = TCOD_image_get_mipmap_pixel(image,ix,iy,ix+1.0f,iy+1.0f); } TCOD_console_set_back(console,cx,cy,col,bkgnd_flag); } } } } }