Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Bishop <nicholasbishop@gmail.com>2015-02-13 19:30:04 +0300
committerNicholas Bishop <nicholasbishop@gmail.com>2015-02-13 19:30:04 +0300
commit9b7bb2960b89fe3d2c3a35c5be51db8289e1ecaf (patch)
treeb8c1b6dfcc47c1e0ed16b399aabaaf3bd46aca3b
parent9691524970014032cd612b14fd468bfb0c402eb5 (diff)
Improve filtering across Ptex cornerscycles-ptex-49
-rw-r--r--intern/ptex/bpx_c_api.cpp277
1 files changed, 238 insertions, 39 deletions
diff --git a/intern/ptex/bpx_c_api.cpp b/intern/ptex/bpx_c_api.cpp
index 1b1e095ce48..4a4755084da 100644
--- a/intern/ptex/bpx_c_api.cpp
+++ b/intern/ptex/bpx_c_api.cpp
@@ -320,24 +320,249 @@ static void bpx_create_border(ImageBuf &buf,
bpx_write_border(buf, dst_edge_roi, side_buf, transform);
}
-static const int CORNER_NUM_SOURCES = 2;
-static bool bpx_corner_average(ImageBuf &buf, const int dst_co[2],
- const int src_co[CORNER_NUM_SOURCES][2])
+static const BPXRect &bpx_get_rect(const int i, const void *rects_v,
+ const int stride)
+{
+ const unsigned char *rects_uc = static_cast<const unsigned char*>(rects_v);
+ return *reinterpret_cast<const BPXRect *>(rects_uc + stride * i);
+}
+
+static void bpx_rect_corner_xy(const BPXRect &rect, const BPXRectSide side,
+ int &r_x, int &r_y, const bool border)
+{
+ switch (side) {
+ case BPX_RECT_SIDE_BOTTOM:
+ r_x = rect.xbegin;
+ r_y = rect.ybegin;
+ if (border) {
+ r_x--;
+ r_y--;
+ }
+ break;
+
+ case BPX_RECT_SIDE_RIGHT:
+ r_x = rect.xend - 1;
+ r_y = rect.ybegin;
+ if (border) {
+ r_x++;
+ r_y--;
+ }
+ break;
+
+ case BPX_RECT_SIDE_TOP:
+ r_x = rect.xend - 1;
+ r_y = rect.yend - 1;
+ if (border) {
+ r_x++;
+ r_y++;
+ }
+ break;
+
+ case BPX_RECT_SIDE_LEFT:
+ r_x = rect.xbegin;
+ r_y = rect.yend - 1;
+ if (border) {
+ r_x--;
+ r_y++;
+ }
+ break;
+
+ case BPX_RECT_NUM_SIDES:
+ break;
+ }
+}
+
+static BPXRectSide bpx_rect_side_wrap(const BPXRectSide start,
+ const int offset)
+{
+ const int start_i = static_cast<int>(start);
+ const int num = static_cast<int>(BPX_RECT_NUM_SIDES);
+ const int new_i = (start_i + num + offset) % num;
+ return static_cast<BPXRectSide>(new_i);
+}
+
+struct BPXCornerIter {
+public:
+ enum Direction {
+ CW,
+ CCW
+ };
+
+ BPXCornerIter(const void *rects_v, const int rects_stride,
+ const BPXRect &orig_rect, const BPXRectSide orig_side,
+ const Direction direction)
+ : rects_v(rects_v),
+ rects_stride(rects_stride),
+ orig_rect(&orig_rect),
+ cur_rect(&orig_rect),
+ cur_side(orig_side),
+ direction(direction)
+ {}
+
+ // Return true if the iterator successfully moves to another face,
+ // false if the iterator has reached the end
+ bool next()
+ {
+ if (!cur_rect) {
+ return false;
+ }
+ const BPXRectSideAdj *adj;
+ if (direction == CW) {
+ adj = &cur_rect->adj[cur_side];
+ }
+ else {
+ adj = &cur_rect->adj[bpx_rect_side_wrap(cur_side, -1)];
+ }
+
+ if (adj->index == BPX_RECT_SIDE_ADJ_NONE) {
+ return false;
+ }
+ const BPXRect *next_rect = &bpx_get_rect(adj->index, rects_v,
+ rects_stride);
+ if (orig_rect == next_rect) {
+ return false;
+ }
+
+ cur_rect = next_rect;
+ if (direction == CW) {
+ cur_side = bpx_rect_side_wrap(adj->side, 1);
+ }
+ else {
+ cur_side = adj->side;
+ }
+ return true;
+ }
+
+ void flip_direction() {
+ orig_rect = cur_rect;
+ if (direction == CW) {
+ direction = CCW;
+ }
+ else {
+ direction = CW;
+ }
+ }
+
+ const BPXRect &get_rect() const {
+ return *cur_rect;
+ }
+
+ BPXRectSide get_side() const {
+ return cur_side;
+ }
+
+private:
+ const void *rects_v;
+ const int rects_stride;
+
+ const BPXRect *orig_rect;
+ const BPXRect *cur_rect;
+ BPXRectSide cur_side;
+
+ Direction direction;
+};
+
+// TODO
+struct BPXRectPixel {
+ int x;
+ int y;
+ int bx;
+ int by;
+};
+
+// TODO, better comments
+static void bpx_update_corner(ImageBuf &buf,
+ const void *rects_v,
+ const int rects_stride,
+ const BPXRect &orig_rect,
+ const BPXRectSide orig_side)
{
const int nchannels = buf.nchannels();
- std::vector<float> a(nchannels, 0.0f);
- std::vector<float> b(nchannels, 0.0f);
+ std::vector<float> pixel(nchannels);
+
+ BPXCornerIter iter(rects_v, rects_stride,
+ orig_rect, orig_side,
+ BPXCornerIter::CW);
+ while (iter.next()) {
+ // Iterate as far as possible on one direction. Not needed if
+ // the faces loop all the way around the corner, but needed
+ // for boundaries.
+ }
+
+ std::vector<BPXRectPixel> corners;
+ int my_corner_index = 0;
+
+ // Iterate in the other direction to get all the pixels
+ iter.flip_direction();
+ do {
+ // Find rect corner coordinates
+ BPXRectPixel p;
+ bpx_rect_corner_xy(iter.get_rect(), iter.get_side(),
+ p.x, p.y, false);
+ bpx_rect_corner_xy(iter.get_rect(), iter.get_side(),
+ p.bx, p.by, true);
+
+ if (&iter.get_rect() == &orig_rect) {
+ my_corner_index = corners.size();
+ }
+ corners.push_back(p);
+ } while (iter.next());
- buf.getpixel(src_co[0][0], src_co[0][1], a.data());
- buf.getpixel(src_co[1][0], src_co[1][1], b.data());
+ std::vector<float> accum(nchannels, 0.0f);
+ float fac = 1.0f;
- for (int i = 0; i < nchannels; i++) {
- a[i] = (a[i] + b[i]) * 0.5f;
+ if (corners.size() == 1) {
+ const BPXRectPixel &c = corners[0];
+ buf.getpixel(c.x, c.y, pixel.data());
+ }
+ else if (corners.size() == 2) {
+ // Copy the other rects corner
+ const BPXRectPixel &c = corners[1 - my_corner_index];
+ buf.getpixel(c.x, c.y, pixel.data());
+ }
+ else if (corners.size() == 3) {
+ // Accumulate all three
+ fac = 1.0f / 3.0f;
+ for (int i = 0; i < corners.size(); i++) {
+ const BPXRectPixel &c = corners[i];
+ buf.getpixel(c.x, c.y, pixel.data());
+ for (int c = 0; c < nchannels; c++) {
+ accum[c] += pixel[c];
+ }
+ }
+ }
+ else if (corners.size() == 4) {
+ // Special case of the final else block, only one pixel to
+ // accumulate
+ const BPXRectPixel &c = corners[(my_corner_index + 2) % 4];
+ buf.getpixel(c.x, c.y, pixel.data());
+ }
+ else {
+ // Accumulate all but self and adjacent
+ fac = 1.0f / (corners.size() - 3);
+ for (int i = 0; i < corners.size(); i++) {
+ if (i != my_corner_index &&
+ ((i + 1) % corners.size()) != my_corner_index &&
+ ((i + corners.size() - 1) % corners.size()) != my_corner_index)
+ {
+ const BPXRectPixel &c = corners[i];
+ buf.getpixel(c.x, c.y, pixel.data());
+ for (int c = 0; c < nchannels; c++) {
+ accum[c] += pixel[c];
+ }
+ }
+ }
}
- buf.setpixel(dst_co[0], dst_co[1], a.data());
+ if (corners.size() == 3 || corners.size() >= 5) {
+ for (int c = 0; c < nchannels; c++) {
+ pixel[c] = accum[c] * fac;
+ }
+ }
- return true;
+ // Copy pixel into the corner
+ const BPXRectPixel &c = corners[my_corner_index];
+ buf.setpixel(c.bx, c.by, pixel.data());
}
bool BPX_rect_borders_update(BPXImageBuf *bpx_buf, const BPXRect *dst_rect,
@@ -350,8 +575,6 @@ bool BPX_rect_borders_update(BPXImageBuf *bpx_buf, const BPXRect *dst_rect,
ImageBuf &buf = *bpx_image_buf_to_oiio_image_buf(bpx_buf);
const ROI dst_roi = bpx_rect_to_oiio_roi(*dst_rect);
- const unsigned char *rects_uc = static_cast<const unsigned char*>(rects_v);
-
// Sample adjacent regions to create filter edges
for (int i = 0; i < BPX_RECT_NUM_SIDES; i++) {
const BPXRectSide dst_side = static_cast<BPXRectSide>(i);
@@ -369,8 +592,7 @@ bool BPX_rect_borders_update(BPXImageBuf *bpx_buf, const BPXRect *dst_rect,
}
else {
- const int offset = adj.index * rects_stride;
- src_rect = reinterpret_cast<const BPXRect *>(rects_uc + offset);
+ src_rect = &bpx_get_rect(adj.index, rects_v, rects_stride);
src_edge.side = adj.side;
src_edge.reverse = true;
}
@@ -381,31 +603,8 @@ bool BPX_rect_borders_update(BPXImageBuf *bpx_buf, const BPXRect *dst_rect,
// Also update in the other direction. TODO(nicholasbishop):
// names are a bit confusing now
bpx_create_border(buf, src_roi, src_edge, dst_roi, dst_edge);
- }
- // Average adjacent borders to fill in
- // corners. TODO(nicholasbishop): need to improve this, it is
- // noticable after all
- const int dst_co[BPX_RECT_NUM_SIDES][2] = {
- {dst_roi.xbegin - 1, dst_roi.ybegin - 1},
- {dst_roi.xend , dst_roi.ybegin - 1},
- {dst_roi.xend , dst_roi.yend },
- {dst_roi.xbegin - 1, dst_roi.yend }
- };
- const int src_co[BPX_RECT_NUM_SIDES][CORNER_NUM_SOURCES][2] = {
- {{dst_co[0][0] + 1, dst_co[0][1] },
- {dst_co[0][0], dst_co[0][1] + 1}},
- {{dst_co[1][0] - 1, dst_co[1][1]},
- {dst_co[1][0], dst_co[1][1] + 1}},
- {{dst_co[2][0] - 1, dst_co[2][1]},
- {dst_co[2][0], dst_co[2][1] - 1}},
- {{dst_co[3][0] + 1, dst_co[3][1]},
- {dst_co[3][0], dst_co[3][1] - 1}}
- };
- for (int i = 0; i < BPX_RECT_NUM_SIDES; i++) {
- if (!bpx_corner_average(buf, dst_co[i], src_co[i])) {
- return false;
- }
+ bpx_update_corner(buf, rects_v, rects_stride, *dst_rect, dst_side);
}
return true;