Как я могу масштабировать изображение без размытия? - PullRequest
9 голосов
/ 05 апреля 2011

Я пытаюсь масштабировать крошечное изображение (размером примерно 20x40 пикселей) в произвольно большое изображение. Я делаю масштабирование, устанавливая свойство ImageView.scaleType, но, хотя оно масштабирует изображение, оно исчезает с одного исходного цвета пикселя на другой, создавая большую размытую версию изображения.

Вот некоторый контекст для вопроса. Я пытаюсь создать старую 16-битную игру для Android. Я хочу сохранить спрайты и т. Д. В виде крошечных файлов, а затем масштабировать их больше в зависимости от размера экрана пользователя. Таким образом, мне не нужно создавать тонну разных изображений разных размеров для каждого спрайта. Сейчас я просто работаю над проверкой концепции, поэтому я пытаюсь масштабировать крошечный файл изображения 20x40 до размера всего экрана.

* редактировать: я понял, как использовать рекомендованный метод Reflog. Тем не менее, он все еще вызывает некоторое затухание, намного меньше, чем алгоритм по умолчанию.

* edit2: Понял! Мне пришлось отключить сглаживание

* edit3: это таинственным образом перестало работать для меня, и я нашел другое место, где дизеринг / автоматическое масштабирование необходимо было отключить. Добавлены опции строки.

@Override
protected void onDraw(Canvas canvas) {
    Paint paint = new Paint();
    paint.setDither(false);
    paint.setAntiAlias(false);

    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inDither = false;
    options.inScaled = false;

    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.tinyimg, options);
    canvas.drawBitmap(bitmap, null, new RectF(getLeft(), getTop(), getRight()/2, getBottom()/2), paint);
}

Ответы [ 2 ]

7 голосов
/ 05 апреля 2011

Используйте:

paint.setDither(false);
g.drawBitmap(img, src, dst, paint);

, чтобы использовать масштабирование NN, это уменьшит размытие, но также уменьшит качество масштабирования.

1 голос
/ 29 июня 2013

Может быть, этот код поможет вам:

/**
 * @param bitmap Bitmap original
 * @param finWid width of the new Bitmap (width of the cut)
 * @param finHei height of the new Bitmap (height of the cut)
 * @param angulo angle of rotation in degrees
 * @param sx scale X
 * @param sy scale Y
 * @param tx Translate X
 * @param ty Translate Y
 * @param config {@link Config} of the new Bitmap
 * @return {@link Bitmap} transformed
 */
public Bitmap createTransPixBitmap(Bitmap bitmap, int finWid, int finHei, float  angulo, float sx, float sy, float tx, float ty, Config config){

    return Bitmap.createBitmap(createTransPixArray(bitmap, bitmap.getWidth(), bitmap.getHeight(), finWid, finHei, angulo, sx, sy, tx, ty), finWid, finHei, config);

}

public int[] createTransPixArray(Bitmap bitmap, int width, int height, int finWid, int finHei, float angulo, float sx, float sy, float tx, float ty){

    float scaWid = width*sx;
    float scaHei = height*sy;

    int[] ori = new int[width*height];
    bitmap.getPixels(ori, 0, width, 0, 0, width, height);

    bitmap.recycle();
    bitmap = null;
    System.gc();

    return transformPix(ori, width, height, scaWid, scaHei, finWid, finHei, angulo, tx, ty);
}

/**
 * Core function for apply scale, translate and rotation (cut the image if you want too)
 * @param ori original color array
 * @param wid original width
 * @param hei original height
 * @param scaWid scaled original width
 * @param scaHei scaled original height
 * @param finWid width of the new Bitmap
 * @param finHei height of the new Bitmap
 * @param angulo rotation in degrees
 * @param tx Translate X
 * @param ty Translate Y
 * @return int[] of colors
 */
private int[] transformPix(int[] ori, int wid, int hei, float scaWid, float scaHei, int finWid, int finHei, float angulo, float tx, float ty){

    int[] fin = new int[finWid*finHei];

    double sin = Math.sin(Math.toRadians(angulo));
    double cos = Math.cos(Math.toRadians(angulo));

    int dx = (int)((scaWid-finWid)/2);
    int dy = (int)((scaHei-finHei)/2);

    /* No se como explicar esto, solo puedo decir que el proceso de escalado es en sentido inverso
     * escala, rota, translada y corta, todo al mismo tiempo :D
     */
    for(int y = 0; y < finHei; y++){
        for(int x = 0; x < finWid; x++){
            int tempX = (int)Math.floor(((x+dx-((float)scaWid/2))*((float)wid/scaWid))+0.5f-tx);
            int tempY = (int)Math.floor(((y+dy-((float)scaHei/2))*((float)hei/scaHei))+0.5f-ty);

            int tempRX = (int)Math.floor(((cos*(float)tempX)+(sin*(float)tempY))+0.5f+((float)wid/2));
            int tempRY = (int)Math.floor(((cos*(float)tempY)-(sin*(float)tempX))+0.5f+((float)hei/2));

            if((tempRX >= 0 && tempRX < wid) && (tempRY >= 0 && tempRY < hei))
                fin[x+(y*finWid)] = ori[tempRX+(tempRY*wid)];   
        }
    }

    ori = null;
    return fin;
}

Эта функция просто масштабирует массив цветов (если вам не нужны дополнительные функции):

private int[] scale(int[] ori, int wid, int hei, int finWid, int finHei){

    int[] fin = new int[finWid*finHei];

    for(int y = 0; y < finHei; y++){
        for(int x = 0; x < finWid; x++){
            int temp = (int)(x*(wid/finWid))+((int)(y*(hei/finHei))*wid);
            fin[x+(y*finWid)] = ori[temp];
        }
    }

    return fin;
}

Надеюсь, это будет полезно, и я с удовольствием буду благодарен за несколько советов по улучшению этого кода.

...