/*virtual*/ void DeepTransform::sample (int outX, int outY, const DeepTile& deep_in_tile, Dcx::DeepPixel& out_pixel) { out_pixel.clear(); // No filtering, find nearest input pixel and copy it: if (m_filter_mode == FILTER_NEAREST) { // Back project center of pixel: float finX, finY; backTransform(float(outX)+0.5f, float(outY)+0.5f, finX, finY, 0/*clamp_to*/); const int inX = int(floorf(finX)+0.01f); const int inY = int(floorf(finY)+0.01f); if (inX < deep_in_tile.x() || inX > deep_in_tile.r() || inY < deep_in_tile.y() || inY > deep_in_tile.t()) return; // Skip if projected outside input bbox deep_in_tile.getDeepPixel(inX, inY, out_pixel); return; } // Back-project output pixel corners into input tile. // backTransform expects an inclusive bbox, so we don't add one to r/t here: const IMATH_NAMESPACE::Box2i in = backTransform(IMATH_NAMESPACE::Box2i(IMATH_NAMESPACE::V2i(outX, outY), IMATH_NAMESPACE::V2i(outX, outY)), 0/*clamp_to*/); #ifdef DCX_DEBUG_TRANSFORM if (debug) { std::cout << "----------------------------------------------------------------------------------" << std::endl; std::cout << "DeepTransform::sample(" << outX << ", " << outY << ") yUp=" << deep_in_tile.tileYup(); // std::cout << ", dataWindow" << deep_in_tile.dataWindow() << std::endl; //std::cout << " transform:" << std::endl << std::fixed << imatrix(); // std::cout << " sample input rectangle=" << in; std::cout << " [" << (in.max.x - in.min.x + 1) << " " << (in.max.y - in.min.y + 1) << "]"; } #endif // Bail if it transformed outside input bbox: if (in.min.x < deep_in_tile.x() || in.max.x > deep_in_tile.r() || in.min.y < deep_in_tile.y() || in.max.y > deep_in_tile.t()) #ifdef DCX_DEBUG_TRANSFORM { if (debug) std::cout << "...sample rectangle outside input tile bbox, bail." << std::endl; return; } #else return; #endif Dcx::DeepPixel in_pixel(deep_in_tile.channels()); //============================================================= // Partial-transparency filtering //============================================================= const int ss_factor = std::min(std::max(m_ss_factor, 1), SSAMPLING_MAX); const int ss_factor_sqr = ss_factor*ss_factor; const int superW = (int)SpMask8::width*ss_factor; // 32 const float ifsuperW = 1.0f/float(superW); const float ss_factor_center = 0.5f/float(superW); const float fmaskW = float(SpMask8::width); const float foutX = float(outX); const float foutY = float(outY); float finX, finY; #ifdef DCX_DEBUG_TRANSFORM if (debug) std::cout << ", ss_factor=" << ss_factor << ", ss_factor_sqr=" << ss_factor_sqr << std::endl; #endif char bin_hits[SpMask8::numBits]; std::vector<char> ss_weight_counts(ss_factor_sqr); //char ss_weight_counts[ss_factor_sqr]; std::vector<SpMask8> ss_weight_masks(ss_factor_sqr); //SpMask8 ss_weight_masks[ss_factor_sqr]; SpMask8 out_mask, out_opaque_mask, out_transp_mask; // Iterate through input pixel range, finding segments that contribute to the output pixel, // and resampling the masks: for (int tY=in.min.y; tY <= in.max.y; ++tY) { for (int tX=in.min.x; tX <= in.max.x; ++tX) { // Get the deep pixel from the deep tile: deep_in_tile.getDeepPixel(tX, tY, in_pixel); const size_t nSegments = in_pixel.size(); #ifdef DCX_DEBUG_TRANSFORM if (debug) { std::cout << " --------------------------------------------------------------------" << std::endl; std::cout << " in[" << tX << " " << tY << "] segments=" << nSegments << std::endl; } #endif if (nSegments == 0) continue; assert(nSegments < 10000); // just in case... // There's input subpixel masks, so resample them: for (size_t segment=0; segment < nSegments; ++segment) { // Get input segment: const DeepSegment& in_segment = in_pixel.getSegment(segment); const SpMask8 in_mask = (!in_segment.zeroCoverage())?in_segment.spMask():SpMask8::fullCoverage; #ifdef DCX_DEBUG_TRANSFORM if (debug) { std::cout << " -----------------------------" << std::endl; std::cout << " " << segment << " Zf=" << in_segment.Zf << ", Zb=" << in_segment.Zb << std::endl; std::cout << " mask:" << std::endl; in_mask.printPattern(std::cout, " "); } #endif out_mask = out_opaque_mask = SpMask8::zeroCoverage; memset(bin_hits, 0, SpMask8::numBits); // Sample subpixel locations at a potentially higher rate and stochastically(TODO) // than 8x8, building up the bin-hit counts and accumulated masks: for (int spSupOutY=(superW-1); spSupOutY >= 0; --spSupOutY) { #ifdef DCX_DEBUG_TRANSFORM if (debug) std::cout << " "; #endif const int spOutY = spSupOutY / ss_factor; for (int spSupOutX=0; spSupOutX < superW; ++spSupOutX) { const int spOutX = spSupOutX / ss_factor; // Back-project input subpixel coordinate into output space: // (TODO: can this be a dPdx/dpDy interpolation routine instead?) // (TODO: jitter this stochastically too!) backTransform(foutX + ss_factor_center + float(spSupOutX)*ifsuperW, foutY + ss_factor_center + float(spSupOutY)*ifsuperW, finX, finY); const float flr_inX = floorf(finX); const float flr_inY = floorf(finY); const int inX = int(flr_inX); const int inY = int(flr_inY); // Skip if it projects outside the current output pixel: if (inX != tX || inY != tY) #ifdef DCX_DEBUG_TRANSFORM { if (debug) std::cout << " [ ] "; continue; } #else continue; #endif // Sample location in input spmask: const int spInX = int(floorf((finX - flr_inX)*fmaskW)); const int spInY = int(floorf((finY - flr_inY)*fmaskW)); #ifdef DCX_DEBUG_TRANSFORM if (debug) std::cout << " [" << spInX << " " << spInY << "]"; #endif // Get input spmask bit: const SpMask8 in_sp = SpMask8(1ull) << (spInY*SpMask8::width + spInX); if (in_mask & in_sp) { // Increment hit-count for this output bin: const int out_bin = spOutY*SpMask8::width + spOutX; assert(out_bin < (int)SpMask8::numBits); const SpMask8 out_sp = SpMask8(1ull) << out_bin; out_mask |= out_sp; ++bin_hits[out_bin]; if (bin_hits[out_bin] >= ss_factor_sqr) out_opaque_mask |= out_sp; #ifdef DCX_DEBUG_TRANSFORM if (debug) std::cout << "=" << std::dec << (int)bin_hits[out_bin]; #endif } #ifdef DCX_DEBUG_TRANSFORM else { if (debug) std::cout << " "; } #endif } // spInX loop #ifdef DCX_DEBUG_TRANSFORM if (debug) std::cout << std::endl; #endif } // spInY loop // Skip this segment if it doesn't overlap any output bins: if (out_mask == SpMask8::zeroCoverage) #ifdef DCX_DEBUG_TRANSFORM { if (debug) std::cout << " no output overlap, skip segment " << segment << std::endl; continue; } #else continue; #endif // Write the opaque sample if the mask is non-zero: if (out_opaque_mask != SpMask8::zeroCoverage) { DeepSegment& out_segment = out_pixel.getSegment(out_pixel.append(in_pixel, segment)); // Update output metadata: out_segment.metadata.spmask = out_opaque_mask; out_segment.metadata.flags &= ~DEEP_PARTIAL_BIN_COVERAGE; } // Write partially-transparent segment if segment is included in accumulated transp mask: // The transparent mask is the bins that are on but not opaque: out_transp_mask = (out_mask & ~out_opaque_mask); #if 0//def DCX_DEBUG_TRANSFORM if (debug) { std::cout << " out_mask" << std::endl; out_mask.printPattern(std::cout, " "); std::cout << " out_opaque_mask" << std::endl; out_opaque_mask.printPattern(std::cout, " "); std::cout << " out_transp_mask" << std::endl; out_transp_mask.printPattern(std::cout, " "); } #endif if (out_transp_mask != SpMask8::zeroCoverage) { // Determine weights for each bin, then output the dominant weight, or // separate segments with the separate weights separated by subpixel bits: memset(&ss_weight_counts[0], 0, ss_factor_sqr); memset(&ss_weight_masks[0], 0, ss_factor_sqr*sizeof(SpMask8)); float average_weight = 0.0f; int transp_hits = 0; SpMask8 count_mask(1ull); for (int sp_bin=0; sp_bin < SpMask8::numBits; ++sp_bin, count_mask <<= 1) { const int nHits = bin_hits[sp_bin]; if (nHits == 0 || nHits >= ss_factor_sqr) continue; // Increment weight count for ss bin: ++ss_weight_counts[nHits]; ss_weight_masks[nHits] |= (SpMask8(1ull) << sp_bin); // const float bin_weight = float(nHits) / float(ss_factor_sqr); average_weight += bin_weight; ++transp_hits; } // if (1) { // Output separate segments for each weight bin, building a unique // subpixel mask for each: for (int i=1; i < ss_factor_sqr; ++i) { const int weight_count = ss_weight_counts[i]; if (weight_count == 0) continue; DeepSegment& out_segment = out_pixel.getSegment(out_pixel.append(in_pixel, segment)); // Weight output channels: out_pixel.getSegmentPixel(out_segment) *= float(i) / float(ss_factor_sqr); // Update output metadata: out_segment.metadata.spmask = ss_weight_masks[i]; out_segment.metadata.flags |= DEEP_PARTIAL_BIN_COVERAGE; } } else { // Output only the dominant (just the average for now...) weight: // TODO: change this to some other weighting...? DeepSegment& out_segment = out_pixel.getSegment(out_pixel.append(in_pixel, segment)); // Weight output channels: out_pixel.getSegmentPixel(out_segment) *= (average_weight / float(transp_hits)); // Update output metadata: out_segment.metadata.spmask = out_transp_mask; out_segment.metadata.flags |= DEEP_PARTIAL_BIN_COVERAGE; } } } // segments loop } // tX loop } // tY loop }
static void cmd_stick_yn(int idx, char *par, int yn) { int i = 0, j; struct chanset_t *chan = NULL; char *stick_type = NULL, s[UHOSTLEN] = "", chname[81] = "", type = 0, *str_type = NULL; maskrec *channel_list = NULL; stick_type = newsplit(&par); strlcpy(s, newsplit(&par), sizeof s); strlcpy(chname, newsplit(&par), sizeof chname); if (strcasecmp(stick_type, "exempt") && strcasecmp(stick_type, "invite") && strcasecmp(stick_type, "ban")) { strlcpy(chname, s, sizeof chname); strlcpy(s, stick_type, sizeof s); stick_type = "ban"; } if (!s[0]) { dprintf(idx, "Usage: %sstick [ban/exempt/invite] <hostmask or number> [channel]\n", yn ? "" : "un"); return; } /* Now deal with exemptions */ if (!strcasecmp(stick_type, "exempt")) { type = 'e'; str_type = "exempt"; } else if (!strcasecmp(stick_type, "invite")) { type = 'I'; str_type = "invite"; } else if (!strcasecmp(stick_type, "ban")) { type = 'b'; str_type = "ban"; } else return; if (!chname[0]) { channel_list = (type == 'b' ? global_bans : type == 'e' ? global_exempts : global_invites); i = u_setsticky_mask(NULL, channel_list, s, (dcc[idx].user->flags & USER_MASTER) ? yn : -1, type); if (i > 0) { putlog(LOG_CMDS, "*", "#%s# %sstick %s %s", dcc[idx].nick, yn ? "" : "un", str_type, s); dprintf(idx, "%stuck %s: %s\n", yn ? "S" : "Uns", str_type, s); if (!conf.bot->hub) { struct chanset_t *achan = NULL; for (achan = chanset; achan != NULL; achan = achan->next) check_this_mask(type, achan, s, yn); } else write_userfile(idx); return; } strlcpy(chname, dcc[idx].u.chat->con_chan, sizeof chname); } /* Channel-specific mask? */ if (!(chan = findchan_by_dname(chname))) { dprintf(idx, "No such channel.\n"); return; } get_user_flagrec(dcc[idx].user, &user, chan->dname); if (privchan(user, chan, PRIV_OP)) { dprintf(idx, "No such channel.\n"); return; } channel_list = (type == 'b' ? chan->bans : type == 'e' ? chan->exempts : chan->invites); if (str_isdigit(s)) { /* substract the numer of global masks to get the number of the channel masks */ j = atoi(s); j -= count_mask(type == 'b' ? global_bans : type == 'e' ? global_exempts : global_invites); simple_snprintf(s, sizeof s, "%d", j); } j = u_setsticky_mask(chan, channel_list, s, yn, type); if (j > 0) { putlog(LOG_CMDS, "*", "#%s# %sstick %s %s %s", dcc[idx].nick, yn ? "" : "un", str_type, s, chname); dprintf(idx, "%stuck %s %s: %s\n", yn ? "S" : "Uns", chname, str_type, s); if (!conf.bot->hub) check_this_mask(type, chan, s, yn); else write_userfile(idx); return; } dprintf(idx, "No such %s.\n", str_type); }