【问题标题】:Merging png files programmatically以编程方式合并 png 文件
【发布时间】:2020-03-05 03:21:45
【问题描述】:

我意识到这个主题有很多帖子,我已经使用它们来做到这一点,但我觉得我需要一些额外的东西才能越过山,因为没有一个人演示了在这个过程中使用数组。

我正在构建一个适合儿童的数学应用程序,因此,我使用 .png 文件来显示相关数字。我在可绘制文件夹中有 png 格式的数字 0-9(透明属性所需),并且仅使用数字 0-9 时进行了测试,但我希望应用程序的范围更进一步 - 数字 > 10(可能 > 100 ( )。

首先,我已将文件输入到位图数组中 -

    bitmapNumbers[0] = BitmapFactory.decodeResource(getResources(), R.drawable.zero);
    bitmapNumbers[1] = BitmapFactory.decodeResource(getResources(), R.drawable.one);
    bitmapNumbers[2] = BitmapFactory.decodeResource(getResources(), R.drawable.two);
    bitmapNumbers[3] = BitmapFactory.decodeResource(getResources(), R.drawable.three);
    bitmapNumbers[4] = BitmapFactory.decodeResource(getResources(), R.drawable.four);
    bitmapNumbers[5] = BitmapFactory.decodeResource(getResources(), R.drawable.five);
    bitmapNumbers[6] = BitmapFactory.decodeResource(getResources(), R.drawable.six);
    bitmapNumbers[7] = BitmapFactory.decodeResource(getResources(), R.drawable.seven);
    bitmapNumbers[8] = BitmapFactory.decodeResource(getResources(), R.drawable.eight);
    bitmapNumbers[9] = BitmapFactory.decodeResource(getResources(), R.drawable.nine);

当 Activity 加载时,它会调用一个方法来生成总和并将其显示给用户,然后需要用户输入,该输入会调用另一个方法来检查答案。下面是 generateSum 方法——

public void generateSum () {

    String stringFirst;
    String stringSecond;

    Bitmap[] buildFirst;
    Bitmap[] buildSecond;

    String newFile = "";

    Random rand = new Random();

    // generate first random number

    firstNumber = rand.nextInt(highestNumber + 1);
    stringFirst = String.valueOf(firstNumber);
    int[] splitFirst = new int[stringFirst.length()];

    for (int i = 0; i < stringFirst.length(); i++) {

        // split number down to individual 'single-digit' elements

        splitFirst[i] = Integer.parseInt(stringFirst.substring(i, i + 1));

    }

    // generate second random number

    secondNumber = rand.nextInt(highestNumber + 1);
    stringSecond = String.valueOf(secondNumber);
    int[] splitSecond = new int[stringSecond.length()];

    for (int i = 0; i < stringSecond.length(); i++) {

        // split number down to individual 'single-number' elements

        splitSecond[i] = Integer.parseInt(stringSecond.substring(i, i + 1));

    }

    // calculate sum answer depending on mode selected in setup

    switch (sPrefs.getString("sumMethod", null)) {
        case ("Addition"):
            answer = firstNumber + secondNumber;
            break;
        case ("Subtraction"):
            if (secondNumber > firstNumber) {
                while (secondNumber > firstNumber) {

                    firstNumber = rand.nextInt(highestNumber + 1);
                    secondNumber = rand.nextInt(highestNumber + 1);

                }
            }
            answer = firstNumber - secondNumber;
            break;
        case ("Multiplication"):
            answer = firstNumber * secondNumber;
            break;
        default:
            return;
    }

    // build Bitmap array based on first number generated and split

    buildFirst = new Bitmap[splitFirst.length];

    for (int i = 0; i < splitFirst.length; i++) {
        for (int j = 0; j <= 9; j++) {
            if (j == splitFirst[i]) {

                // built from Bitmap array containing .png drawable resources

                buildFirst[i] = bitmapNumbers[j];

            }
        }
    }

    // code to generate new merged .png file based on built arrays and .png files

    Bitmap builtFirst = Bitmap.createBitmap(buildFirst[0].getWidth(), buildFirst[0].getHeight(), buildFirst[0].getConfig());
    Canvas canvas = new Canvas(builtFirst);
    newFile = buildFirst[0].toString();

    if (buildFirst.length > 1) {

        for (int i = 1; i < buildFirst.length; i++) {

            canvas.drawBitmap(buildFirst[i], 0, 0, null);
            canvas.drawBitmap(builtFirst, new Matrix(), null);
            newFile = newFile + buildFirst[i].toString();

        }
    }

    try {

        FileOutputStream out = new FileOutputStream("android.resource://com.app.numberup/drawable/" + newFile);
        builtFirst.compress(Bitmap.CompressFormat.PNG, 100, out);

        imageViewFirstNumber.setImageBitmap(builtFirst);

    } catch (Exception e) {

        Log.i("Error caught", e.getMessage());
        e.printStackTrace();

    }
/*
    buildSecond = new int[splitSecond.length];

    for (int i = 0; i <= splitSecond.length; i++) {
        for (int j = 0; j <= 9; j++) {
            if (j == splitSecond[i]) {

                buildSecond[i] = numbers[j];

            }
        }
    }*/

    // original code to display single numbers - worked
    //imageViewFirstNumber.setImageResource(numbers[i]);

    //imageViewSecondNumber.setImageResource(numbers[i]);

}

根据我所看到的,这段代码至少应该在可绘制目录中构建一个 .png 文件(如果那是生成的数字,则称为 72.png。我知道这一行 -

imageViewFirstNumber.setImageBitmap(builtFirst);

不会显示该文件。我不确定如何引用新生成的文件,但更大的问题是 newFile 不在可绘制文件夹中找到。

我也知道 -

if (buildFirst.length > 1) {

        for (int i = 1; i < buildFirst.length; i++) {

            canvas.drawBitmap(buildFirst[i], 0, 0, null);
            canvas.drawBitmap(builtFirst, new Matrix(), null);
            newFile = newFile + buildFirst[i].toString();

        }
    }

这只会将一个数字图像堆在另一个上面,我在想如果我使用buildFirst[i].getwidth * i 作为'left'参数会将图像放在最后一个的右侧,但我希望能够显示任何生成的图像,然后进行改进。目前,我只得到生成总和后显示的默认数字文件。

我的错误处理程序确实在这行代码中捕获了 FileNotFoundException -

Bitmap builtFirst = Bitmap.createBitmap(buildFirst[0].getWidth(), buildFirst[0].getHeight(), buildFirst[0].getConfig());

我认为这是由于 buildFirst[0] 的内容是 'android.graphics.Bitmap@1852540c' 与 [1] 中的类似内容(生成 2 位数字),这个过程不能用 .png 文件完成吗?如果是这种情况,我该如何合并它们,同时保持原始 .png 文件的透明属性?也许有更好的方法来填充原始 Bitmap 数组?

如何解决这个图像处理步骤?

【问题讨论】:

  • 你必须创建一个 Bitmap.create() 并创建画布,然后在画布上绘制 bitmapNumbers。例如,要生成数字 10,您必须创建具有双倍宽度的位图 bitmapNumbers 并绘制 bitmapNumbers[1] 并通过移动 x 位置 bitmapNumbers[0] 然后调用 imageView setDrawable()
  • 是 Bitmap.createBitmap 导致了异常。似乎该文件在我使用之前需要再次编码,有什么想法吗?
  • 你必须在内存中创建位图而不是在文件中
  • 您能否发布一些示例代码以使用数组中的解码 .png 作为答案来实现这一点,这是我第一次尝试任何类型的程序化图像处理。我看过的示例使用位图来调整 createBitmap 的大小,因此我不太确定您的意思,谢谢

标签: java android image-processing png bitmapfactory


【解决方案1】:

2天的反复试验终于找到了解决方案。

这里的问题是无需压缩文件或编写任何新文件或使用任何位图作为模板,也无需将新的可绘制对象作为资源引用(而只需应用创建的位图变量)。

Bitmap builtFirst = Bitmap.createBitmap(500 * splitFirst.length, 700, ARGB_8888);
    Canvas canvas = new Canvas(builtFirst);

    if (buildFirst.length > 1) {

        for (int i = 0; i < buildFirst.length; i++) {

            canvas.drawBitmap(buildFirst[i], 300 * i, 0, null);
            canvas.drawBitmap(builtFirst, new Matrix(), null);

        }
    }

imageViewFirstNumber.setImageBitmap(builtFirst);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-26
    • 1970-01-01
    • 2011-07-27
    • 2011-01-17
    相关资源
    最近更新 更多