Как сгладить угол изображения в Android [Алгоритм не использует путь и т. д.]

Я спрашиваю о том, как применить алгоритм Xiaolin, чтобы иметь гладкий угол для изображения в Android. Я написал алгоритм, который перебирает пиксели и определяет, следует ли удалить этот пиксель или нет, чтобы угол для изображения также удалял пиксель, делая он прозрачный 255 для альфа-значения, но угол не гладкий, и я читаю об алгоритме Xiaolin для плавной линии, но, поскольку я нахожусь на среднем уровне программиста Java, я не знаю, как применить этот алгоритм >>> может ли кто-нибудь помочь мне о том, как применить этот алгоритм или предложить другой алгоритм и как его использовать, это мой код

int radius = Integer.parseInt(((EditText)MainActivity.this.findViewById(R.id.editTextRadius)).getText().toString());
    int xCenter ;
    int yCenter;
    Bitmap mutableBitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.h); 
    Bitmap drawaBitmap = mutableBitmap.copy(Bitmap.Config.ARGB_4444, true);


    for (int i = 0; i < radius; i++) {
        xCenter = radius;
        yCenter = radius;
        for (int j = 0; j < radius; j++) {
            if (Math.pow(i - xCenter , 2) + Math.pow(j - yCenter , 2) > Math.pow(radius, 2) ) {

                    drawaBitmap.setPixel(i, j,
                            Color.argb(255, 255, 255, 255));
            }

        }
        xCenter = radius;
        yCenter =  drawaBitmap.getHeight()-radius;
        for (int j = drawaBitmap.getHeight()-1; j > drawaBitmap.getHeight()-radius; j--) {
            if (Math.pow(i - xCenter , 2) + Math.pow(j - yCenter , 2) > Math.pow(radius, 2) ) {

                    drawaBitmap.setPixel(i, j,
                            Color.argb(255, 255, 255, 255));
            }

        }
    }
    for (int i = drawaBitmap.getWidth()-1; i > drawaBitmap.getWidth()-radius; i--) {
        xCenter = drawaBitmap.getWidth() - radius;
        yCenter =  radius;
        for (int j = 0; j < radius; j++) {
            if (Math.pow(i - xCenter , 2) + Math.pow(j - yCenter , 2) > Math.pow(radius, 2)) {

                    drawaBitmap.setPixel(i, j,
                            Color.argb(255, 255, 255, 255));
            }

        }
        xCenter = drawaBitmap.getWidth()-radius;
        yCenter =  drawaBitmap.getHeight()-radius;
        for (int j = drawaBitmap.getHeight()-1; j > drawaBitmap.getHeight()-radius; j--) {
            if (Math.pow(i - xCenter , 2) + Math.pow(j - yCenter , 2) > Math.pow(radius, 2) ) {

                    drawaBitmap.setPixel(i, j,
                            Color.argb(255, 255, 255, 255));
            }

        }
    }
    ((ImageView)this.findViewById(R.id.image)).setImageBitmap(drawaBitmap);

заранее спасибо


