//+----------------------------------------------------------------------------+ //| Description: Magic Set Editor - Program to make Magic (tm) cards | //| Copyright: (C) 2001 - 2008 Twan van Laarhoven and "coppro" | //| License: GNU General Public License 2 or later (see file COPYING) | //+----------------------------------------------------------------------------+ // ----------------------------------------------------------------------------- : Includes #include #include #include // ----------------------------------------------------------------------------- : AlphaMask AlphaMask::AlphaMask(const Image& img) : size(img.GetWidth(), img.GetHeight()) { // Copy red chanel to alpha size_t n = size.GetWidth() * size.GetHeight(); alpha = new Byte[n]; Byte* from = img.GetData(), *to = alpha; for (size_t i = 0 ; i < n ; ++i) { *to = *from; from += 3; to += 1; } } AlphaMask::~AlphaMask() { delete[] alpha; } void AlphaMask::setAlpha(Image& img) const { set_alpha(img, alpha, size); } void AlphaMask::setAlpha(Bitmap& bmp) const { Image img = bmp.ConvertToImage(); setAlpha(img); bmp = Bitmap(img); } bool AlphaMask::isTransparent(int x, int y) const { if (x < 0 || y < 0 || x >= size.x || y >= size.y) return false; return alpha[x + y * size.x] < 20; } bool convex(const wxPoint& p, const wxPoint& q, const wxPoint& r) { return p.y*q.x - p.x*q.y - p.y*r.x + q.y*r.x + p.x*r.y - q.x*r.y > 0; } void make_convex(vector& points) { while (points.size() > 2 && !convex(points[points.size() - 3] ,points[points.size() - 2] ,points[points.size() - 1])) { points.erase(points.end() - 2); } } void AlphaMask::convexHull(vector& points) const { // Left side int miny = size.y, maxy = -1, lastx = 0; for (int y = 0 ; y < size.y ; ++y) { for (int x = 0 ; x < size.x ; ++x) { if (alpha[x + y * size.x] >= 20) { // opaque pixel miny = min(miny,y); maxy = y; if (y == miny) { points.push_back(wxPoint(x-1,y-1)); } points.push_back(wxPoint(x-1,y)); make_convex(points); lastx = x; break; } } } if (maxy == -1) return; // No image points.push_back(wxPoint(lastx-1,maxy+1)); make_convex(points); // Right side for (int y = maxy ; y >= miny ; --y) { for (int x = size.x - 1 ; x >= 0 ; --x) { if (alpha[x + y * size.x] >= 20) { // opaque pixel if (y == maxy) { points.push_back(wxPoint(x+1,y+1)); make_convex(points); } points.push_back(wxPoint(x+1,y)); make_convex(points); lastx = x; break; } } } points.push_back(wxPoint(lastx+1,miny-1)); make_convex(points); } // ----------------------------------------------------------------------------- : ContourMask ContourMask::ContourMask() : width(0), height(0), lefts(nullptr), rights(nullptr) {} ContourMask::~ContourMask() { unload(); } void ContourMask::load(const Image& image) { unload(); width = image.GetWidth(); height = image.GetHeight(); lefts = new int[height]; rights = new int[height]; // for each row: determine left and rightmost white pixel Byte* data = image.GetData(); for (int y = 0 ; y < height ; ++y) { lefts[y] = width; rights[y] = width; for (int x = 0 ; x < width ; ++x) { int v = data[0] + data[1] + data[2]; if (v > 50) { // white enough rights[y] = x; if (x < lefts[y]) lefts[y] = x; } data += 3; } } } void ContourMask::unload() { delete lefts; delete rights; lefts = rights = nullptr; width = height = 0; } double ContourMask::rowLeft (double y, RealSize size) const { if (!ok() || y < 0 || y >= size.height) { // no mask, or outside it return 0; } return lefts[(int)(y * size.height / height)] * size.width / width; } double ContourMask::rowRight(double y, RealSize size) const { if (!ok() || y < 0 || y >= size.height) { // no mask, or outside it return size.width; } return rights[(int)(y * size.height / height)] * size.width / width; }