it-swarm.com.de

Skalieren und drehen Sie Bitmap mithilfe von Matrix in Android

Ich versuche, in einem einzigen Vorgang zu skalieren und zu rotieren, bevor die endgültige Bitmap erstellt wird, aber die preRotate post Concat scheint nicht zu funktionieren.

Bitmap bmp = ... original image ...

Matrix m = new Matrix()
m.setScale(x, y);
m.preRotate(degrees, (float) width / 2, (float) height / 2);

Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), m, true);

Es gilt nur die Skala und nicht die Rotation.

29
Taranfx

Bitte überprüfen Sie diesen Link für Details

http://www.anddev.org/resize_and_rotate_image_-_example-t621.html

Dies ist der Code 

public class Bitmaptest extends Activity {
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        LinearLayout linLayout = new LinearLayout(this);

        // load the origial BitMap (500 x 500 px)
        Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(),
               R.drawable.Android);

        int width = bitmapOrg.getWidth();
        int height = bitmapOrg.getHeight();
        int newWidth = 200;
        int newHeight = 200;

        // calculate the scale - in this case = 0.4f
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;

        // createa matrix for the manipulation
        Matrix matrix = new Matrix();
        // resize the bit map
        matrix.postScale(scaleWidth, scaleHeight);
        // rotate the Bitmap
        matrix.postRotate(45);

        // recreate the new Bitmap
        Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0,
                          newWidth, newHeight, matrix, true);

        // make a Drawable from Bitmap to allow to set the BitMap
        // to the ImageView, ImageButton or what ever
        BitmapDrawable bmd = new BitmapDrawable(resizedBitmap);

        ImageView imageView = new ImageView(this);

        // set the Drawable on the ImageView
        imageView.setImageDrawable(bmd);

        // center the Image
        imageView.setScaleType(ScaleType.CENTER);

        // add ImageView to the Layout
        linLayout.addView(imageView,
                new LinearLayout.LayoutParams(
                      LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT
                )
        );

        // set LinearLayout as ContentView
        setContentView(linLayout);
    }
}
38
Arslan

Die Antwort wurde gegeben, aber um es den Lesern klarer zu machen: 

1) Wenn Sie EINE Transformation in Ihrer Bitmap durchführen möchten, KÖNNEN Sie SET (setRotate, setScale usw.) verwenden. 

Beachten Sie jedoch, dass jeder Aufruf einer "set" -Methode andere Transformationen überschreibt. Es ist wie eine neue Matrix. Deshalb funktionierte die OP-Rotation nicht. Diese Anrufe werden nicht Zeile für Zeile ausgeführt. Es ist, als würden sie zur Laufzeit von der GPU ausgeführt, wenn die neue Bitmap gezeichnet wird. Es ist wie beim Auflösen Ihrer Matrix, GPU hat sie gedreht, aber dann eine skalierte neue erstellt, wobei die vorherige Matrix ignoriert wurde.

2) Wenn Sie mehr als eine Transformation durchführen möchten, MÜSSEN Sie "pre" - oder "post" -Methoden verwenden. 

Und was ist beispielsweise der Unterschied zwischen einem postRotate und einem preRotate? Nun, dieses Matrix-Mathematik-Zeug ist nicht meine Stärke, aber ich weiß, dass die Grafikkarten diese Transformationen mit Matrix-Multiplikation durchführen. Es scheint viel effizienter zu sein. Und soweit ich mich an die Schule erinnere, ist bei der Multiplikation von Matrizen die Reihenfolge IS wichtig. A X B! = B X A. Skalieren Sie eine Matrix und drehen Sie sie dann anders als drehen und skalieren Sie sie. 

BUUUUT: Wenn das Endergebnis auf dem Bildschirm das gleiche ist, müssen Programmierer auf hoher Ebene diese Unterschiede normalerweise nicht kennen. Die GPU tut. 

Nun, in seltenen Fällen, wenn Sie wirklich komplizierte Matrixoperationen ausführen und die Ergebnisse nicht Ihren Erwartungen entsprechen oder die Leistung schlecht ist und Sie diese Methoden gründlich verstehen müssen, um Ihren Code zu korrigieren, dann kann die Dokumentation von Android nicht viel sein trotzdem helfen. Stattdessen wäre ein gutes Buch mit linearer Algebra Ihr bester Freund. ;)

38
PFROLIM

Canvas enthält einen Matrixstapel, den Sie mit den folgenden Methoden verwenden können:

Canvas.save ()

Doc: /** * Speichert die aktuelle Matrix und den Clip auf einem privaten Stack . * 

* Nachfolgende Aufrufe zum Übersetzen, Skalieren, Drehen, Neigen, Concat oder ClipRect, * clipPath funktioniert wie gewohnt, aber wenn der Balancing-Aufruf an * restore () wird ausgeführt, diese Anrufe werden vergessen und die Einstellungen werden * existiert, bevor save () wiederhergestellt wird . * * @return Der Wert, der an restoreToCount () übergeben wird, um dieses save () */auszugleichen.

Canvas.restore ()