person BlackRoot    schedule 09.09.2013    source источник
comment
by making it transparent 255 for alpha value: 255 сделает пиксель непрозрачным, а не прозрачным. Вместо этого используйте 0.   -  person Vikram    schedule 09.09.2013
comment
когда я использую 0 для альфы, у меня есть черный пиксель, какой бы алгоритм ни работал хорошо, но не сглаженный угол, это проблема ›››› спасибо @user2558882 за эту информацию   -  person BlackRoot    schedule 09.09.2013
comment
также 255 прозрачный 0 непрозрачный попробуйте :)   -  person BlackRoot    schedule 09.09.2013
comment
also 255 is transparent 0 is opaque try it :) Неправда: Ссылка   -  person Vikram    schedule 09.09.2013
comment
Попробуйте добавить ((ImageView)this.findViewById(R.id.image)).setBackground(getResources().getColor(android.R.color.transparent)); перед ((ImageView)this.findViewById(R.id.image)).setImageBitmap(drawaBitmap);.   -  person Vikram    schedule 09.09.2013
comment
@user2558882 user2558882, но со значением 0 у меня есть черный пиксель со значением 255, пиксель становится прозрачным и исчезает, либо я написал код выше, либо нет   -  person BlackRoot    schedule 09.09.2013
comment
Позвольте мне объяснить вам это: Color.argb(255, 255, 255, 255): Первый аргумент: альфа — это 255 или FF, второй аргумент: красный — это 255 или FF, третий аргумент: зеленый — это 255 или FF, четвертый аргумент: синий — это 255 или FF. Это переводится как: 0x FF FF FF FF ==› непрозрачный white. Я думаю, что то, что вы называете transparent, на самом деле white пикселей. Попробуйте установить фон макета на черный. Вы увидите, что я имею в виду. Вы пытались сделать то, что я предложил в моем предыдущем комментарии? Попробуйте с Color.argb(0, 255, 255, 255));.   -  person Vikram    schedule 09.09.2013
comment
@ user2558882 да, я сделал то, что вы не хотите, и я изменил фон на черный, но я не получил белого пикселя. У меня есть прозрачный пиксель, который исчезает :) ›››› пожалуйста, убедитесь, что мы работаем с растровым изображением, а не Drawable   -  person BlackRoot    schedule 09.09.2013
comment
please be sure we work on Bitmap not Drawable : Итак, я проверил ваш код с моими предложениями, и он работает. Написал ответ ниже. Надеюсь, поможет.   -  person Vikram    schedule 09.09.2013


Ответы (2)


Итак, я попробовал ваш код, и он отлично работает для меня. Я добавил изменения, которые я предложил вам. Вот xml для ImageView:

<ImageView
    android:id="@+id/imageView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layerType="hardware"/>

Причина, по которой вы видите черные пиксели вместо прозрачных, может заключаться в том, что не установлен тип слоя. Исправленный код:

// hardcoded this value for testing purposes
int radius = 120;
int xCenter;
int yCenter;
Bitmap mutableBitmap = BitmapFactory.decodeResource(
                                  this.getResources(), R.drawable.h); 

// ARGB_8888 // ARGB_4444 has been deprecated
Bitmap drawaBitmap = mutableBitmap.copy(Bitmap.Config.ARGB_8888, true);

for (int i = 0; i < radius; i++) {
    xCenter = radius;
    yCenter = radius;

    for (int j = 0; j < radius; j++) {
    if (Math.pow(i - xCenter , 2) + Math.pow(j - yCenter , 2) > Math.pow(radius, 2) ) {

            drawaBitmap.setPixel(i, j,
                            Color.argb(0, 0, 0, 0));
        }

    }

    xCenter = radius;
    yCenter =  drawaBitmap.getHeight()-radius;

    for (int j = drawaBitmap.getHeight()-1; j > drawaBitmap.getHeight()-radius; j--) {

        if (Math.pow(i - xCenter , 2) + Math.pow(j - yCenter , 2) > Math.pow(radius, 2) ) {

            drawaBitmap.setPixel(i, j,
                            Color.argb(0, 0, 0, 0));
        }

    }
}
for (int i = drawaBitmap.getWidth()-1; i > drawaBitmap.getWidth()-radius; i--) {
    xCenter = drawaBitmap.getWidth() - radius;
    yCenter =  radius;

    for (int j = 0; j < radius; j++) {
        if (Math.pow(i - xCenter , 2) + Math.pow(j - yCenter , 2) > Math.pow(radius, 2)) {

        drawaBitmap.setPixel(i, j,
                            Color.argb(0, 0, 0, 0));
    }

}

xCenter = drawaBitmap.getWidth()-radius;
yCenter =  drawaBitmap.getHeight()-radius;

for (int j = drawaBitmap.getHeight()-1; j > drawaBitmap.getHeight()-radius; j--) {
    if (Math.pow(i - xCenter , 2) + Math.pow(j - yCenter , 2) > Math.pow(radius, 2) ) {

        drawaBitmap.setPixel(i, j,
                            Color.argb(0, 0, 0, 0));


    }

}

}

((ImageView) findViewById(R.id.image)).
    setBackgroundColor(getResources().getColor(android.R.color.transparent));

((ImageView) findViewById(R.id.imageView1)).setImageBitmap(drawaBitmap);

Кстати, вы также можете использовать Color.TRANSPARENT вместо Color.argb(0, 0, 0, 0).

Результат: оригинал и обработка

