• Welcome to Religious Forums, a friendly forum to discuss all religions in a friendly surrounding.

    Your voice is missing! You will need to register to get access to the following site features:
    • Reply to discussions and create your own threads.
    • Our modern chat room. No add-ons or extensions required, just login and start chatting!
    • Access to private conversations with other members.

    We hope to see you as a part of our community soon!

Fast Image Rotation

Onyx

Active Member
Premium Member
parrots.jpg


parrots_rotated.jpg


Thought I would share this routine from a 2D game engine I designed several years back while learning Java. It's based on the popular "rotozoom" demo effect, but works on individual images rather than tiling them all over the screen, and is a good example of how choosing the right algorithm can pay off in terms of performance.

Code:
  // rotate/scale a sprite
  public void rotateSprite(Bitmap dest, int xx, int yy, int angle, float scale)
  {
    int duCol = (int)(Trig.sin[(1023 - angle) & 1023] * scale * 256);
    int dvCol = (int)(Trig.sin[(1023 - (angle + 256)) & 1023] * scale * 256);
    int duRow = -dvCol;
    int dvRow = duCol;
    int ww = w / 2;
    int hh = h / 2;

    // origin
    int ox = xx + ww;
    int oy = yy + hh;
  
    // project new corners
    int x0 = xx - ox;
    int y0 = yy - oy;
    int x1 = xx + (w - 1) - ox;
    int y1 = yy - oy;
    int x2 = xx - ox;
    int y2 = yy + (h - 1) - oy;
    int x3 = xx + (w - 1) - ox;
    int y3 = yy + (h - 1) - oy;

    // rotate
    int newx0 = (int)(x0 * duCol + y0 * duRow) >> 8;
    int newy0 = (int)(x0 * dvCol + y0 * dvRow) >> 8;
    int newx1 = (int)(x1 * duCol + y1 * duRow) >> 8;
    int newy1 = (int)(x1 * dvCol + y1 * dvRow) >> 8;
    int newx2 = (int)(x2 * duCol + y2 * duRow) >> 8;
    int newy2 = (int)(x2 * dvCol + y2 * dvRow) >> 8;
    int newx3 = (int)(x3 * duCol + y3 * duRow) >> 8;
    int newy3 = (int)(x3 * dvCol + y3 * dvRow) >> 8;

    x0 = newx0 + xx;
    y0 = newy0 + yy;
    x1 = newx1 + xx;
    y1 = newy1 + yy;
    x2 = newx2 + xx;
    y2 = newy2 + yy;
    x3 = newx3 + xx;
    y3 = newy3 + yy;

    // find new bounding box
    int bx1 = Int.min(x0, Int.min(x1, Int.min(x2, x3)));
    int by1 = Int.min(y0, Int.min(y1, Int.min(y2, y3)));
    int bx2 = Int.max(x0, Int.max(x1, Int.max(x2, x3)));
    int by2 = Int.max(y0, Int.max(y1, Int.max(y2, y3)));
    int bw = (bx2 - bx1) / 2;
    int bh = (by2 - by1) / 2;

    // draw the sprite
    duCol = (int)(Trig.sin[angle & 1023] / scale * 256);
    dvCol = (int)(Trig.sin[(angle + 256) & 1023] / scale * 256);
    duRow = -dvCol;
    dvRow = duCol;

    int rowU = ww << 8;
    int rowV = hh << 8;
    rowU -= bw * duCol + bh * duRow;
    rowV -= bw * dvCol + bh * dvRow;

    int x, y;

    for(y = by1; y <= by2; y++)
    {
      int u = rowU;
      int v = rowV;

      rowU += duRow;
      rowV += dvRow;

      // skip rows that are out-of-bounds
      if(y < dest.ct || y > dest.cb)
        continue;

      int p = dest.row[y] + bx1;

      for(x = bx1; x <= bx2; x++, p++)
      {
        int uu = u >> 8;
        int vv = v >> 8;

        u += duCol;
        v += dvCol;

        if(uu < 0 || uu >= w || vv < 0 || vv >= h)
          continue;

        int c = data[uu + row[vv]];

        // skip columns that are out-of-bounds or transparent
        if(x < dest.cl || x > dest.cr || c == 0xFFFF00FF)
          continue;

        // plot the pixel
        dest.data[p] = c;
      }
    }
  }
 
Top