0

我目前正在编写一个将 a 转换BufferedImage为音乐的程序。当我得到 的宽度和高度时BufferedImage,这些值是正确的。但是,在FOR我用来获取像素的循环内,我正在操作FOR循环值之一 ( i++)。在结束时void,我将值重置为其原始状态 ( i--)。该程序不会评估整个图像,而是给我这个错误:

java.lang.ArrayIndexOutOfBoundsException: Coordinate out of bounds!

我应该如何解决这个错误?这是我的代码:

        try {
            String fp = jTextField1.getText();
            File pict = new File(fp);
            BufferedImage img = ImageIO.read(pict);
            // int keybase = img.getRGB(1, 1);
            // int red = (keybase & 0x00ff0000) >> 16;
            // int green = (keybase & 0x0000ff00) >> 8;
            // int blue = keybase & 0x000000ff;
            int width = img.getWidth();
            int height = img.getHeight();
            String key = null;
            int keybase = img.getRGB(1, 1);
            int keyred = (keybase & 0x00ff0000) >> 16;
            int keygreen = (keybase & 0x0000ff00) >> 8;
            int keyblue = keybase & 0x000000ff;
            int keyAvg = (keyred + keygreen + keyblue) / 3;
            if (keyAvg <= 10) {
                key = "Cmaj";
            }
            else if (keyAvg <=20 && keyAvg > 10) {
                key = "Cmin";
            }
            else if (keyAvg <=30 && keyAvg > 20) {
                key = "C#maj";
            }
            else if (keyAvg <=40 && keyAvg > 30) {
                key = "C#min";
            }
            else if (keyAvg <=50 && keyAvg > 40) {
                key = "Dmaj";
            }
            else if (keyAvg <=60 && keyAvg > 50) {
                key = "Dmin";
            }
            else if (keyAvg <=70 && keyAvg > 60) {
                key = "D#maj";
            }
            else if (keyAvg <=80 && keyAvg > 70) {
                key = "D#min";
            }
            else if (keyAvg <=90 && keyAvg > 80) {
                key = "Emaj";
            }
            else if (keyAvg <=100 && keyAvg > 90) {
                key = "Emin";
            }
            else if (keyAvg <=110 && keyAvg > 100) {
                key = "Fmaj";
            }
            else if (keyAvg <=120 && keyAvg > 110) {
                key = "Fmin";
            }
            else if (keyAvg <=130 && keyAvg > 120) {
                key = "F#maj";
            }
            else if (keyAvg <=140 && keyAvg > 130) {
                key = "F#min";
            }
            else if (keyAvg <=150 && keyAvg > 140) {
                key = "Gmaj";
            }
            else if (keyAvg <=160 && keyAvg > 150) {
                key = "Gmin";
            }
            else if (keyAvg <=170 && keyAvg > 160) {
                key = "G#maj";
            }
            else if (keyAvg <=180 && keyAvg > 170) {
                key = "G#min";
            }
            else if (keyAvg <=190 && keyAvg > 180) {
                key = "Amaj";
            }
            else if (keyAvg <=200 && keyAvg > 190) {
                key = "Amin";
            }
            else if (keyAvg <=210 && keyAvg > 200) {
                key = "A#maj";
            }
            else if (keyAvg <=220 && keyAvg > 210) {
                key = "A#min";
            }
            else if (keyAvg <=230 && keyAvg > 220) {
                key = "Bmaj";
            }
            else {
                key = "Bmin";
            }
            int tempoVal = 0;
            int tempobase = img.getRGB(2, 2);
            int tempored = (tempobase & 0x00ff0000) >> 16;
            int tempogreen = (tempobase & 0x0000ff00) >> 8;
            int tempoblue = tempobase & 0x000000ff;
            if (tempored > tempogreen && tempored > tempoblue) {
                tempoVal = tempored;
            }
            else if (tempogreen > tempored && tempogreen > tempoblue) {
                tempoVal = tempogreen;
            }
            else if (tempoblue > tempored && tempoblue > tempogreen) {
                tempoVal = tempoblue;
            }
            else {
                tempoVal = 120;
            }
            String tempo = "T" + String.valueOf(tempoVal) + " ";
            String inst;
            int instbase = img.getRGB(3, 3);
            int red5 = (instbase & 0x00ff0000) >> 16;
            int green5 = (instbase & 0x0000ff00) >> 8;
            int blue5 = instbase & 0x000000ff;
            int instAvg = (red5 + green5 + blue5) / 3;
            if (instAvg > 111) {
                instAvg = instAvg / 2;
                inst = "I" + String.valueOf(instAvg) + " ";
            }
            else {
                inst = "I" + String.valueOf(instAvg) + " ";
            }
            for (int i = 0; i < width; i++) {
                for (int j = 0; j < height; j++) {
                    int note = img.getRGB(i, j);
                    int red = (note & 0x00ff0000) >> 16;
                    int green = (note & 0x0000ff00) >> 8;
                    int blue = note & 0x000000ff;
                    int noteAvg = (red + green + blue) / 3;
                    if (noteAvg >= 127) {
                        noteAvg = noteAvg / 2;
                    }
                    String nAvg = String.valueOf(noteAvg);
                    i++;
                    int len = img.getRGB(i, j);
                    int red2 = (len & 0x00ff0000) >> 16;
                    int green2 = (len & 0x0000ff00) >> 8;
                    int blue2 = len & 0x000000ff;
                    int noteAvg2 = (red2 + green2 + blue2) / 3;
                    String noteLen;
                    String keyVar = null;
                    if (noteAvg2 <= 42) {
                        noteLen = "W";
                    }
                    else if (noteAvg2 <= (42 * 2) && noteAvg2 > 42) {
                        noteLen = "H";
                    }
                    else if (noteAvg2 <= (42 * 3) && noteAvg2 > (42 * 2)) {
                        noteLen = "Q";
                    }
                    else if (noteAvg2 <= (42 * 4) && noteAvg2 > (42 * 3)) {
                        noteLen = "I";
                    }
                    else if (noteAvg2 <= (42 * 5) && noteAvg2 > (42 * 4)) {
                        noteLen = "S";
                    }
                    else {
                        noteLen = "T";
                    }
                    i++;
                    int keyvarbase = img.getRGB(i, j);
                    int red4 = (keyvarbase & 0x00ff0000) >> 16;
                    int green4 = (keyvarbase & 0x0000ff00) >> 8;
                    int blue4 = keyvarbase & 0x000000ff;
                    int noteAvg4 = (red4 + green4 + blue4) / 3;
                    int findKeyVar = noteAvg4 % 4;
                    if (findKeyVar == 1) {
                        keyVar = "min";
                    }
                    else if (findKeyVar == 2) {
                        keyVar = "maj";
                    }
                    else if (findKeyVar == 3) {
                        keyVar = "aug";
                    }
                    else {
                        keyVar = "dim";
                    }
                    i++;
                    int inv = img.getRGB(i, j);
                    int red3 = (inv & 0x00ff0000) >> 16;
                    int green3 = (inv & 0x0000ff00) >> 8;
                    int blue3 = inv & 0x000000ff;
                    int noteAvg3 = (red3 + green3 + blue3) / 3;
                    String inversion = null;
                    if (noteAvg3 <= (85 * 2) && noteAvg3 > 85) {
                        inversion = "^";
                    }
                    else if (noteAvg3 <= (85 * 3) && noteAvg3 > (85 * 2)) {
                        inversion = "^^";
                    }
                    if (noteAvg == 0) {

                    }
                    else {
                        String forPlayer = tempo + inst + "K" + key + " [" + nAvg + "]" + keyVar + noteLen;
                        midi.add(forPlayer);
                        midi.add("_");
                        player.play(forPlayer);
                    }
                    i--;
                    i--;
                    i--;
                }
            }
        } catch (IOException ex) {
            Logger.getLogger(I2MC.class.getName()).log(Level.SEVERE, null, ex);
        }

