読者です 読者をやめる 読者になる 読者になる

プログラミング向上雑記

プログラミングが趣味のだらだら学生。自作したプログラムの紹介やいまハマってることなんかを適当に書いていったりいかなったり。Twitterはこちら→ @niishi_8

Processingでディレクトリ内の全ての画像を読み込む方法(モザイクはずすプログラムもあるよ!)

Processing プログラミング ソースコード

Processingで画像を全て読み込みたい

画像を扱うプログラムを作ろうとおもうとき、フォルダの中の画像全て読み込んできたいということがあると思います。
今回は、Processingではどうすればフォルダ内の画像全て読み込めるようになるのか解説していきたいと思います。

実装方法

ProcessingではselectFolder()と言う関数が用意されており、これを実行するとフォルダを選択するダイアログが表示されます。具体的な使い方は以下の通りです。

void setup() {
   selectFolder("写真のあるフォルダを選択してください","loadImages");
}
void loadImages(File selection){
    File files = selection.listFiles();
    // 以下、各ファイルについて操作を行う
}

こんなダイアログボックスが出てくるはずなんで適当にフォルダを選んでください。しかし、まあなんともレガシーな見た目…… f:id:kirari0831:20160104231044p:plain

ここでselectFoloder()でフォルダが選択されると、第2引数に与えたメソッド名のメソッドが呼び出されます(上の例ではloadImages())。呼び出す関数はさきほど選択したFileを引数に受け取らなければなりません。ちなみに、Fileクラスはそれがファイルだろうがディレクトリだろうが気にしませんのでご注意を。

では選択したフォルダ内の全ての画像を読み込んでいきましょう。ProcessingのloadImage()では以下の拡張子(.gif, .jpg, .png, .tif)の画像が読み込めるのでこれに該当するかどうか調べましょう。Stringクラスの関数endsWith()を使ってファイル名の末尾がその拡張子と同じか調べることでできます。画像ファイルであることがわかればあとは読み込むだけです。いままで紹介してきた記事では事前に画像やファイルをプログラム内に取り込んでおきましたが、今回はファイルの絶対パスが簡単に取得できちゃうので事前に取り込む必要はないです。file.ggetAbsolutePath()絶対パスが取得できるためこれをloadImage()にぶちこんじゃいましょう。

ArrayList<PImage> images = new ArrayList<PImage>(); //読み込んだ画像の保存先
String[] extensions = { //操作したいファイルの拡張子を登録
    ".jpg",".gif",".tga",".png"
};
void loadImages(File selection){
    File[] files = selection.listFiles();   //ディレクトリ内の全てのファイル(ディレクトリも含む)を取得
    for(int i = 0; i < files.length; i++){
        for(String extension : extensions){
            if(files[i].getPath().endsWith(extension)){ //ファイル名の末尾が拡張子と一致するか
                PImage img = loadImage(files[i].getAbsolutePath()); //絶対パスで画像を読み込む
                images.add(img);
            }
        }
    }
}

実際にプログラムに用いてみる

これで画像をすべて読み込むことができました。普通だったらこれでスライドショープログラムでも作るのがふつうなのでしょうが、せっかく前回の記事で変なことやったのでそれの拡張にしましょう。前回は1枚分の画像しか読み込めませんでしたが、ディレクトリ内の画像丸ごと持って来てモザイクはずしていっちゃいましょう。

void setup() {
   surface.setResizable(true);
   selectFolder("写真のあるフォルダを選択してください","loadImages");
}
int indexOfImage = 0;
ArrayList<PImage> originalImages = new ArrayList<PImage>();
ArrayList<PImage> mosaicImages = new ArrayList<PImage>();
String[] extensions = {
    ".jpg",".gif",".tga",".png"
};
void loadImages(File selection){
    File[] files = selection.listFiles();
    for(int i = 0; i < files.length; i++){
        for(String extension : extensions){
            if(files[i].getPath().endsWith(extension)){
                PImage originalImage = loadImage(files[i].getAbsolutePath());
                PImage mosaicImage = loadImage(files[i].getAbsolutePath());
                fitSize(originalImage);
                fitSize(mosaicImage);
                mosaicImage.filter(BLUR, 20);
                originalImages.add(originalImage);
                mosaicImages.add(mosaicImage);
            }
        }
    }
    if(!originalImages.isEmpty()){
        PImage img = originalImages.get(0);
        surface.setSize(img.width, img.height);
    }
}

int length = 600;
void fitSize(PImage img){
    if(img.width > img.height){
         img.resize(600,0);
     }else{
         img.resize(0,600);
     }
}


void draw() {
    if(!mosaicImages.isEmpty()){
        image(mosaicImages.get(indexOfImage),0,0);
        if(!(mouseX == 0 || mouseX == width || mouseY == 0 || mouseY == height)){
            clearCircle();
        }
    }
}

int rectWidth = 200;
void clearRectangle(){
   int startX = mouseX - rectWidth/2;
   int startY = mouseY - rectWidth/2;
   if(startX < 0){
       startX = 0;
   }
   if(startY < 0){
       startY = 0;
   }
   int endX = startX + rectWidth;
   int endY = startY + rectWidth;
   if(endX >= width){
       endX = width-1;
   }
   if(endY >= height){
       endY = height-1;
   }
   copy(originalImages.get(indexOfImage),startX,startY,endX-startX,endY-startY,startX,startY,endX-startX,endY-startY);
}
int r = 200;
void clearCircle(){
   int startY = mouseY - r/2;
   for(int y = startY; y < startY+r; y++){
       if(y >= 0 && y < height){
           int h = abs(y-mouseY);
           int w = int(sqrt(r/2*r/2-h*h))*2;
           int startX = mouseX - w/2;
           for(int x = startX; x < startX+w; x++){
               if(x >= 0 && x < width){
                   set(x,y,originalImages.get(indexOfImage).get(x,y));
               }
           }
       }
   }
   updatePixels();
}

void keyPressed(){
   if(keyCode == UP){
       r += 50;
   }
   else if(keyCode == DOWN){
       if(r > 0){
           r -= 50;
       }
   }else if(keyCode == RIGHT){
       indexOfImage = (indexOfImage+1)%originalImages.size();
       PImage img = originalImages.get(indexOfImage);
       surface.setSize(img.width, img.height);
   }else if(keyCode == LEFT){
       indexOfImage--;
       if(indexOfImage < 0){
           indexOfImage += originalImages.size();
       }
       indexOfImage = (indexOfImage)%originalImages.size();
       PImage img = originalImages.get(indexOfImage);
       surface.setSize(img.width, img.height);
   }
}

これで色んな画像を一辺に堪能することができるようになりましたね!めでたしめでたし。 f:id:kirari0831:20160104231126j:plain f:id:kirari0831:20160104231510j:plain