void bicriteria_as_coreset( const wplist& src, wplist bic, const csize_t dstsize, wplist& dst) { typedef wplist::const_iterator citer; typedef wplist::iterator iter; bic.resize(dstsize - dst.size()); for (iter it = bic.begin(); it != bic.end(); ++it) { it->weight = 0; } for (iter it = dst.begin(); it != dst.end(); ++it) { pair<int, double> m = min_dist(*it, bic); bic[m.first].weight -= it->weight; } for (citer it = src.begin(); it != src.end(); ++it) { pair<int, double> m = min_dist(*it, bic); bic[m.first].weight += it->weight; } std::copy(bic.begin(), bic.begin()+dstsize-dst.size(), std::back_inserter(dst)); for (iter it = dst.begin(); it != dst.end(); ++it) { if (it->weight < 0) { it->weight = 0; } } }
//returns the line that vector< pair<Line, vector<City> > > determine_closest_lines(vector<Line> &hull_lines, vector<City> &points){ // cout << points.size() << endl; vector<float> min_dist(points.size(), INT_MAX); vector<int> min_lines(points.size()); vector< pair<Line, vector<City> > > line_city_pair; for(int i = 0; i < hull_lines.size(); i++){ pair<Line, vector<City> > temp; temp.first = hull_lines[i]; line_city_pair.push_back(temp); } for(int i = 0; i < hull_lines.size(); i++){ for(int j = 0; j < points.size(); j++){ double dist = hull_lines[i].ltp(points[j]); if(dist < min_dist[j]){ //line_city_pair[i].second.push_back(points[j]); min_lines[j] = i; min_dist[i] = dist; //cout << min_dist[j] << endl; } } } for(int j = 0; j < min_dist.size();j++){ line_city_pair[min_lines[j]].second.push_back(points[j]); } return line_city_pair; }
void kmeans_clustering_method::do_batch_update(wplist& points) { static jubatus::util::math::random::mtrand r; bool terminated = false; if (points.size() < k_) { return; } while (!terminated) { vector<common::sfv_t> kcenters_new(k_); vector<double> center_count(k_, 0); for (wplist::iterator it = points.begin(); it != points.end(); ++it) { pair<int64_t, double> m = min_dist((*it).data, kcenters_); scalar_mul_and_add(it->data, it->weight, kcenters_new[m.first]); center_count[m.first] += it->weight; } terminated = true; for (size_t i = 0; i < k_; ++i) { if (center_count[i] == 0) { kcenters_new[i] = kcenters_[i]; continue; } kcenters_new[i] = scalar_dot(kcenters_new[i], 1.0 / center_count[i]); double d = dist(kcenters_new[i], kcenters_[i]); if (d > 1e-9) { terminated = false; } } kcenters_ = kcenters_new; } }
void generate_colors(int static_component,double dist_treshold){ yuv c; double dist; randomize_yuv(-1,&c); for(int i=0;i<num_colors;i++){ // attempt to create a specific contrast between the colors not sure how well it works if(!i ){ randomize_yuv(static_component,&c); }else{ randomize_yuv(static_component,&c); int cnt=0; while(dist_treshold > (dist=min_dist(c,i))){ assert(++cnt < STUCK_TRESHOLD); randomize_yuv(static_component,&c); } } yuv_colors[i].y=c.y; yuv_colors[i].u=c.u; yuv_colors[i].v=c.v; } // convert the colors to rgb for(int i=0;i<num_colors;i++){ yuv2rgb(&colors[i],yuv_colors[i]); } }
int64_t kmeans_clustering_method::get_nearest_center_index( const common::sfv_t& point) const { if (kcenters_.empty()) { throw JUBATUS_EXCEPTION(not_performed()); } return min_dist(point, kcenters_).first; }
vector<wplist> kmeans_clustering_method::get_clusters( const wplist& points) const { vector<wplist> ret(k_); for (wplist::const_iterator it = points.begin(); it != points.end(); ++it) { pair<int64_t, double> m = min_dist(it->data, kcenters_); ret[m.first].push_back(*it); } return ret; }
int64_t kmeans_clustering_method::get_nearest_center_index( const common::sfv_t& point) const { if (kcenters_.empty()) { throw JUBATUS_EXCEPTION(common::exception::runtime_error( "clustering is not performed yet")); } return min_dist(point, kcenters_).first; }
vector<wplist> kmeans_clustering_method::get_clusters( const wplist& points) const { if (kcenters_.empty()) { throw JUBATUS_EXCEPTION(not_performed()); } vector<wplist> ret(k_); for (wplist::const_iterator it = points.begin(); it != points.end(); ++it) { pair<int64_t, double> m = min_dist(it->data, kcenters_); ret[m.first].push_back(*it); } return ret; }
void kmeans_clustering_method::initialize_centers(wplist& points) { if (points.size() < k_) { return; } kcenters_.clear(); kcenters_.push_back(points[0].data); vector<double> weights; while (kcenters_.size() < k_) { weights.clear(); for (wplist::iterator it = points.begin(); it != points.end(); ++it) { pair<int64_t, double> m = min_dist((*it).data, kcenters_); weights.push_back(m.second * it->weight); } discrete_distribution d(weights.begin(), weights.end()); kcenters_.push_back(points[d()].data); } }
void kmeans_compressor::bicriteria_to_coreset( wplist& src, wplist& bicriteria, csize_t dstsize, wplist& dst) { if (bicriteria.size() == 0) { dst = src; return; } double weight_sum = 0; double squared_min_dist_sum = 0; for (wplist::iterator it = src.begin(); it != src.end(); ++it) { std::pair<int, double> m = min_dist(*it, bicriteria); (*it).free_long = m.first; (*it).free_double = m.second; bicriteria.at((*it).free_long).free_double += (*it).weight; squared_min_dist_sum += pow((*it).free_double, 2) * (*it).weight; weight_sum += (*it).weight; } std::vector<double> weights; double sumw = 0; double prob = 0; for (wplist::iterator it = src.begin(); it != src.end(); ++it) { weighted_point p = *it; weighted_point bp = bicriteria.at(p.free_long); prob = get_probability(p, bp, weight_sum, squared_min_dist_sum); (*it).free_double = prob; weights.push_back(prob); sumw += prob; } discrete_distribution d(weights.begin(), weights.end()); std::vector<size_t> ind(dstsize); std::generate(ind.begin(), ind.end(), d); for (std::vector<size_t>::iterator it = ind.begin(); it != ind.end(); ++it) { weighted_point sample = src.at(*it); sample.weight = 1.0 / dstsize * sumw / sample.free_double * sample.weight; sample.free_double = 0; sample.free_long = 0; dst.push_back(sample); } }
void kmeans_compressor::get_bicriteria( const wplist& src, csize_t bsize, csize_t dstsize, wplist& dst) { timer_start(); dst.clear(); wplist resid = src; vector<double> weights(src.size()); double r = (1 - exp(bsize*(log(bsize)-log(src.size()))/dstsize)) / 2; r = max(0.1, r); std::vector<size_t> ind(bsize); while (resid.size() > 1 && dst.size() < dstsize) { timer_start(); weights.resize(resid.size()); for (wplist::iterator it = resid.begin(); it != resid.end(); ++it) { weights[it - resid.begin()] = it->weight; } discrete_distribution d(weights.begin(), weights.end()); std::generate(ind.begin(), ind.end(), d); std::sort(ind.begin(), ind.end()); std::vector<size_t>::iterator it = std::unique(ind.begin(), ind.end()); ind.erase(it, ind.end()); for (it = ind.begin(); it != ind.end(); ++it) { weighted_point p = resid[*it]; p.free_long = 0; dst.push_back(p); } for (wplist::iterator itr = resid.begin(); itr != resid.end(); ++itr) { (*itr).free_double = min_dist(*itr, dst).second; } std::sort(resid.begin(), resid.end(), compare_weight); csize_t size = (csize_t)std::min(static_cast<double>(resid.size()), static_cast<double>(resid.size()*r)); if (size == 0) { size = 1; } resid.resize(size); } }
int64_t kmeans_clustering_method::get_nearest_center_index( const common::sfv_t& point) const { return min_dist(point, kcenters_).first; }
void ElutionPeakDetection::findLocalExtrema(const MassTrace& tr, const Size & num_neighboring_peaks, std::vector<Size> & chrom_maxes, std::vector<Size> & chrom_mins) { std::vector<DoubleReal> smoothed_ints_vec(tr.getSmoothedIntensities()); Size mt_length(smoothed_ints_vec.size()); if (mt_length != tr.getSize()) { throw Exception::InvalidValue(__FILE__, __LINE__, __PRETTY_FUNCTION__, "MassTrace was not smoothed before! Aborting...", String(smoothed_ints_vec.size())); } // first make sure that everything is cleared chrom_maxes.clear(); chrom_mins.clear(); // Extract RTs from the chromatogram and store them into into vectors for index access // std::cout << "neighboring peaks: " << num_neighboring_peaks << std::endl; // Store indices along with smoothed_ints to keep track of the peak order std::multimap<DoubleReal, Size> intensity_indices; boost::dynamic_bitset<> used_idx(mt_length); for (Size i = 0; i < mt_length; ++i) { intensity_indices.insert(std::make_pair(smoothed_ints_vec[i], i)); } for (std::multimap<DoubleReal, Size>::const_iterator c_it = intensity_indices.begin(); c_it != intensity_indices.end(); ++c_it) { DoubleReal ref_int = c_it->first; Size ref_idx = c_it->second; if (!(used_idx[ref_idx]) && ref_int > 0.0) { bool real_max = true; // iterate up the RT Size start_idx(0); if (ref_idx > num_neighboring_peaks) { start_idx = ref_idx - num_neighboring_peaks; } Size end_idx = ref_idx + num_neighboring_peaks; if (end_idx > mt_length) { end_idx = mt_length; } for (Size j = start_idx; j < end_idx; ++j) { if (used_idx[j]) { real_max = false; break; } if (j == ref_idx) { continue; } if (smoothed_ints_vec[j] > ref_int) { real_max = false; } } if (real_max) { chrom_maxes.push_back(ref_idx); for (Size j = start_idx; j < end_idx; ++j) { used_idx[j] = true; } } } } std::sort(chrom_maxes.begin(), chrom_maxes.end()); if (chrom_maxes.size() > 1) { Size i(0), j(1); //for (Size i = 0; i < chrom_maxes.size() - 1; ++i) while (i < j && j < chrom_maxes.size()) { // bisection Size left_bound(chrom_maxes[i] + 1); Size right_bound(chrom_maxes[j] - 1); while ((left_bound + 1) < right_bound) { DoubleReal mid_dist((right_bound - left_bound) / 2.0); Size mid_element_idx(left_bound + std::floor(mid_dist)); DoubleReal mid_element_int = smoothed_ints_vec[mid_element_idx]; if (mid_element_int <= smoothed_ints_vec[mid_element_idx + 1]) { right_bound = mid_element_idx; } else // or to the right... { left_bound = mid_element_idx; } } Size min_rt((smoothed_ints_vec[left_bound] < smoothed_ints_vec[right_bound]) ? left_bound : right_bound); // check for valley depth between chromatographic peaks DoubleReal min_int(1.0); if (smoothed_ints_vec[min_rt] > min_int) { min_int = smoothed_ints_vec[min_rt]; } DoubleReal left_max_int(smoothed_ints_vec[chrom_maxes[i]]); DoubleReal right_max_int(smoothed_ints_vec[chrom_maxes[j]]); DoubleReal left_rt(tr[chrom_maxes[i]].getRT()); DoubleReal mid_rt(tr[min_rt].getRT()); DoubleReal right_rt(tr[chrom_maxes[j]].getRT()); DoubleReal left_dist(std::fabs(mid_rt - left_rt)); DoubleReal right_dist(std::fabs(right_rt - mid_rt)); DoubleReal min_dist(min_fwhm_ / 2.0); // out debug info // std::cout << tr.getLabel() << ": i,j " << i << "," << j << ":" << left_max_int << " min: " << min_int << " " << right_max_int << " l " << left_rt << " r " << right_rt << " m " << mid_rt << std::endl; if (left_max_int / min_int >= 2.0 && right_max_int / min_int >= 2.0 && left_dist >= min_dist && right_dist >= min_dist) { chrom_mins.push_back(min_rt); // std::cout << "min added!" << std::endl; i = j; ++j; } else { // keep one of the chrom_maxes, iterate the other if (left_max_int > right_max_int) { ++j; } else { i = j; ++j; } } // chrom_mins.push_back(min_rt); } } return; }
bool CurveWarp::accelerated_cairorender(Context context, cairo_t *cr, int quality, const RendDesc &renddesc_, ProgressCallback *cb)const { Point start_point=param_start_point.get(Point()); Point end_point=param_end_point.get(Point()); SuperCallback stageone(cb,0,9000,10000); SuperCallback stagetwo(cb,9000,10000,10000); RendDesc renddesc(renddesc_); // Untransform the render desc if(!cairo_renddesc_untransform(cr, renddesc)) return false; int x,y; const Real pw(renddesc.get_pw()),ph(renddesc.get_ph()); Point tl(renddesc.get_tl()); Point br(renddesc.get_br()); const int w(renddesc.get_w()); const int h(renddesc.get_h()); // find a bounding rectangle for the context we need to render // todo: find a better way of doing this - this way doesn't work Rect src_rect(transform(tl)); Point pos1, pos2; Real dist, along; Real min_dist(999999), max_dist(-999999), min_along(999999), max_along(-999999); #define UPDATE_DIST \ if (dist < min_dist) min_dist = dist; \ if (dist > max_dist) max_dist = dist; \ if (along < min_along) min_along = along; \ if (along > max_along) max_along = along // look along the top and bottom edges pos1[0] = pos2[0] = tl[0]; pos1[1] = tl[1]; pos2[1] = br[1]; for (x = 0; x < w; x++, pos1[0] += pw, pos2[0] += pw) { src_rect.expand(transform(pos1, &dist, &along)); UPDATE_DIST; src_rect.expand(transform(pos2, &dist, &along)); UPDATE_DIST; } // look along the left and right edges pos1[0] = tl[0]; pos2[0] = br[0]; pos1[1] = pos2[1] = tl[1]; for (y = 0; y < h; y++, pos1[1] += ph, pos2[1] += ph) { src_rect.expand(transform(pos1, &dist, &along)); UPDATE_DIST; src_rect.expand(transform(pos2, &dist, &along)); UPDATE_DIST; } // look along the diagonals const int max_wh(std::max(w,h)); const Real inc_x((br[0]-tl[0])/max_wh),inc_y((br[1]-tl[1])/max_wh); pos1[0] = pos2[0] = tl[0]; pos1[1] = tl[1]; pos2[1] = br[1]; for (x = 0; x < max_wh; x++, pos1[0] += inc_x, pos2[0] = pos1[0], pos1[1]+=inc_y, pos2[1]-=inc_y) { src_rect.expand(transform(pos1, &dist, &along)); UPDATE_DIST; src_rect.expand(transform(pos2, &dist, &along)); UPDATE_DIST; } #if 0 // look at each blinepoint std::vector<synfig::BLinePoint>::const_iterator iter; for (iter=bline.begin(); iter!=bline.end(); iter++) src_rect.expand(transform(iter->get_vertex()+origin, &dist, &along)); UPDATE_DIST; #endif Point src_tl(src_rect.get_min()); Point src_br(src_rect.get_max()); Vector ab((end_point - start_point).norm()); Angle::tan ab_angle(ab[1], ab[0]); Real used_length = max_along - min_along; Real render_width = max_dist - min_dist; int src_w = (abs(used_length*Angle::cos(ab_angle).get()) + abs(render_width*Angle::sin(ab_angle).get())) / abs(pw); int src_h = (abs(used_length*Angle::sin(ab_angle).get()) + abs(render_width*Angle::cos(ab_angle).get())) / abs(ph); Real src_pw((src_br[0] - src_tl[0]) / src_w); Real src_ph((src_br[1] - src_tl[1]) / src_h); if (src_pw > abs(pw)) { src_w = int((src_br[0] - src_tl[0]) / abs(pw)); src_pw = (src_br[0] - src_tl[0]) / src_w; } if (src_ph > abs(ph)) { src_h = int((src_br[1] - src_tl[1]) / abs(ph)); src_ph = (src_br[1] - src_tl[1]) / src_h; } #define MAXPIX 10000 if (src_w > MAXPIX) src_w = MAXPIX; if (src_h > MAXPIX) src_h = MAXPIX; // this is an attempt to remove artifacts around tile edges - the // cubic interpolation uses at most 2 pixels either side of the // target pixel, so add an extra 2 pixels around the tile on all // sides src_tl -= (Point(src_pw,src_ph)*2); src_br += (Point(src_pw,src_ph)*2); src_w += 4; src_h += 4; src_pw = (src_br[0] - src_tl[0]) / src_w; src_ph = (src_br[1] - src_tl[1]) / src_h; // set up a renddesc for the context to render RendDesc src_desc(renddesc); //src_desc.clear_flags(); src_desc.set_tl(src_tl); src_desc.set_br(src_br); src_desc.set_wh(src_w, src_h); // New expanded renddesc values const double wpw=src_desc.get_pw(); const double wph=src_desc.get_ph(); const double wtlx=src_desc.get_tl()[0]; const double wtly=src_desc.get_tl()[1]; // render the context onto a new surface cairo_surface_t* csource, *cresult; csource=cairo_surface_create_similar(cairo_get_target(cr),CAIRO_CONTENT_COLOR_ALPHA, src_w, src_h); cresult=cairo_surface_create_similar(cairo_get_target(cr),CAIRO_CONTENT_COLOR_ALPHA, w, h); cairo_t *subcr=cairo_create(csource); cairo_scale(subcr, 1/wpw, 1/wph); cairo_translate(subcr, -wtlx, -wtly); if(!context.accelerated_cairorender(subcr,quality,src_desc,&stageone)) return false; // don't needed anymore cairo_destroy(subcr); //access to pixels CairoSurface source(csource); source.map_cairo_image(); CairoSurface result(cresult); result.map_cairo_image(); float u,v; Point pos, tmp; if(quality<=4) // CUBIC for(y=0,pos[1]=tl[1];y<h;y++,pos[1]+=ph) { for(x=0,pos[0]=tl[0];x<w;x++,pos[0]+=pw) { tmp=transform(pos); u=(tmp[0]-src_tl[0])/src_pw; v=(tmp[1]-src_tl[1])/src_ph; if(u<0 || v<0 || u>=src_w || v>=src_h || isnan(u) || isnan(v)) result[y][x]=CairoColor(context.get_color(tmp)).premult_alpha(); else result[y][x]=source.cubic_sample_cooked(u,v); } if((y&31)==0 && cb && !stagetwo.amount_complete(y,h)) return false; } else if (quality<=6) // INTERPOLATION_LINEAR for(y=0,pos[1]=tl[1];y<h;y++,pos[1]+=ph) { for(x=0,pos[0]=tl[0];x<w;x++,pos[0]+=pw) { tmp=transform(pos); u=(tmp[0]-src_tl[0])/src_pw; v=(tmp[1]-src_tl[1])/src_ph; if(u<0 || v<0 || u>=src_w || v>=src_h || isnan(u) || isnan(v)) result[y][x]=CairoColor(context.get_color(tmp)).premult_alpha(); else result[y][x]=source.linear_sample_cooked(u,v); } if((y&31)==0 && cb && !stagetwo.amount_complete(y,h)) return false; } else // NEAREST_NEIGHBOR for(y=0,pos[1]=tl[1];y<h;y++,pos[1]+=ph) { for(x=0,pos[0]=tl[0];x<w;x++,pos[0]+=pw) { tmp=transform(pos); u=(tmp[0]-src_tl[0])/src_pw; v=(tmp[1]-src_tl[1])/src_ph; if(u<0 || v<0 || u>=src_w || v>=src_h || isnan(u) || isnan(v)) result[y][x]=CairoColor(context.get_color(tmp)).premult_alpha(); else result[y][x]=source[floor_to_int(v)][floor_to_int(u)]; } if((y&31)==0 && cb && !stagetwo.amount_complete(y,h)) return false; } result.unmap_cairo_image(); source.unmap_cairo_image(); cairo_surface_destroy(csource); // Now paint it on the context cairo_save(cr); cairo_translate(cr, tl[0], tl[1]); cairo_scale(cr, pw, ph); cairo_set_source_surface(cr, cresult, 0, 0); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_paint(cr); cairo_restore(cr); cairo_surface_destroy(cresult); // Mark our progress as finished if(cb && !cb->amount_complete(10000,10000)) return false; return true; }
bool CurveWarp::accelerated_render(Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const { Point start_point=param_start_point.get(Point()); Point end_point=param_end_point.get(Point()); SuperCallback stageone(cb,0,9000,10000); SuperCallback stagetwo(cb,9000,10000,10000); int x,y; const Real pw(renddesc.get_pw()),ph(renddesc.get_ph()); Point tl(renddesc.get_tl()); Point br(renddesc.get_br()); const int w(renddesc.get_w()); const int h(renddesc.get_h()); // find a bounding rectangle for the context we need to render // todo: find a better way of doing this - this way doesn't work Rect src_rect(transform(tl)); Point pos1, pos2; Real dist, along; Real min_dist(999999), max_dist(-999999), min_along(999999), max_along(-999999); #define UPDATE_DIST \ if (dist < min_dist) min_dist = dist; \ if (dist > max_dist) max_dist = dist; \ if (along < min_along) min_along = along; \ if (along > max_along) max_along = along // look along the top and bottom edges pos1[0] = pos2[0] = tl[0]; pos1[1] = tl[1]; pos2[1] = br[1]; for (x = 0; x < w; x++, pos1[0] += pw, pos2[0] += pw) { src_rect.expand(transform(pos1, &dist, &along)); UPDATE_DIST; src_rect.expand(transform(pos2, &dist, &along)); UPDATE_DIST; } // look along the left and right edges pos1[0] = tl[0]; pos2[0] = br[0]; pos1[1] = pos2[1] = tl[1]; for (y = 0; y < h; y++, pos1[1] += ph, pos2[1] += ph) { src_rect.expand(transform(pos1, &dist, &along)); UPDATE_DIST; src_rect.expand(transform(pos2, &dist, &along)); UPDATE_DIST; } // look along the diagonals const int max_wh(std::max(w,h)); const Real inc_x((br[0]-tl[0])/max_wh),inc_y((br[1]-tl[1])/max_wh); pos1[0] = pos2[0] = tl[0]; pos1[1] = tl[1]; pos2[1] = br[1]; for (x = 0; x < max_wh; x++, pos1[0] += inc_x, pos2[0] = pos1[0], pos1[1]+=inc_y, pos2[1]-=inc_y) { src_rect.expand(transform(pos1, &dist, &along)); UPDATE_DIST; src_rect.expand(transform(pos2, &dist, &along)); UPDATE_DIST; } #if 0 // look at each blinepoint std::vector<synfig::BLinePoint>::const_iterator iter; for (iter=bline.begin(); iter!=bline.end(); iter++) src_rect.expand(transform(iter->get_vertex()+origin, &dist, &along)); UPDATE_DIST; #endif Point src_tl(src_rect.get_min()); Point src_br(src_rect.get_max()); Vector ab((end_point - start_point).norm()); Angle::tan ab_angle(ab[1], ab[0]); Real used_length = max_along - min_along; Real render_width = max_dist - min_dist; int src_w = (abs(used_length*Angle::cos(ab_angle).get()) + abs(render_width*Angle::sin(ab_angle).get())) / abs(pw); int src_h = (abs(used_length*Angle::sin(ab_angle).get()) + abs(render_width*Angle::cos(ab_angle).get())) / abs(ph); Real src_pw((src_br[0] - src_tl[0]) / src_w); Real src_ph((src_br[1] - src_tl[1]) / src_h); if (src_pw > abs(pw)) { src_w = int((src_br[0] - src_tl[0]) / abs(pw)); src_pw = (src_br[0] - src_tl[0]) / src_w; } if (src_ph > abs(ph)) { src_h = int((src_br[1] - src_tl[1]) / abs(ph)); src_ph = (src_br[1] - src_tl[1]) / src_h; } #define MAXPIX 10000 if (src_w > MAXPIX) src_w = MAXPIX; if (src_h > MAXPIX) src_h = MAXPIX; // this is an attempt to remove artifacts around tile edges - the // cubic interpolation uses at most 2 pixels either side of the // target pixel, so add an extra 2 pixels around the tile on all // sides src_tl -= (Point(src_pw,src_ph)*2); src_br += (Point(src_pw,src_ph)*2); src_w += 4; src_h += 4; src_pw = (src_br[0] - src_tl[0]) / src_w; src_ph = (src_br[1] - src_tl[1]) / src_h; // set up a renddesc for the context to render RendDesc src_desc(renddesc); src_desc.clear_flags(); src_desc.set_tl(src_tl); src_desc.set_br(src_br); src_desc.set_wh(src_w, src_h); // render the context onto a new surface Surface source; source.set_wh(src_w,src_h); if(!context.accelerated_render(&source,quality,src_desc,&stageone)) return false; float u,v; Point pos, tmp; surface->set_wh(w,h); surface->clear(); if(quality<=4) // CUBIC for(y=0,pos[1]=tl[1];y<h;y++,pos[1]+=ph) { for(x=0,pos[0]=tl[0];x<w;x++,pos[0]+=pw) { tmp=transform(pos); u=(tmp[0]-src_tl[0])/src_pw; v=(tmp[1]-src_tl[1])/src_ph; if(u<0 || v<0 || u>=src_w || v>=src_h || isnan(u) || isnan(v)) (*surface)[y][x]=context.get_color(tmp); else (*surface)[y][x]=source.cubic_sample(u,v); } if((y&31)==0 && cb && !stagetwo.amount_complete(y,h)) return false; } else if (quality<=6) // INTERPOLATION_LINEAR for(y=0,pos[1]=tl[1];y<h;y++,pos[1]+=ph) { for(x=0,pos[0]=tl[0];x<w;x++,pos[0]+=pw) { tmp=transform(pos); u=(tmp[0]-src_tl[0])/src_pw; v=(tmp[1]-src_tl[1])/src_ph; if(u<0 || v<0 || u>=src_w || v>=src_h || isnan(u) || isnan(v)) (*surface)[y][x]=context.get_color(tmp); else (*surface)[y][x]=source.linear_sample(u,v); } if((y&31)==0 && cb && !stagetwo.amount_complete(y,h)) return false; } else // NEAREST_NEIGHBOR for(y=0,pos[1]=tl[1];y<h;y++,pos[1]+=ph) { for(x=0,pos[0]=tl[0];x<w;x++,pos[0]+=pw) { tmp=transform(pos); u=(tmp[0]-src_tl[0])/src_pw; v=(tmp[1]-src_tl[1])/src_ph; if(u<0 || v<0 || u>=src_w || v>=src_h || isnan(u) || isnan(v)) (*surface)[y][x]=context.get_color(tmp); else (*surface)[y][x]=source[floor_to_int(v)][floor_to_int(u)]; } if((y&31)==0 && cb && !stagetwo.amount_complete(y,h)) return false; } // Mark our progress as finished if(cb && !cb->amount_complete(10000,10000)) return false; return true; }