int Image32::FunFilter(Image32& outputImage) const { double height = this->height(); double width = this->width(); for(int y=0; y<height; ++y){ for(int x=0; x<width; ++x){ double y1 = (double) y / (double) (height-1.0); double x1 = (double) x / (double) (width-1.0); double r = sqrt( pow(x1 - 0.5, 2.0) + pow(y1 - 0.5, 2.0) ); double a = atan2((y1 - 0.5) , (x1 - 0.5)); double rd = pow(r, 2.5)/.5; float xNew = ((rd*cos(a)) + 0.5) * (width-1); float yNew = ((rd*sin(a)) + 0.5) * (height-1); Pixel32 pix = this->NearestSample(xNew,yNew); outputImage.pixel(x,y).r = pix.r; outputImage.pixel(x,y).g = pix.g; outputImage.pixel(x,y).b = pix.b; } } return 1; }
/* * scales each pixel's rgb by the brightness factor to increase brightness */ int Image32::Brighten(const float& brightness,Image32& outputImage) const { int r1, g1, b1; for (int x = 0; x < outputImage.width(); x++) for (int y = 0; y < outputImage.height(); y++) { // clamp [0,255] r1 = (int)(pixel(x,y).r*brightness); if (r1 > 255) r1 = 255; if (r1 < 0) r1 = 0; g1 = (int)(pixel(x,y).g*brightness); if (g1 > 255) g1 = 255; if (g1 < 0) g1 = 0; b1 = (int)(pixel(x,y).b*brightness); if (b1 > 255) b1 = 255; if (b1 < 0) b1 = 0; // write clamped values to outputImage outputImage.pixel(x,y).r = r1; outputImage.pixel(x,y).g = g1; outputImage.pixel(x,y).b = b1; } return 1; }
int Image32::Brighten(const float& brightness,Image32& outputImage) const { int height = this->height(); int width = this->width(); outputImage.setSize(width, height); for(int y=0; y<height; ++y){ for(int x=0; x<width; ++x){ int r = this->pixel(x,y).r; int g = this->pixel(x,y).g; int b = this->pixel(x,y).b; int rBright = int(r * brightness); int gBright = int(g * brightness); int bBright = int(b * brightness); if(rBright <= 255 && gBright <= 255 && bBright <= 255 ){ outputImage.pixel(x,y).r = rBright; outputImage.pixel(x,y).g = gBright; outputImage.pixel(x,y).b = bBright; outputImage.pixel(x,y).a = this->pixel(x,y).a; } else{ // must clamp if any r,g,b values are over 255 int maxBrightness = 255 / max(r,max(g,b)); outputImage.pixel(x,y).r = int(r * maxBrightness); outputImage.pixel(x,y).g = int(g * maxBrightness); outputImage.pixel(x,y).b = int(b * maxBrightness); outputImage.pixel(x,y).a = this->pixel(x,y).a; } } } return 1; }
int Image32::Quantize(const int& bits,Image32& outputImage) const { int height = this->height(); int width = this->width(); outputImage.setSize(width, height); for(int y=0; y<height; ++y){ for(int x=0; x<width; ++x){ int r = this->pixel(x,y).r; int g = this->pixel(x,y).g; int b = this->pixel(x,y).b; int multiple = int(pow(2,8-bits)); int quanR = r + multiple/2; quanR = min(255, quanR - (quanR % multiple)); // clamped to 255 int quanG = g + multiple/2; quanG = min(255, quanG - (quanG % multiple)); // clamped to 255 int quanB = b + multiple/2; quanB = min(255, quanB - (quanB % multiple)); // clamped to 255 outputImage.pixel(x,y).r = quanR; outputImage.pixel(x,y).g = quanG; outputImage.pixel(x,y).b = quanB; outputImage.pixel(x,y).a = this->pixel(x,y).a; } } return 1; }
int Image32::BeierNeelyMorph(const Image32& source,const Image32& destination,const OrientedLineSegmentPairs& olsp,const float& timeStep,Image32& outputImage) { OrientedLineSegmentPairs olsp1,olsp2; OrientedLineSegment ols; Image32 temp1,temp2; int i; // Generate the in-between line segment pairs if(!olsp1.setCount(olsp.count) || !olsp2.setCount(olsp.count)) { return 0; } for(i=0; i<olsp.count; i++) { olsp1.segments1[i]=olsp.segments1[i]; olsp2.segments1[i]=olsp.segments2[i]; OrientedLineSegment::Blend(olsp.segments1[i],olsp.segments2[i],timeStep,ols); olsp1.segments2[i]=ols; olsp2.segments2[i]=ols; } // Generate the in-between morphs if(!source.Warp(olsp1,temp1) || !destination.Warp(olsp2,temp2)) { return 0; } // Cross-dissolve to get the final image return CrossDissolve(temp1,temp2,timeStep,outputImage); }
int Image32::Warp(const OrientedLineSegmentPairs& olsp,Image32& outputImage) const { int height = this->height(); int width = this->width(); outputImage.setSize(width,height); int numOfLineSegments = olsp.count; float dSumX, dSumY, weight, weightSum; cout << "warp" << "\n"; for(int y=0; y<height; ++y){ for(int x=0; x<width; ++x){ for(int i=0; i<numOfLineSegments; ++i){ dSumX = 0, dSumY = 0, weightSum = 0; weight = olsp.segments2[i].getWeight(x,y); weightSum += weight; float sourceX, sourceY; olsp.segments1[i].GetSourcePosition(olsp.segments1[i], olsp.segments2[i], x, y, sourceX, sourceY); dSumX += (sourceX - x) * weight; dSumY += (sourceY - y) * weight; } outputImage.pixel(x,y).r = this->pixel(x + (dSumX/weightSum), y + (dSumY/weightSum)).r; outputImage.pixel(x,y).g = this->pixel(x + (dSumX/weightSum), y + (dSumY/weightSum)).g; outputImage.pixel(x,y).b = this->pixel(x + (dSumX/weightSum), y + (dSumY/weightSum)).b; } } return 1; }
/** This function is called when the user presses a key. */ void RayWindow::KeyboardFunction( unsigned char c, int x, int y ){ char temp[500]; Image32 img; int z; switch( c ){ case KEY_ESCAPE: exit( 0 ); break; case 'I': printf("Image Name: "); fgets(temp,500,stdin); // gets(temp); TakeSnapshot(img); z = img.WriteImage(temp); printf("Wrote to file: %s\n, %i",temp, z); break; case 'p': fprintf(stderr,"\nPos: (%g,%g,%g)\n Dir: (%g,%g,%g)\n Up: (%g,%g,%g)\n", scene->camera->position[0],scene->camera->position[1],scene->camera->position[2], scene->camera->direction[0],scene->camera->direction[1],scene->camera->direction[2], scene->camera->up[0],scene->camera->up[1],scene->camera->up[2]); break; } }
int Image32::RandomDither(const int& bits,Image32& outputImage) const { float noise = 0.5/pow(2,bits-1); Image32 interImage; this->AddRandomNoise(noise, interImage); interImage.Quantize(bits,outputImage); return 1; }
int Image32::Contrast(const float& contrast,Image32& outputImage) const { int height = this->height(); int width = this->width(); outputImage.setSize(width, height); float totalLum = 0.0; int numPixels = 0; for(int y=0; y<height; ++y){ for(int x=0; x<width; ++x){ int r = this->pixel(x,y).r; int g = this->pixel(x,y).g; int b = this->pixel(x,y).b; float l = 0.30*r + 0.59*g + 0.11*b; totalLum += l; numPixels += 1; } } float meanLum = totalLum / numPixels; for(int y=0; y<height; ++y){ for(int x=0; x<width; ++x){ int r = this->pixel(x,y).r; int g = this->pixel(x,y).g; int b = this->pixel(x,y).b; int a = this->pixel(x,y).a; float l = 0.30*r + 0.59*g + 0.11*b; float lDiff = l - meanLum; float maxContrast; if(lDiff >= 0){ maxContrast = (255 - (max(r,max(g,b)) - lDiff)) / lDiff; } else{ maxContrast = fabs(((min(r,min(g,b))) - lDiff) / lDiff); // lDiff is negative, so adding to minimum of r,g,b } float contrastClamped = min(maxContrast,contrast); outputImage.pixel(x,y).r = contrastClamped*lDiff + (r-lDiff); outputImage.pixel(x,y).g = contrastClamped*lDiff + (g-lDiff); outputImage.pixel(x,y).b = contrastClamped*lDiff + (b-lDiff); outputImage.pixel(x,y).a = a; } } return 1; }
int Image32::RotateGaussian(const float& angle,Image32& outputImage) const { int height = this->height(); int width = this->width(); double rad = -1.0 * angle * (M_PI/180.0); double midHeight = (height/2.0); double midWidth = (width/2.0); double diagonal = sqrt(midHeight*midHeight + midWidth*midWidth); int offset = ceil(diagonal - min(midWidth, midHeight)); Image32 interImage; interImage.setSize(width+(2*offset), height+(2*offset)); outputImage.setSize(width+(2*offset), height+(2*offset)); float variance = 2; float radius = 2; for(int y=0; y < height; ++y){ for(int x=0; x < width; ++x){ int xOffset = x + offset; int yOffset = y + offset; interImage.pixel(xOffset, yOffset).r = this->pixel(x,y).r; interImage.pixel(xOffset, yOffset).g = this->pixel(x,y).g; interImage.pixel(xOffset, yOffset).b = this->pixel(x,y).b; } } for(int y=-1*offset; y < height + offset; ++y){ for(int x=-1*offset; x < width + offset; ++x){ int xOffset = x + offset; int yOffset = y + offset; float u = cos(rad)*(x - midWidth) - sin(rad)*(y - midHeight) + offset + midWidth; float v = sin(rad)*(x - midWidth) + cos(rad)*(y - midHeight) + offset + midHeight; Pixel32 pix = interImage.GaussianSample(u,v, variance, radius); outputImage.pixel(xOffset,yOffset).r = pix.r; outputImage.pixel(xOffset,yOffset).g = pix.g; outputImage.pixel(xOffset,yOffset).b = pix.b; outputImage.pixel(xOffset,yOffset).a = pix.a; // useful for debugging // outputImage.pixel(xOffset,yOffset).r = interImage.pixel(xOffset, yOffset).r; // outputImage.pixel(xOffset,yOffset).g = interImage.pixel(xOffset, yOffset).g; // outputImage.pixel(xOffset,yOffset).b = interImage.pixel(xOffset, yOffset).b; } } return 1; }
/** This function reads the current frame buffer and sets the pixels of the image accordingly. */ int RayWindow::TakeSnapshot(Image32& img){ GLfloat *pixels; int i,j,temp; Pixel p; GLint vp[4]; glGetIntegerv(GL_VIEWPORT,vp); if(!img.setSize(vp[2],vp[3])){return 0;} pixels=new GLfloat[vp[2]*vp[3]*3]; if(!pixels){return 0;} glReadBuffer(GL_FRONT); glReadPixels(vp[0],vp[1],vp[2],vp[3],GL_RGB,GL_FLOAT,pixels); for(i=0;i<vp[3];i++){ for(j=0;j<vp[2];j++){ temp=0+j*3+(vp[3]-i-1)*(vp[2])*3; p.r=255*pixels[temp]; temp=1+j*3+(vp[3]-i-1)*(vp[2])*3; p.g=255*pixels[temp]; temp=2+j*3+(vp[3]-i-1)*(vp[2])*3; p.b=255*pixels[temp]; img(j,i)=p; } } delete[] pixels; return 1; }
int Image32::ScaleBilinear(const float& scaleFactor,Image32& outputImage) const { int widthSRC = this->width(); int heightSRC = this->height(); int widthDST = int(floor(widthSRC * scaleFactor + 0.5)); int heightDST = int(floor(heightSRC * scaleFactor + 0.5)); outputImage.setSize(widthDST, heightDST); for(int yDST=0; yDST<heightDST-(int)scaleFactor; ++yDST){ for(int xDST=0; xDST<widthDST-(int)scaleFactor; ++xDST){ outputImage.pixel(xDST, yDST) = this->BilinearSample(((float)xDST / scaleFactor),((float)yDST / scaleFactor)); } } return 1; }
int Image32::OrderedDither2X2(const int& bits,Image32& outputImage) const { int height = this->height(); int width = this->width(); int i; int j; float D[2][2]; D[0][0] = 1.0; D[0][1] = 3.0; D[1][0] = 4.0; D[1][1] = 2.0; Image32 interImage; interImage.setSize(width,height); float scaler255 = (255.0/pow(2,bits-1)); this->Quantize(bits,interImage); for(int y=0; y<height; ++y){ for (int x = 0; x<width; ++x){ i = x % 2; j = y % 2; float r = float(this->pixel(x,y).r) / 255.0; float g = float(this->pixel(x,y).g) / 255.0; float b = float(this->pixel(x,y).b) / 255.0; float cR = r*pow(2,bits-1); float cG = g*pow(2,bits-1); float cB = b*pow(2,bits-1); float eR = cR - floor(cR); float eG = cG - floor(cG); float eB = cB - floor(cB); if(eR > (D[i][j] / 8)) {outputImage.pixel(x,y).r = int(ceil(cR)*scaler255);} else{outputImage.pixel(x,y).r = int(floor(cR) * scaler255);} if(eG > (D[i][j] / 8)) {outputImage.pixel(x,y).g = int(ceil(cG)*scaler255);} else{outputImage.pixel(x,y).g = int(floor(cG) * scaler255);} if(eB > (D[i][j] / 8)) {outputImage.pixel(x,y).b = int(ceil(cB)*scaler255);} else{outputImage.pixel(x,y).b = int(floor(cB) * scaler255);} outputImage.pixel(x,y).a = this->pixel(x,y).a; } } return 1; }
void Win32CompatibleBitmap::Set(Image32 &image) { ///!!! надо сделать по нормальному, а не через SetPixel !!! clear(); int w = image.width(); int h = image.height(); if (w<=0 && h<=0) return; init(w, h); if (!handle) return; HDC dc = CreateCompatibleDC(0); if (!dc) return; _w = w; _h = h; HGDIOBJ old = ::SelectObject(dc, handle); int i; bool masked = false; for (int y = 0; y<h; y++) { unsigned32 *t = image.line(y); char *m = (masked) ? mask.ptr()+y*w : 0; for (i=0; i<w; i++) { if (t[i] > 0x80000000) { if (!masked) { mask.alloc(w*h); memset(mask.ptr(), 1, w*h); masked = true; m = mask.ptr()+y*w; } m[i] = 0; } ::SetPixel(dc, i, y, t[i]&0xFFFFFF); } } ::SelectObject(dc, old); DeleteDC(dc); }
int main(int argc,char *argv[]) { if(argc < 6) { std::cerr<<"Usage: render XMLfile w s e n [OSMfile]" << std::endl; exit(0); } datasource_cache::instance()->register_datasources ("/usr/local/lib/mapnik/input"); freetype_engine::register_font ("/usr/local/lib/mapnik/fonts/DejaVuSans.ttf"); Map m (800,800); load_map(m,argv[1]); if(argc>6) { parameters p; p["type"] = "osm"; p["file"] = argv[6]; for(int count=0; count<m.layerCount(); count++) { parameters q = m.getLayer(count).datasource()->params(); m.getLayer(count).set_datasource(datasource_cache::instance()-> create(p)); } } Envelope<double> bbox (atof(argv[2]),atof(argv[3]), atof(argv[4]),atof(argv[5])); m.zoomToBox(bbox); Image32 buf (m.getWidth(), m.getHeight()); agg_renderer<Image32> r(m,buf); r.apply(); save_to_file<ImageData32>(buf.data(),"blah.png","png"); return 0; }
int Image32::AddRandomNoise(const float& noise,Image32& outputImage) const { int height = this->height(); int width = this->width(); outputImage.setSize(width, height); int noiseRange = (noise * 256) * 2; for(int y=0; y<height; ++y){ for(int x=0; x<width; ++x){ int randNum; if(noiseRange != 0) randNum = (rand() % noiseRange) - (.5*noiseRange); else{ randNum = 0; } outputImage.pixel(x,y).r = max(0,min(255,randNum + this->pixel(x,y).r)); outputImage.pixel(x,y).g = max(0,min(255,randNum + this->pixel(x,y).g)); outputImage.pixel(x,y).b = max(0,min(255,randNum + this->pixel(x,y).b)); outputImage.pixel(x,y).a = this->pixel(x,y).a; } } return 1; }
int Image32::SetAlpha(const Image32& matte) { int height = this->height(); int width = this->width(); for(int y=0; y<height; ++y){ for(int x=0; x<width; ++x){ this->pixel(x,y).a = matte.pixel(x,y).r; // one channel, all components should be equal } } return 1; }
int Image32::Crop(const int& x1,const int& y1,const int& x2,const int& y2,Image32& outputImage) const { int width = (x2 - x1) + 1; int height = (y2 - y1) + 1; outputImage.setSize(width,height); int i = 0; int j = 0; for(int y=y1; y <= y2; ++y){ i = 0; for(int x=x1; x <= x2; ++x){ outputImage.pixel(i,j).r = this->pixel(x,y).r; outputImage.pixel(i,j).g = this->pixel(x,y).g; outputImage.pixel(i,j).b = this->pixel(x,y).b; outputImage.pixel(i,j).a = this->pixel(x,y).a; i += 1; } j += 1; } return 1; }
int Image32::Saturate(const float& saturation,Image32& outputImage) const { int height = this->height(); int width = this->width(); outputImage.setSize(width, height); for(int y=0; y<height; ++y){ for(int x=0; x<width; ++x){ int r = this->pixel(x,y).r; int g = this->pixel(x,y).g; int b = this->pixel(x,y).b; float l = 0.30*r + 0.59*g + 0.11*b; float rDiff = r-l; float gDiff = g-l; float bDiff = b-l; bool rOverflow = (r-rDiff) + rDiff*saturation > 255 || (r-rDiff) + rDiff*saturation < 0; bool gOverflow = (g-gDiff) + gDiff*saturation > 255 || (g-gDiff) + gDiff*saturation < 0; bool bOverflow = (b-bDiff) + bDiff*saturation > 255 || (b-bDiff) + bDiff*saturation < 0; float satClamped = saturation; // if no overflows, satClamped is saturation if(rOverflow){ // if r overflows, clamp sat to max so r doesn't overflow satClamped = min((r-rDiff), 255-(r-rDiff)) / rDiff; } if(gOverflow){ // if g overflows, clamp sat to max so g doesn't overflow (or satClamped if less) satClamped = min(min((g-gDiff), 255-(g-gDiff)) / gDiff, satClamped); } if(bOverflow){ // if b overflows, clamp sat to max so b doesn't overflow (or satClamped if less) satClamped = min(min((b-bDiff), 255-(b-bDiff)) / bDiff, satClamped); } outputImage.pixel(x,y).r = satClamped*rDiff + (r-rDiff); outputImage.pixel(x,y).g = satClamped*gDiff + (g-gDiff); outputImage.pixel(x,y).b = satClamped*bDiff + (b-bDiff); outputImage.pixel(x,y).a = this->pixel(x,y).a; } } return 1; }
int Image32::ScaleGaussian(const float& scaleFactor,Image32& outputImage) const { int widthSRC = this->width(); int heightSRC = this->height(); int widthDST = int(floor((float)widthSRC * scaleFactor)-ceil(scaleFactor)); int heightDST = int(floor((float)heightSRC * scaleFactor)-ceil(scaleFactor)); outputImage.setSize(widthDST, heightDST); float variance = 1.0 / scaleFactor; float r = 3.0; for(int yDST=0; yDST < heightDST; ++yDST){ for(int xDST=0; xDST < widthDST; ++xDST){ outputImage.pixel(xDST, yDST) = this->GaussianSample(((float)xDST / scaleFactor), ((float)yDST / scaleFactor), variance, r); } } return 1; }
int Image32::Luminance(Image32& outputImage) const { int height = this->height(); int width = this->width(); outputImage.setSize(width, height); for(int y=0; y<height; ++y){ for(int x=0; x<width; ++x){ int r = this->pixel(x,y).r; int g = this->pixel(x,y).g; int b = this->pixel(x,y).b; int l = int(0.30*r + 0.59*g + 0.11*b); outputImage.pixel(x,y).r = l; outputImage.pixel(x,y).g = l; outputImage.pixel(x,y).b = l; outputImage.pixel(x,y).a = this->pixel(x,y).a; } } return 1; }
void image_symbolizer::render(Feature const& feat,CoordTransform const& t,Image32& image) const { geometry_ptr const& geom=feat.get_geometry(); if (geom) { double x; double y; geom->label_position(&x,&y); t.forward_x(&x); t.forward_y(&y); int w=symbol_.width(); int h=symbol_.height(); int px=int(ceil(x - 0.5 * w)); int py=int(ceil(y - 0.5 * h)); image.set_rectangle_alpha(px,py,symbol_); } }
int Image32::Composite(const Image32& overlay,Image32& outputImage) const { int height = this->height(); int width = this->width(); int heightOverlay = overlay.height(); int widthOverlay = overlay.width(); outputImage.setSize(width, height); for(int y=0; y<height; ++y){ for(int x=0; x<width; ++x){ int alpha256 = overlay.pixel(x,y).a; float alpha = (float) alpha256 / 255.0; outputImage.pixel(x,y).r = alpha*(overlay.pixel(x,y).r) + (1.0-alpha)*(this->pixel(x,y).r); outputImage.pixel(x,y).g = alpha*(overlay.pixel(x,y).g) + (1.0-alpha)*(this->pixel(x,y).g); outputImage.pixel(x,y).b = alpha*(overlay.pixel(x,y).b) + (1.0-alpha)*(this->pixel(x,y).b); outputImage.pixel(x,y).a = 255; } } return 1; }
int Image32::CrossDissolve(const Image32& source,const Image32& destination,const float& blendWeight,Image32& outputImage) { int height = destination.height(); int width = destination.width(); cout << "CrossDissolve" << "\n"; for(int y=0; y<height; ++y){ for(int x=0; x<width; ++x){ outputImage.pixel(x,y).r = (blendWeight * source.pixel(x,y).r) + ((1-blendWeight) * destination.pixel(x,y).r); outputImage.pixel(x,y).g = (blendWeight * source.pixel(x,y).g) + ((1-blendWeight) * destination.pixel(x,y).g); outputImage.pixel(x,y).b = (blendWeight * source.pixel(x,y).b) + ((1-blendWeight) * destination.pixel(x,y).b); } } return 1; }
int RayScene::RayTrace(const int& width,const int& height,const int& rLimit,const double& cLimit,Image32& img){ int i,j; Ray3D ray; Point3D c; Pixel32 p; int rayCount=0; if(!img.setSize(width,height)){return 0;} ray.position=camera->position; for(i=0;i<width;i++){ printf(" \r"); printf("%3.1f\r",(float)i/width*100); for(j=0;j<height;j++){ ray=GetRay(camera,i,height-j-1,width,height); c=GetColor(ray,rLimit,Point3D(cLimit,cLimit,cLimit)); p.r=(int)(c[0]*255); p.g=(int)(c[1]*255); p.b=(int)(c[2]*255); img(i,j)=p; } } return 1; }
int Image32::Blur3X3(Image32& outputImage) const { int width = this->width(); int height = this->height(); for(int y=0; y<height; ++y){ for(int x=0; x<width; ++x){ float denominator; bool leftBorder = (x==0); bool rightBorder = (x == width-1); bool bottomBorder = (y == height-1); bool xBorder = leftBorder || rightBorder; bool yBorder = ( y==0 || y == (height-1)); if(xBorder || yBorder){ outputImage.pixel(x,y).r = this->pixel(x,y).r; outputImage.pixel(x,y).g = this->pixel(x,y).g; outputImage.pixel(x,y).b = this->pixel(x,y).b; } else{ denominator = 16; float topR = (this->pixel(x-1,y-1).r + 2*this->pixel(x,y-1).r + this->pixel(x+1,y-1).r) / (denominator); float middleR = (2*this->pixel(x-1,y).r + 4*this->pixel(x,y).r + 2*this->pixel(x+1,y).r) / (denominator); float bottomR = (this->pixel(x-1,y+1).r + 2*this->pixel(x,y+1).r + this->pixel(x+1,y+1).r) / (denominator); outputImage.pixel(x,y).r = topR + middleR + bottomR; float topG = (this->pixel(x-1,y-1).g + 2*this->pixel(x,y-1).g + this->pixel(x+1,y-1).g) / (denominator); float middleG = (2*this->pixel(x-1,y).g + 4*this->pixel(x,y).g + 2*this->pixel(x+1,y).g) / (denominator); float bottomG = (this->pixel(x-1,y+1).g + 2*this->pixel(x,y+1).g + this->pixel(x+1,y+1).g) / (denominator); outputImage.pixel(x,y).g = topG + middleG + bottomG; float topB = (this->pixel(x-1,y-1).b + 2*this->pixel(x,y-1).b + this->pixel(x+1,y-1).b) / (denominator); float middleB = (2*this->pixel(x-1,y).b + 4*this->pixel(x,y).b + 2*this->pixel(x+1,y).b) / (denominator); float bottomB = (this->pixel(x-1,y+1).b + 2*this->pixel(x,y+1).b + this->pixel(x+1,y+1).b) / (denominator); outputImage.pixel(x,y).b = topB + middleB + bottomB; } outputImage.pixel(x,y).a = this->pixel(x,y).a; } } return 1; }
int Image32::FloydSteinbergDither(const int& bits,Image32& outputImage) const { int height = this->height(); int width = this->width(); float alpha = 7/16; float beta = 3/16; float gamma = 5/16; float delta = 1/16; this->Quantize(bits,outputImage); for (int y = 0; y < height; ++y){ for (int x = 0; x < width; ++x){ float eR = this->pixel(x,y).r - outputImage.pixel(x,y).r; float eG = this->pixel(x,y).g - outputImage.pixel(x,y).g; float eB = this->pixel(x,y).b - outputImage.pixel(x,y).b; if(y+1 < height){ outputImage.pixel(x,y+1).r = max(0,min(255,int(outputImage.pixel(x,y+1).r + alpha * eR))); outputImage.pixel(x,y+1).g = max(0,min(255,int(outputImage.pixel(x,y+1).g + alpha * eG))); outputImage.pixel(x,y+1).b = max(0,min(255,int(outputImage.pixel(x,y+1).b + alpha * eB))); } if(x+1 < width && y > 0){ outputImage.pixel(x+1,y-1).r = max(0,min(255,int(outputImage.pixel(x+1,y-1).r + beta * eR))); outputImage.pixel(x+1,y-1).g = max(0,min(255,int(outputImage.pixel(x+1,y-1).g + beta * eG))); outputImage.pixel(x+1,y-1).b = max(0,min(255,int(outputImage.pixel(x+1,y-1).b + beta * eB))); } if(x+1 < width){ outputImage.pixel(x+1,y).r = max(0,min(255,int(outputImage.pixel(x+1,y).r + gamma * eR))); outputImage.pixel(x+1,y).g = max(0,min(255,int(outputImage.pixel(x+1,y).g + gamma * eG))); outputImage.pixel(x+1,y).b = max(0,min(255,int(outputImage.pixel(x+1,y).b + gamma * eB))); } if(x+1 < width && y+1 < height){ outputImage.pixel(x+1,y+1).r = max(0,min(255,int(outputImage.pixel(x+1,y+1).r + delta * eR))); outputImage.pixel(x+1,y+1).g = max(0,min(255,int(outputImage.pixel(x+1,y+1).g + delta * eG))); outputImage.pixel(x+1,y+1).b = max(0,min(255,int(outputImage.pixel(x+1,y+1).b + delta * eB))); } } } return 1; }
void render(geometry_type& geom, Image32& image) const { typedef agg::renderer_base<agg::pixfmt_rgba32> ren_base; agg::row_ptr_cache<agg::int8u> buf(image.raw_data(),image.width(),image.height(), image.width()*4); agg::pixfmt_rgba32 pixf(buf); ren_base renb(pixf); Color const& col = stroke_.get_color(); double r=col.red()/255.0; double g=col.green()/255.0; double b=col.blue()/255.0; if (0) //stroke_.width() == 1.0) { typedef agg::renderer_outline_aa<ren_base> renderer_oaa; typedef agg::rasterizer_outline_aa<renderer_oaa> rasterizer_outline_aa; agg::line_profile_aa prof; prof.width(stroke_.get_width()); renderer_oaa ren_oaa(renb, prof); rasterizer_outline_aa ras_oaa(ren_oaa); ren_oaa.color(agg::rgba(r, g, b, stroke_.get_opacity())); ras_oaa.add_path(geom); //LineRasterizerAA<Image32> rasterizer(image); //rasterizer.render<SHIFT0>(geom,stroke_.get_color()); } else { //typedef agg::renderer_base<agg::pixfmt_rgba32> ren_base; typedef agg::renderer_scanline_aa_solid<ren_base> renderer; renderer ren(renb); agg::rasterizer_scanline_aa<> ras; agg::scanline_u8 sl; if (stroke_.has_dash()) { agg::conv_dash<geometry<vertex2d,vertex_vector> > dash(geom); dash_array const& d = stroke_.get_dash_array(); dash_array::const_iterator itr = d.begin(); dash_array::const_iterator end = d.end(); while (itr != end) { dash.add_dash(itr->first, itr->second); ++itr; } agg::conv_stroke<agg::conv_dash<geometry<vertex2d,vertex_vector> > > stroke(dash); line_join_e join=stroke_.get_line_join(); if ( join == MITER_JOIN) stroke.generator().line_join(agg::miter_join); else if( join == MITER_REVERT_JOIN) stroke.generator().line_join(agg::miter_join); else if( join == ROUND_JOIN) stroke.generator().line_join(agg::round_join); else stroke.generator().line_join(agg::bevel_join); line_cap_e cap=stroke_.get_line_cap(); if (cap == BUTT_CAP) stroke.generator().line_cap(agg::butt_cap); else if (cap == SQUARE_CAP) stroke.generator().line_cap(agg::square_cap); else stroke.generator().line_cap(agg::round_cap); stroke.generator().miter_limit(4.0); stroke.generator().width(stroke_.get_width()); ras.clip_box(0,0,image.width(),image.height()); ras.add_path(stroke); ren.color(agg::rgba(r, g, b, stroke_.get_opacity())); agg::render_scanlines(ras, sl, ren); } else { agg::conv_stroke<geometry<vertex2d,vertex_vector> > stroke(geom); line_join_e join=stroke_.get_line_join(); if ( join == MITER_JOIN) stroke.generator().line_join(agg::miter_join); else if( join == MITER_REVERT_JOIN) stroke.generator().line_join(agg::miter_join); else if( join == ROUND_JOIN) stroke.generator().line_join(agg::round_join); else stroke.generator().line_join(agg::bevel_join); line_cap_e cap=stroke_.get_line_cap(); if (cap == BUTT_CAP) stroke.generator().line_cap(agg::butt_cap); else if (cap == SQUARE_CAP) stroke.generator().line_cap(agg::square_cap); else stroke.generator().line_cap(agg::round_cap); stroke.generator().miter_limit(4.0); stroke.generator().width(stroke_.get_width()); ras.clip_box(0,0,image.width(),image.height()); ras.add_path(stroke); ren.color(agg::rgba(r, g, b, stroke_.get_opacity())); agg::render_scanlines(ras, sl, ren); } } }