// 画像用の変数 PImage[] img = new PImage[5]; // 出力ファイル名 String[] fName = {"元", "選択範囲", "1描画機能", "2最近傍補間", "3双一次補間"}; int w, h; boolean created = false; // 画像を作ったかどうかのフラグ float cx, cy; // 拡大の基準位置 float s = 5; // 拡大の倍率 void setup() { size(800, 600); img[0] = loadImage("元.jpg"); img[0].resize(width, height); w = width; h = height; // 1~4番を元画像と同じサイズの黒画像にする for (int i=1; i<=4; i++) { img[i] = img[0].get(); } textFont(createFont("MS Pゴシック", 48)); noFill(); // 図形の中を塗りつぶさない設定にする strokeWeight(2*s); // 図形の枠の太さを実質2ptにする stroke(255, 0, 0); // 図形の枠の色を赤にする } void draw() { cx = mouseX; // 拡大基準の横位置の更新 cy = mouseY; // 拡大基準の縦位置の更新 // 画像作成前 (選択範囲に枠を描画する) if (!created) { background(0); image(img[0], 0, 0, width, height);// 画像を表示 translate(cx, cy); // 原点をカーソル位置に移動 scale(1/s); // 拡大率の逆数のスケールをかける translate(-cx, -cy); // 枠内での中心位置移動 rect(0, 0, width, height); // 元画像サイズの長方形を描く } } // 実行画面のスクリーンショットを保存する void saveScreenshot(int n) { loadPixels(); // 実行画面の情報をpixelsにロード img[n].pixels = pixels; // pixelsの情報をimg[n]にコピー img[n].save("data/" + fName[n] + ".jpg"); } // Processingの描画機能を使って拡大(課題1) void drawToImage(float s, int n) { PGraphics pg = createGraphics(w, h); pg.beginDraw(); pg.translate(cx, cy); // (pg)原点を(cx, cy)だけ平行移動 pg.scale(s); // (pg)けスケールをかける pg.translate(-cx, -cy); // (pg)原点を(-cx, -cy)だけ平行移動 pg.image(img[0], 0, 0); pg.endDraw(); img[n].pixels = pg.pixels; img[n].save("data/"+ fName[n] +".jpg"); } // 最近傍補間(課題2) void nearestNeighbor(float s, int n) { for (int j=0; j<h; j++) { for (int i=0; i<w; i++) { // 出力画像の(i, j)の位置に対応する元画像の位置(i0, j0)を求める PVector pos = getScaledPosition(new PVector(cx-0.5, cy-0.5), new PVector(i, j), s); int i0 =round(pos.x); int j0 =round(pos.y); // 出力画像の(i, j)の点の色を元画像の(i0, j0)の色にする img[n].pixels[i+j*w] = img[0].pixels[i0+j0*w]; } } img[n].save("data/"+ fName[n] +".jpg"); } // 双一次補間(課題3) void bilinear(float s, int n) { for (int j=0; j<h; j++) { for (int i=0; i<w; i++) { // 出力画像の(i, j)の位置に対応する元画像の位置(i0, j0)を求める PVector pos = getScaledPosition(new PVector(cx-0.5, cy-0.5), new PVector(i, j), s); int i0 =int(pos.x); int j0 =int(pos.y); color clt = img[0].pixels[i0+j0*w]; //対応点の左上の点の色 color crt = img[0].pixels[i0+1+j0*w]; //対応点の右上の点の色 color clb = img[0].pixels[i0+(j0+1)*w]; //対応点の左下の点の色 color crb = img[0].pixels[i0+1+(j0+1)*w]; //対応点の右下の点の色 // 対応点の左上のピクセルからの横、縦のずれ float x = pos. x-i0; float y = pos. y-j0; float r = (1-y)*((1-x)*red(clt)+x*red(crt))+y*((1-x)*red(clb)+x*red(crb)); //対応点の色の赤成分 float g = (1-y)*((1-x)*green(clt)+x*green(crt))+y*((1-x)*green(clb)+x*green(crb));// 対応点の色の緑成分 float b = (1-y)*((1-x)*blue(clt)+x*blue(crt))+y*((1-x)*blue(clb)+x*blue(crb)); // 対応点の色の青成分 // (r, g, b)から色を作り、それを出力画像の(i, j)の点の色とする img[n].pixels[i+j*w] = color(r, g, b); } } img[n].save("data/"+ fName[n] + ".jpg"); } // cを中心として画像を1/s倍したときのベクトルfの移動先のベクトルを返す(課題2, 3で使用) PVector getScaledPosition(PVector c, PVector f, float s) { f.sub(c); // fからcを引く f.div(s); // fを1/s倍する f.add(c); // fにcを加える return f; } // 拡大処理を実行 void mousePressed() { if (created) return; // 画像作成後なら何もしない saveScreenshot(1); // 実行画面をimg[1]に保存 drawToImage(s, 2); // 描画機能でs倍に拡大した画像をimg[2]に保存 nearestNeighbor(s, 3); // 最近傍補間でs倍に拡大した画像をimg[3]に保存 bilinear(s, 4); // 双一次補間でs倍に拡大した画像をimg[4]に保存 println("完了"); created = true; } void keyPressed() { int k = key-'0'; if (k>=0 && k<=4) { background(0); image(img[k], 0, 0, width, height); fill(255, 0, 0); text(fName[k], 30, height-30); fill(255); } }