#include "image.h" #include "palette.h" #include "font.h" #include #include #include #include Image::Image() : iWidth( 0 ), iHeight( 0 ), pPix( NULL ) { } Image::Image( int32_t iWidth, int32_t iHeight ) : iWidth( iWidth ), iHeight( iHeight ), pPix( NULL ) { pPix = new uint8_t[iWidth*iHeight]; clear(); } Image::~Image() { delete[] pPix; } int Image::getWidth() const { return iWidth; } int Image::getHeight() const { return iHeight; } void Image::clear( uint8_t uColor ) { memset( pPix, uColor, iWidth*iHeight ); } void Image::set( int32_t x, int32_t y, uint8_t iCol ) { if( x < 0 || y < 0 || x >= iWidth || y >= iHeight ) return; pPix[x+y*iWidth] = iCol; } void Image::save( const char *sPath, class Palette &rPal ) { uint8_t **pRows = new uint8_t*[iHeight]; for( int r = 0; r < iHeight; r++ ) { pRows[r] = pPix+(iWidth*r); } png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); png_infop info_ptr = png_create_info_struct(png_ptr); png_set_IHDR(png_ptr, info_ptr, iWidth, iHeight, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); png_color *pCol = new png_color[rPal.getCount()]; for( int j = 0; j < rPal.getCount(); j++ ) { uint8_t r, g, b; rPal.getColor( j, r, g, b ); pCol[j].red = r; pCol[j].green = g; pCol[j].blue = b; } png_set_PLTE( png_ptr, info_ptr, pCol, rPal.getCount()); png_set_rows( png_ptr, info_ptr, pRows ); FILE *fp = fopen(sPath, "wb"); if( fp == NULL ) { printf("Error opening file!\n"); exit( 1 ); } png_init_io( png_ptr, fp ); png_write_png( png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL ); png_destroy_write_struct( &png_ptr, &info_ptr ); fclose( fp ); delete[] pCol; delete[] pRows; } void Image::drawText( class Font &rFnt, int32_t x, int32_t y, uint8_t uColor, const char *sText ) { for( const char *s = sText; *s; s++ ) { Font::Glyph *pGlyph = rFnt.get( *s ); if( pGlyph == NULL ) continue; for( int cy = 0; cy < pGlyph->pBox.y; cy++ ) { for( int cx = 0; cx < pGlyph->pBox.x; cx++ ) { int bit = 1<<(7-(cx%8)); int byte = cx/8; if( pGlyph->pData[byte+cy*pGlyph->iRowBytes]&bit ) set( x+cx, y+cy-pGlyph->pBox.y-pGlyph->pOff.y, uColor ); } } x += pGlyph->pDevOff.x; y += pGlyph->pDevOff.y; } } void Image::drawLine( int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint8_t uColor ) { if( x1 == x2 ) { // Vertical line, easy if( y2 < y1 ) { int32_t r = y2; y2 = y1; y1 = r; } for( int j = y1; j <= y2; j++ ) { set( x1, j, uColor ); } } else if( y1 == y2 ) { // Horizontal line, easy if( x2 < x1 ) { int32_t r = x2; x2 = x1; x1 = r; } for( int j = x1; j <= x2; j++ ) { set( j, y1, uColor ); } } else { int xd = x2-x1; int yd = y2-y1; float d = sqrt( xd*xd + yd*yd ); float ux = xd/d; float uy = yd/d; float x = x1; float y = y1; set( (int)x, (int)y, uColor ); for( float n = 0.0; n < d; n += 1.0 ) { x += ux; y += uy; set( (int)x, (int)y, uColor ); } } }