예제 #1
0
/*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

}
예제 #2
0
파일: cmdschan.c 프로젝트: kirune/wraith
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);
}