Dokument: /** * Dieser Anruf gleicht einen vorherigen Aufruf von save () aus und wird verwendet, um alle .__ zu entfernen. * Änderungen am Matrix-/Clip-Status seit dem letzten Speicheraufruf. Es ist * ein Fehler beim Aufruf von restore () war mehr als der Aufruf von save () . * /

beispiel: Eine benutzerdefinierte Ansicht (Android), die wie ein Drehknopf aussieht (z. B. Potentiometer)

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    viewX = getWidth();     //views width
    viewY = getHeight();    //views height
    setMeasuredDimension(widthMeasureSpec, heightMeasureSpec); //a must call for every custom view
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    double tempAngel = 3.6 * barValue;
    int deltaX = bitmap.getWidth() / 2;
    int deltaY = bitmap.getHeight() / 2;
    ...
    canvas.save();
    canvas.translate(viewX / 2, viewY / 2);             //translate drawing point to center
    canvas.rotate((float) tempAngel);                   //rotate matrix
    canvas.save();                                      //save matrix. your drawing point is still at (viewX / 2, viewY / 2)
    canvas.translate(deltaX * -1, deltaY * -1);         //translate drawing  point a bit up and left to draw the bitmap in the middle
    canvas.drawBitmap(bitmap, 0,0, bitmapPaint);   // draw bitmap to the tranlated point at 0,0
    canvas.restore();     //must calls...
    canvas.restore();
}
1
RickPat

Wenn Sie mit dem Thema OutOfMemory mit den obigen Antworten konfrontiert sind, verwenden Sie unten:

Bitmap MyFinalBitmap = Bitmap.createBitmap(CurrentBitmap, 0, 0,CurrentBitmap.getWidth()/2, CurrentBitmap.getHeight()/2,matrix, true);
0
Hiren Patel

Skalieren Sie den Bereich der Original-Bitmap mit der Matrix auf 50% und komprimieren Sie die Bitmap bis zu einer Größe von <200 KB . Komprimieren Sie die Bitmap in Android auf eine bestimmte Byte-Größe .

0
Anh Duy
Matrix rotateMatrix = new Matrix();
rotateMatrix.postRotate(rotation);
rotatedBitmap = Bitmap.createBitmap(loadedImage, 0, 0,loadedImage.getWidth(), loadedImage.getHeight(),rotateMatrix, false);
0
Saurabh Omer

Siehe den folgenden Code, scheint zu funktionieren. In Ihrem Code definieren Sie Matrix als m, aber als Matrix .

public class FourthActivity extends Activity {
private static final int WIDTH = 50;
private static final int HEIGHT = 50;
private static final int STRIDE = 64;  

private static int[] createColors() {
    int[] colors = new int[STRIDE * HEIGHT];
    for (int y = 0; y < HEIGHT; y++) {
        for (int x = 0; x < WIDTH; x++) {
            int r = x * 255 / (WIDTH - 1);
            int g = y * 255 / (HEIGHT - 1);
            int b = 255 - Math.min(r, g);
            int a = Math.max(r, g);
            colors[y * STRIDE + x] = (a << 24) | (r << 16) | (g << 8) | b;
        }
    }
    return colors;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main2);
    final ImageView view1 = (ImageView) findViewById(R.id.imageView1);

    int[] colors = createColors();
    final Bitmap bmp1 = Bitmap.createBitmap(colors, 0, STRIDE, WIDTH, HEIGHT,
    Bitmap.Config.ARGB_8888);
    view1.setImageBitmap(bmp1);
    Button button = (Button) findViewById(R.id.button1);
    button.setOnClickListener(new OnClickListener(){
        @Override
        public void onClick(View v) {   
            Matrix matrix = new Matrix();
            matrix.setScale(2, 2);
            matrix.preRotate(45, (float) WIDTH / 2, (float) HEIGHT / 2);

            Bitmap bmp2 = Bitmap.createBitmap(bmp1, 0, 0, 
      bmp1.getWidth(), bmp1.getHeight(), matrix, true);
            ImageView view2 = (ImageView) findViewById(R.id.imageView2);
            view2.setImageBitmap(bmp2);
        }
    });
}
}
0
Rajdeep Dua

Bei allen vorherigen Antworten wird davon ausgegangen, dass diese Änderung der Bitmap in einer Ansicht vorgenommen wird. In meinem Fall habe ich jedoch die Änderung vorgenommen, um gerettet zu werden. Ich dachte, ich würde es für diejenigen in einem ähnlichen Boot beantworten.

Es gibt zwei Möglichkeiten, um Übersetzungen zu erstellen. Unter dx befindet sich die Translation in der X-Achse und dy ist die Translation in der Y-Achse. Die anderen Variablen sollten selbsterklärend sein.

1 - Übersetzung innerhalb des Bildes (ohne Drehung)

val newBitmap = Bitmap.createBitmap(originalBitmap, dx, dy, newWidth, newHeight, matrix, false)

2 - komplexe Matrix

 matrix.postTranslate(dx, dy)

 val newBitmap = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888)

 val canvas = Canvas(newBitmap)
 canvas.drawBitmap(originalBitmap, matrix, null)
0
drspaceboo