введите здесь описание изображения

person Vikram    schedule 09.09.2013
comment
<ImageView android:id="@+id/imageView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layerType="hardware"/> Я не использовал это, но я изменил ARGB_8888//ARGB_4444 и setPixel(i,j,Color.TRANSPARENT); он отлично работает для прозрачного Но все же это не моя проблема, моя проблема в том, чтобы иметь гладкий угол, но этот ответ хорош тем, что показывает мне новую информацию .. . Спасибо - person BlackRoot; 09.09.2013
comment
@BlackRoot Я думаю, что плавность углов будет зависеть от более высокого значения радиуса. Когда я использовал 120 для радиуса, углы были довольно гладкими. Каковы ваши критерии для гладких углов? - person Vikram; 09.09.2013
comment
никакая плавность не зависит от радиуса ››› есть возможность создать плавный угол, поместив рядом с последним полупрозрачный пиксель того же цвета или что-то в этом роде. Я прочитал алгоритм Сяолиня и алгоритм Брезенхэма, но у меня недостаточно опыта, чтобы применить какой-либо из этих алгоритмов.. вы можете мне помочь.... эти ссылки для алгоритма Алгоритм Xiaolin алгоритм Брезенхэма - person BlackRoot; 09.09.2013
comment
@BlackRoot посмотрю. Я добавил изображение в свой ответ для справки. - person Vikram; 09.09.2013
comment
Я вижу это изображение, но посмотри внимательно, оно не гладкое, смотри гладкое ЗДЕСЬ - person BlackRoot; 09.09.2013
comment
@pskink не пиксель один за другим, а помещая пиксель или 2 рядом с последним пикселем :: позвольте мне объяснить: мы делаем цикл внутри него, есть if close, когда предложение comse false ничего не происходит, но до того, как IF close станет ложным, мы помещаем пиксель наполовину прозрачный - person BlackRoot; 09.09.2013
comment
если вы хотите сгладить альфа-значения, создайте временную маску Bitmap с размером радиуса x радиуса, нарисуйте круг 0, 0, радиус и используйте его альфа-значение при размещении исходных пикселей растрового изображения - person pskink; 09.09.2013
comment
@pskink, можете ли вы объяснить больше и предоставить простой код, который я близко от вашего решения - person BlackRoot; 09.09.2013

это базовый материал для начала:

int radius = 10;
Bitmap b = Bitmap.createBitmap(radius, radius, Config.ARGB_8888);
Bitmap mask = Bitmap.createBitmap(2 * radius, 2 * radius, Config.ARGB_8888);
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
Canvas c;

// create mask
p.setColor(0xff000000);
c = new Canvas(mask);
c.drawCircle(radius, radius, radius, p);

// draw something on the original bitmap
// skip it if you have original bitmap drawn
c = new Canvas(b);
LinearGradient lg = new LinearGradient(0, 0, radius, radius, 0xffff0000, 0xff00ff00, TileMode.CLAMP);
p.setShader(lg);
c.drawRect(0, 0, radius, radius, p);
// end of skip

for (int x = 0; x < radius; x++) {
    for (int y = 0; y < radius; y++) {
        int maskPixel = mask.getPixel(x, y);
        if ((maskPixel & 0xff000000) != 0xff000000) {
            int bPixel = b.getPixel(x, y);
            bPixel &= 0xffffff;
            bPixel |= (maskPixel & 0xff000000);
            b.setPixel(x, y, bPixel);
        }
    }
}

try {
    OutputStream stream;
    stream = new FileOutputStream("/sdcard/image.png");
    b.compress(CompressFormat.PNG, 100, stream);
    stream = new FileOutputStream("/sdcard/mask.png");
    mask.compress(CompressFormat.PNG, 100, stream);
} catch (FileNotFoundException e) {
    e.printStackTrace();
}
person pskink    schedule 09.09.2013
comment
Большое спасибо, и я прошу прощения за это поздно, но мне действительно нужен алгоритм, изменяющий пиксели - пиксель за пикселем, и этот алгоритм написан на Java или подходит для Android. :) - person BlackRoot; 09.10.2013
comment
если быть точным, алгоритм изменяет исходные пиксели, а не создает маску, как вы, спасибо. - person BlackRoot; 09.10.2013