// シームレス画像作成テスト /* @pjs preload="seamless_g_src.png,taj_orig.jpg"; */ PImage img, dstImg; // 初期化 void setup() { size(512, 512); // img = loadImage("seamless_g_src.png"); img = loadImage("taj_orig.jpg"); dstImg = makeSeamless(img); } // 描画 void draw() { background(128); // マウスボタンを押していたら元画像を表示 if ( mousePressed == true) { image(img, 0, 0); } else { image(dstImg, 0, 0); } } // マウスボタンクリック時 void mouseClicked() { if (mouseButton != RIGHT) return; // 右ボタンが押されたら画像保存 dstImg.save("dst.png"); } // 合成の割合を求める float getWeight(float x, float y, float w, float h) { // from gimp filter gimp-2.8.16/plug-ins/common/tile-seamless.c float a = (abs(x - w) - 1) / (w - 1); float b = (abs(y - h) - 1) / (h - 1); if (a < 0.00000001 && b > 0.99999999) return 1.0; if (a > 0.99999999 && b < 0.00000001) return 0.0; return 1.0 - (a * b / (a * b + (1.0 - a) * (1.0 - b))); } // シームレス画像を生成 PImage makeSeamless(PImage img) { color src0, src1; float dstr, dstg, dstb, dsta; int adrs0, adrs1; int w = img.width; int h = img.height; PImage dstImg = createImage(w, h, ARGB); img.loadPixels(); dstImg.loadPixels(); int hw = w / 2; int hh = h / 2; for (float y=0; y < h; y++) { for (float x=0; x < w; x++) { float tx = (x < hw)? x : (w - x - 1); float ty = (y < hh)? y : (h - y - 1); float d0 = getWeight(tx, ty, hw, hh); float d1 = 1- d0; adrs0 = int((y + hh) % h * w + (x + hw) % w); adrs1 = int(y * w + x); src0 = img.pixels[adrs0]; src1 = img.pixels[adrs1]; dstr = red(src0) * d1 + red(src1) * d0; dstg = green(src0) * d1 + green(src1) * d0; dstb = blue(src0) * d1 + blue(src1) * d0; dsta = alpha(src0) * d1 + alpha(src1) * d0; dstImg.pixels[adrs0] = color(dstr, dstg, dstb, dsta); } } dstImg.updatePixels(); return dstImg; }