void pp::getColors(cinder::Surface& source, Palette& result) { result.clear(); ivec2 v(0, 0); int width = source.getWidth(); int height = source.getHeight(); for (v.x = 0; v.x < width; v.x++) for (v.y = 0; v.y < height; v.y++) { Color8u pxl = source.getPixel(v); bool found = false; for (Palette::iterator it = result.begin(); it != result.end(); it++) if (distance2(Color8u(it->r, it->g, it->b), pxl) == 0) // found found = true; if (!found) result.push_back(pxl); } }
uint64_t IAlgoGen::getFitness(const cinder::Surface& realImage, const cinder::Surface& popImage) const { uint64_t fitness = 0; auto realIter = realImage.getIter(); auto popIter = popImage.getIter(); while (realIter.line() && popIter.line()) { while (realIter.pixel() && popIter.pixel()) { fitness += std::abs(popIter.r() - realIter.r()); fitness += std::abs(popIter.g() - realIter.g()); fitness += std::abs(popIter.b() - realIter.b()); } } return fitness; }
cinder::Surface ColorAlgoGen::crossOver(const cinder::Surface& s1, const cinder::Surface& s2) const { cinder::Surface crossOver = s1.clone(); auto s1Iter = crossOver.getIter(); auto s2Iter = s2.getIter(); while (s1Iter.line() && s2Iter.line()) { while (s1Iter.pixel() && s2Iter.pixel()) { if(RANDOMIZER.nextBool()) { s1Iter.r() = s2Iter.r(); s1Iter.g() = s2Iter.g(); s1Iter.b() = s2Iter.b(); } } } return crossOver; }
cinder::Surface ColorAlgoGen::mutate(const cinder::Surface& s) const { cinder::Surface mutateS = s.clone(); auto mSize = mutateS.getSize(); cinder::Vec2i pixelChoose(RANDOMIZER.nextUint(mSize.x), RANDOMIZER.nextUint(mSize.y)); mutateS.setPixel(pixelChoose, cinder::ColorA8u(static_cast<uint8_t>(RANDOMIZER.nextUint(255)), static_cast<uint8_t>(RANDOMIZER.nextUint(255)), static_cast<uint8_t>(RANDOMIZER.nextUint(255)), 255 )); return mutateS; }
SurfaceImage::SurfaceImage( const cinder::Surface &ciSurface ) : SurfaceBase( ciSurface.getWidth(), ciSurface.getHeight() ) { if( ciSurface.getChannelOrder() == cinder::SurfaceChannelOrder::BGRA ) { mCairoSurface = cairo_image_surface_create_for_data( const_cast<unsigned char*>( ciSurface.getData() ), CAIRO_FORMAT_ARGB32, ciSurface.getWidth(), ciSurface.getHeight(), ciSurface.getRowBytes() ); } else if( ciSurface.getChannelOrder() == cinder::SurfaceChannelOrder::BGRX ) { mCairoSurface = cairo_image_surface_create_for_data( const_cast<unsigned char*>( ciSurface.getData() ), CAIRO_FORMAT_RGB24, ciSurface.getWidth(), ciSurface.getHeight(), ciSurface.getRowBytes() ); } else throw; initCinderSurface( ciSurface.hasAlpha(), cairo_image_surface_get_data( mCairoSurface ), cairo_image_surface_get_stride( mCairoSurface ) ); }
Surface pp::choose(cinder::Surface& imageA, cinder::Surface& imageB, cinder::Surface& errorA, cinder::Surface& secondWeight, float threshold) { // for each target pixel find one in source! float width = std::min(imageA.getWidth(), imageB.getWidth()); float height = std::min(imageB.getHeight(), imageB.getHeight()); Surface result(width, height, false); ivec2 v(0, 0); for (v.y = 0; v.y < height; v.y++) for (v.x = 0; v.x < width; v.x++) { // is errorA a local maximum? bool swap = true; Color8u eA = errorA.getPixel(v); float errA = (eA.r-127)*(eA.r-127) + (eA.g-127)*(eA.g-127) + (eA.b-127)*(eA.b-127); float alternative = secondWeight.getPixel(v).r; if (std::sqrt(errA)*alternative <= threshold*(3*127*127)) swap = false; else for (int i = 0; i < 3 && swap; i++) for (int j = 0; j < 3 && swap; j++) if (i != 1 || j != 1) { ivec2 offset(i-1, j-1); Color8u eO = errorA.getPixel(v+offset); float errOther = (eO.r-127)*(eO.r-127) + (eO.g-127)*(eO.g-127) + (eO.b-127)*(eO.b-127); if (errOther >= errA) swap = false; } if (swap) result.setPixel(v, imageB.getPixel(v)); else result.setPixel(v, imageA.getPixel(v)); } return result; }
SurfaceImage::SurfaceImage( cinder::Surface ciSurface ) : SurfaceBase( ciSurface.getWidth(), ciSurface.getHeight() ) { bool needsManualCopy = true; cairo_format_t format = ( ciSurface.getChannelOrder().hasAlpha() ) ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24; bool legalRowBytes = cairo_format_stride_for_width( format, ciSurface.getWidth() ) == ciSurface.getRowBytes(); if( legalRowBytes && ( ciSurface.getChannelOrder() == cinder::SurfaceChannelOrder::BGRA ) ) { mCairoSurface = cairo_image_surface_create_for_data( const_cast<unsigned char*>( ciSurface.getData() ), CAIRO_FORMAT_ARGB32, ciSurface.getWidth(), ciSurface.getHeight(), ciSurface.getRowBytes() ); needsManualCopy = false; } else if( legalRowBytes && ( ciSurface.getChannelOrder() == cinder::SurfaceChannelOrder::BGRX ) ) { mCairoSurface = cairo_image_surface_create_for_data( const_cast<unsigned char*>( ciSurface.getData() ), CAIRO_FORMAT_RGB24, ciSurface.getWidth(), ciSurface.getHeight(), ciSurface.getRowBytes() ); needsManualCopy = false; } else { // we can't natively represent this Surface configuration, so we'll just allocate one and manually copy it mCairoSurface = cairo_image_surface_create( ciSurface.hasAlpha() ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, ciSurface.getWidth(), ciSurface.getHeight() ); } initCinderSurface( ciSurface.hasAlpha(), cairo_image_surface_get_data( mCairoSurface ), cairo_image_surface_get_stride( mCairoSurface ) ); if( needsManualCopy ) mCinderSurface.copyFrom( ciSurface, ciSurface.getBounds(), Vec2i::zero() ); cairo_surface_mark_dirty( mCairoSurface ); }