◆PROCESSING 逆引きリファレンス
 カテゴリー:イメージ処理
 カテゴリー:イメージ処理
画面全体を拡大縮小するには
【概要】
PROCESSINGは scale()命令を利用すると、画面全体の描画サイズを変更することが可能です。つまり scale()命令を利用すれば、結果として画面全体の拡大縮小を行うことが可能となります。
画面全体の拡大縮小処理は、以下のようなケースでも有効活用できます。
PROCESSINGには画面全体に対して画像加工を行う(ボカシやフィルターなどをかける)命令がいくつか存在しますが、これらの処理は1つ1つの画素に対して演算を行うため、どうしても重たい処理になります。
そこで十分に小さな画面領域に対して画像描画と加工を行い、それを画面全体に拡大表示するのです。こうする事で、画面全体に対して画像加工を行う時に比べ、高速に表示を行うことができるようになります。
ただし(特に)画面の拡大処理は、結果として描画内容が荒くなる事になりますので、精細な表示な求められるような場面には不向きです。そこは注意してください。
【詳細】
描画サイズを変更する
void scale( float xPercent, float yPercent );
void scale( float xPercent, float yPercent, float zPercent );
scalePercent:画面全体の縮小率
xPercent:横方向の縮小率
yPercent:縦方向の縮小率
zPercent:奥行への縮小率(P3D利用時)
scale()命令は draw() 関数の中で利用します。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | void setup(){   size( 200,200 );   //四角形の描画方法を中央描画に   rectMode( CENTER );   //塗りつぶし無しで線幅を4に   noFill();   strokeWeight( 4 ); } void draw(){   background( 200 );   //画面中央に、赤の四角形を描画   stroke( 255, 0, 0 );   rect( width/2, height/2, 100, 100 );   //縮小率を半分(50%)に変更   scale( 0.5f );   //先ほどと同じ四角形を青で描画   stroke( 0, 0, 255 );   rect( width/2, height/2, 100, 100 ); } | 
<出力結果>

例えば上記を実行すると、このような絵が描画されます。
赤い四角形は普通に描画したもので、縦横100ピクセルの四角形が画面中央に描かれます。
青い四角形は scale()命令で縮率を50%にしたものなので、同じサイズで描画しても赤い四角形の半分の大きさ(面積比1/4)で描かれています。また線幅も赤い四角形に比べて半分(線幅2)になっている事にも注意してください。
scale()命令で変更した縮小率は、draw()ループを抜けると初期化されます。
なので
| 1 2 3 4 5 6 | void draw(){  …  scale( 0.5f );  scale( 0.5f );  … } | 
とすると、以降は元画像の1/2の1/2、つまり元画像の1/4(25%)の縮小率で描画されることになります。
縮小率は縦横別々に指定する事も可能です。例えば先ほどのサンプルで scale()命令を使っている箇所を
| 1 2 | //縮小率を横だけ50%にする scale( 0.5, 1.0 ); | 
上記のように変更すると

このような描画になります。横方向だけ縮小率が50%になったので、青い四角形が縦長になりました。
応用例
これを応用すると、マウスクリックなどで画像を拡大縮小する事ができるようになります。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | float  scaleVal; PImage img; float  px, py; final float  MIN_SCALE = 0.1f; final float  MAX_SCALE = 3.0f; void setup(){   size( 300,300 );   img = loadImage("witch.png");   //最初の倍率は1.0(=等倍=100%)     scaleVal = 1.0; } void draw(){   background( 240 );   //縮小率を変更   scale( scaleVal );   //画面中央に、図形描画   imageMode( CENTER );     px = width/2  * 1/scaleVal;   py = height/2 * 1/scaleVal;   image( img, px, py ); } void mouseWheel( MouseEvent e ){   if( e.getCount() < 0 ){     //奥に向かってホイールなら10%ずつ縮小     scaleVal = scaleVal - 0.1;     if( scaleVal < MIN_SCALE ){       //最小倍率は10%       scaleVal = MIN_SCALE;     }   } else {     //手前に向かってホイールなら10%ずつ拡大     scaleVal = scaleVal + 0.1;     if( scaleVal > MAX_SCALE ){       //最大倍率は300%       scaleVal = MAX_SCALE;     }   } } | 
上記例を実行すると、画面中央にキャラクターの絵が表示されます。
 (画像URL:illust-AC 様:Kamesanさん、acworksさん)
(画像URL:illust-AC 様:Kamesanさん、acworksさん)
マウスホイールを奥に向かって回すと画像が縮小、手前に向かって回すと拡大されます。
| 1 2 3 4 5 | //画面中央に、図形描画 imageMode( CENTER );   px = width/2  * 1/scaleVal; py = height/2 * 1/scaleVal; image( img, px, py ); | 
と書かれた部分を解説します。
基本的には imageMode()命令で画像の描画原点を画像を囲む矩形の中央にし、それを image() 命令で画面中央に表示しています。
ただ普通に
| 1 | image( img, width/2, height/2 ); | 
とすると、描画領域を元画像(100%表示)の半分の大きさに縮小した場合、図のAにあった中心点がBの位置になってしまいます。
 そこで拡大縮小率に応じて、画像の中心点(描画原点)を、常に画面の中央になるように補正します。
そこで拡大縮小率に応じて、画像の中心点(描画原点)を、常に画面の中央になるように補正します。

たとえば縮率50%なら、width/2(A) が width/4(B) になっているので、これを2倍する事で元の位置(A)に補正するわけです。
【関連記事】
- なし
サンプルプログラム
画像加工高速表示例:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | /**  * PROCESSING 3 画面拡大縮小Sample  * @auther MSLABO  * @version 2020/2 1.0  */ PFont     font;       //文字 PImage    orgImage;   //元画像 PGraphics processPg;  //加工用エリア float     level;      //閾値 float     scaleVal, scaleX, scaleY;  float     px, py; void setup(){   //画面の大きさ   size( 1920,1000 );   orgImage = loadImage("girl.jpg");   textSize( 64 );   textAlign( LEFT, TOP );   //画像加工用のエリア作成   processPg = createGraphics(orgImage.width, orgImage.height);   //ぼかし加工   level = 0;   ImageProcessing( level );   //表示用の拡大縮小率を計算   scaleX = width/orgImage.width;   scaleY = height/orgImage.height;   scaleVal = scaleX > scaleY ? scaleY : scaleX; } void draw(){   background( 0 );   //元画像を左下に表示   imageMode( CORNER );   image( orgImage, 0, height - orgImage.height );   //閾値を表示   stroke(255);   text( level, 0, 0);   ////画面の縮小率を変更   scale( scaleVal );   px = width/2 * 1/scaleVal;    py = height/2 * 1/scaleVal;      ////加工した画像を中央に表示   imageMode( CENTER );   image( processPg, px, py );  } void mouseWheel( MouseEvent e ){   if( e.getCount() < 0 ){     //奥にホイールしたらぼかす     level = level + 0.25;     if( level > 20 ){       level = 20;     }   } else {     //手前にホイールしたら元に戻す     level = level - 0.25;     if( level < 0 ){       level = 0;     }   }   //新しい閾値で画像加工   ImageProcessing( level ); } /**  * ぼかし処理  * @param val : 閾値(0-20)  */ void ImageProcessing( float val ){   processPg.beginDraw();   //加工エリアに画像を貼る   processPg.image( orgImage, 0, 0 );   //ぼかし処理   processPg.filter( BLUR, val );   processPg.endDraw(); } | 
上記を実行すると、小さな元画像(214✕320)に対して画像加工(ぼかし)を実行し、それを引き伸ばして、大きな画面(1900✕1000)に表示します。
画面全体(1900✕1000)に画像加工を行うのに比べて、結果をかなり高速に表示できます。ただし加工後の画像は引き伸ばして表示されているので、品質が低下しています。

(画像URL:illust-AC ・photo-AC 様:acworksさん)
画像サイズを小さくすれば、より高速に表示できますが、より品質は低下します。
<出力サンプル>
 (画像URL:illust-AC ・photo-AC 様:acworksさん)
(画像URL:illust-AC ・photo-AC 様:acworksさん)
本ページで利用しているアイコン画像は、下記サイト様より拝借しております。各画像の著作権は、それぞれのサイト様および作者にあります。