Roteer bitmappixels

Ik probeer een bitmap te roteren waarbij de pixels worden opgeslagen in een array int pixels [] . Ik kreeg de volgende methode:

public void rotate(double angle) {
    double radians = Math.toRadians(angle);
    double cos, sin;
    cos = Math.cos(radians);
    sin = Math.sin(radians);
    int[] pixels2 = pixels;
    for (int x = 0; x < width; x++)
        for (int y = 0; y < height; y++) {
            int centerx = this.width/2, centery = this.height/2;
            int m = x - centerx;
            int n = y - centery;
            int j = (int) (m * cos + n * sin);
            int k = (int) (n * cos - m * sin);
            j += centerx;
            k += centery;
            if (!((j < 0) || (j > this.width - 1) || (k < 0) || (k > this.height - 1)))

                try {
                    pixels2[(x * this.width + y)] = pixels[(k * this.width + j)];
                } catch (Exception e) {
                    e.printStackTrace();
                }
        }
    pixels = pixels2;

}

Maar het geeft me gewoon gekke resultaten. Weet iemand waar de fout zit?

0

2 antwoord

De lijn

int[] pixels2 = pixels;

wordt verondersteld de array te kopiëren, maar u kopieert gewoon de verwijzing ernaar. Gebruik pixels.clone() . In feite heeft u alleen een nieuwe, lege array nodig, dus nieuwe int [pixels.lenght] is voldoende. Uiteindelijk heb je System.arraycopy nodig om de nieuwe inhoud naar de oude array te kopiëren.

Er zijn nog andere problemen in uw code: u vermengt rijen en kolommen. Sommige uitdrukkingen worden geschreven alsof de afbeelding rij per rij wordt opgeslagen, andere alsof het kolom voor kolom is. Als het rij voor rij (mijn aanname) is, heeft dit geen zin: x * width + y . Het moet y * width + x lezen - u slaat rijen y naar beneden en vervolgens kolommen x naar rechts. Al met al heb ik deze code die goed werkt:

import static java.lang.System.arraycopy;

public class Test
{
  private final int width = 5, height = 5;
  private int[] pixels = {0,0,1,0,0,
                          0,0,1,0,0,
                          0,0,1,0,0,
                          0,0,1,0,0,
                          0,0,1,0,0};

  public Test rotate(double angle) {
    final double radians = Math.toRadians(angle),
    cos = Math.cos(radians), sin = Math.sin(radians);
    final int[] pixels2 = new int[pixels.length];
    for (int x = 0; x < width; x++)
      for (int y = 0; y < height; y++) {
        final int
          centerx = this.width/2, centery = this.height/2,
          m = x - centerx,
          n = y - centery,
          j = ((int) (m * cos + n * sin)) + centerx,
          k = ((int) (n * cos - m * sin)) + centery;
        if (j >= 0 && j < width && k >= 0 && k < this.height)
          pixels2[(y * width + x)] = pixels[(k * width + j)];
      }
    arraycopy(pixels2, 0, pixels, 0, pixels.length);
    return this;
  }
  public Test print() {
    for (int y = 0; y < height; y++) {
      for (int x = 0; x < width; x++)
        System.out.print(pixels[width*y + x]);
      System.out.println();
    }
    System.out.println();
    return this;
  }
  public static void main(String[] args) {
    new Test().print().rotate(-45).print();
  }
}
2
toegevoegd
Merk op dat clone() een ondiepe kopie maakt, dat wil zeggen dat het de inhoud van de array niet zal klonen. Met int maakt het niet zoveel uit, maar over het algemeen is het een beter idee om Arrays.copyOf te gebruiken als in int [] pixels2 = Arrays.copyOf (pixels, pixels.lengte)
toegevoegd de auteur Aleks G, de bron
copyOf maakt ook een ondiepe kopie. In feite bestaat er geen standaardmechanisme om een ​​object diep te kopiëren.
toegevoegd de auteur Marko Topolnik, de bron
public void render(float nx, float ny, float nz, float size, float rotate) {

    int wid = (int) ((width - nz) * size);

    int hgt = (int) ((height - nz) * size);

    if (wid < 0 || hgt < 0) {
        wid = 0;
        hgt = 0;
    }

    for (int x = 0; x < wid; x++) {
        for (int y = 0; y < hgt; y++) {
            double simple = Math.PI;
            int xp = (int) (nx +

            Math.cos(rotate) * ((x/simple) - (wid/simple)/2) + Math
                    .cos(rotate + Math.PI/2)
                    * ((y/simple) - (hgt/simple)/2));
            int yp = (int) (ny + Math.sin(rotate)
                    * ((x/simple) - (wid/simple)/2) + Math.sin(rotate
                    + Math.PI/2)
                    * ((y/simple) - (hgt/simple)/2));

            if (xp + width < 0 || yp + height < 0 || xp >= Main.width
                    || yp >= Main.height) {
                break;
            }
            if (xp < 0
                    || yp < 0
                    || pixels[(width/wid) * x + ((height/hgt) * y)
                            * width] == 0xFFFF00DC) {
                continue;
            }
            Main.pixels[xp + yp * Main.width] = pixels[(width/wid) * x
                    + ((height/hgt) * y) * width];
        }
    }
}

Dit is alleen een nieuw te roteren voor mij, maar het proces hiervan is dat van een normale rotatie. Er moet nog veel worden hersteld - het is inefficiënt en traag. Maar in een klein programma werkt deze code. Ik plaats dit zodat je het kunt nemen en het kunt verbeteren. :)

0
toegevoegd