import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import javax.imageio.ImageIO;

public class BMPLoader {
    public int height=0;
    public int width=0;
    public String inputDir;
    public String outputDir;

    public BMPLoader(String in, String out) {
        this.inputDir = in;
        this.outputDir = out;
    }

    public double[] toDouble(byte[] vec) {
        double[] ret = new double[vec.length];
        for (int i=0; i<vec.length; i++) {
            ret[i] = (double)(vec[i] & 0xFF) / 255;
        }
        return ret;
    }

    public byte[] toByte(double[] vec) {
        byte[] ret = new byte[vec.length];
        for (int i=0; i<vec.length; i++) {
            ret[i] = (byte)(vec[i] * 255);
        }
        return ret;
    }

    public double[] readBMP(String path){
        return readBMP(new File(path));
    }

    public double[] readBMP(File file){
        // read image
        BufferedImage img;
        try { 
            img = ImageIO.read(file); 
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        if (height == 0 && width == 0) { // avoid multiple setting
            height = img.getHeight();
            width  = img.getWidth();
        }
        // make sure it's grayscale (one byte per pixel)
        if(img.getType()!=BufferedImage.TYPE_BYTE_GRAY) {
            // System.err.println("Converting to grayscale..."); // too verbose
            img = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
        }

        // return array of pixels
        byte[] pixels = new byte[width*height];
        img.getRaster().getDataElements(0,0,width,height,pixels);
        return toDouble(pixels);
    }

    public void writeBMP(double[] pixels, String path) {
        // make image
        BufferedImage image = new BufferedImage(
            height, width,BufferedImage.TYPE_BYTE_GRAY);

        //set pixels
        image.getRaster().setDataElements(0,0,width,height,toByte(pixels));

        // write file
        try { 
            ImageIO.write(image, "BMP", new File(path));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void saveAll(double[][] imgs, String basename) {
        writeBMPs(imgs, outputDir+"/"+basename);
    }

    public void writeBMPs(double[][] imgs, String basename) {
        for (int i=0; i<imgs.length; i++) {
            writeBMP(imgs[i], basename+"_"+(i+1)+".bmp");
        }
    }

    public File[] listBMP(){
        return listBMPInDir(inputDir);
    }

    public File[] listBMPInDir(String path){
        return new File(path).listFiles(new FilenameFilter() {
                @Override
                public boolean accept(File dir, String name) {
                    return name.endsWith(".bmp");
                }
            });
    }

    public double[][] readAll() {
        return readAllBMPInDir(inputDir);
    }

    public double[][] readAllBMPInDir(String path) {
        File[] files = listBMPInDir(path);
        double[][] ret = new double[files.length][];
        System.out.println("Loading all BMP files in path `"+path+"`");
        int i;
        for (i=0; i<files.length; i++) {
            System.out.print(".");
            ret[i] = readBMP(files[i]);
        }
        System.out.println("\nLoaded "+i+" files.");
        return ret;
    }

    public double[] average(double[][] images) {
        int imglen = images[0].length;
        double[] avg = new double[imglen];
        for (int pixidx=0; pixidx<imglen; pixidx++) {
            avg[pixidx] = 0;
            for (int imgidx=0; imgidx<images.length; imgidx++) {
                avg[pixidx] += images[imgidx][pixidx];
            }
            avg[pixidx] /= images.length;
        }

        return avg;
    }

    // Rescales an array of values to range [0,1]
    public double[] rescale(double[] image) {
        double min=image[0],max=image[0];
        // find min/max
        for (int i=0; i<image.length; i++) {
            if (image[i]<min) { min=image[i]; }
            if (image[i]>max) { max=image[i]; }
        }
        // rescale
        double[] ret = new double[image.length];
        for (int i=0; i<image.length; i++) {
            ret[i] = ((image[i] - min) / (max - min));
        }
        
        return ret;
    }
}

@@ -2922,32 +2922,131 @@
      %7D);%0A    %7D%0A%0A
+    public double%5B%5D%5B%5D readAll(int limit) %7B%0A        return readAllBMPInDir(inputDir, limit);%0A    %7D%0A%0A
     public doubl
@@ -3177,42 +3177,202 @@
     
-File%5B%5D files = listBMPInDir(path);
+return readAllBMPInDir(path, 0);%0A    %7D%0A%0A    public double%5B%5D%5B%5D readAllBMPInDir(String path, int limit) %7B%0A        File%5B%5D files = listBMPInDir(path);%0A        if (limit%3C=0) %7B limit = files.length; %7D
 %0A   
@@ -3404,28 +3404,21 @@
  double%5B
-files.length
+limit
 %5D%5B%5D;%0A   
@@ -3521,28 +3521,21 @@
 (i=0; i%3C
-files.length
+limit
 ; i++) %7B

Allow limited loading for BMPs from a directory