我正在使用 JFugue API。

4

1 回答 1

2

任何一个

for (int i = 0; i < width - 3; i++) { // Will use index i+3

ifs。

当您i++在循环内执行三次并i用作索引,然后三次i--,在单个循环步骤开始时, i+3 必须小于宽度才能成为有效索引。

虽然你的风格一丝不苟,但使用

final int i1 = i + 1;
final int i2 = i + 2;
final int i3 = i + 3;

可能会使代码更具可读性。

一个算法证明i++会更复杂,看起来像:

// Define VALID_I(index) = (0 <= index < width)

for (int i = 0; i < width - 3; i++) { // Will use index i+3
    // Step pre-condition: 0 <= i < width - 3} => VALID_I(i)
    ... getRGG(i, j);
    i++;
    // 1 <= i < width - 2 => VALID_I(i)
    i++;
    // 1 <= 2 < width - 1 => VALID_I(i)
    i++;
    // 1 <= 3 < width => VALID_I(i)
    i -= 3;
    // Step post-condition: 0 <= i < width - 3} => VALID_I(i)
    // Loop-invariant: Step post-condition == step pre-codition
}

替代 if 的:

for (int i = 0; i < width; i++) { // 将使用索引 i+3 // 步骤前置条件:0 <= i < width} <=> VALID_I(i) ... getRGG(i, j); 我++;// 1 <= i < width + 1 => VALID_I(i) if (i + 1 >= width) break; // 1 <= i < 宽度 => VALID_I(i) i++; if (i + 1 >= width) 中断;// 2 <= i < width => VALID_I(i) i++; if (i + 1 >= width) 中断;// 3 <= i < width =e > VALID_I(i) i -= 3; // 0 <= i < width - 3 => VALID_I(i) // 步骤后置条件:0 <= i < width - 3} => VALID_I(i) // 循环不变:步骤后置条件 ==步骤预编码 }

与嵌套的 ifs 相同。

这三个备选方案对于 i >= width - 3 具有不同的行为。

于 2013-01-05T07:59:15.403 回答