0

I am rotating a bitmap using the the three shear method documented in these articles [1][2].

From about 0-90°, the quality is acceptable, but beyond that it gets progressively more distorted until it's unintelligible. Bitmap Image Rotations

Can anyone help me locate what is going wrong? There are a few calls to methods from the application Cinema 4D's API, but I believe the issue is coming from the math. Thank you!

This is my shear function:

def shear(angle,x,y):
    '''
    |1  -tan(/2) |  |1        0|  |1  -tan(/2) |
    |0      1     |  |sin()   1|  |0      1     |

    '''
    # shear 1
    tangent=math.tan(angle/2)
    new_x=round(x-y*tangent)
    new_y=y

    #shear 2
    new_y=round(new_x*math.sin(angle)+new_y)      #since there is no change in new_x according to the shear matrix

    #shear 3
    new_x=round(new_x-new_y*tangent)              #since there is no change in new_y according to the shear matrix

    return new_x,new_y

This is the code in the draw function:

cos = math.cos(self.rotation)
sin = math.sin(self.rotation)

# Define the width and height of the destination image
newWidth = round(abs(w*cos)+abs(h*sin))+1
newHeight = round(abs(h*cos)+abs(w*sin))+1

destBmp = c4d.bitmaps.BaseBitmap() #creates a new BaseBitmap instance for the destination image
destBmp.Init(newWidth,newHeight) #initializes the bitmap
destAlpha = destBmp.AddChannel(True, False) #adds an alpha channel

# Find the center of the source image for rotation
origCenterWidth  = round(((w+1)/2)-1)    #with respect to the source image
origCenterHeight = round(((h+1)/2)-1)    #with respect to the source image

# Find the center of the destination image
newCenterWidth  = round(((newWidth+1)/2)-1)  #with respect to the destination image
newCenterHeight = round(((newHeight)/2)-1)  #with respect to the destination image

for xP in range(w):
  for yP in range(h):
      destBmp.SetPixel(int(xP), int(yP), 0, 0, 255) #sets the destination bitmap's background color to blue

for i in range(h):
    for j in range(w):
        #co-ordinates of pixel with respect to the center of source image
        x = w-1-j-origCenterWidth
        y = h-1-i-origCenterHeight

        #Applying the Shear Transformation
        new_x,new_y = shear(self.rotation,x,y)

        #with rotation, the center will change so new_x and new_y will be the new center
        new_y = newCenterHeight-new_y
        new_x = newCenterWidth-new_x

        alphaValue = sourceBmp.GetAlphaPixel(alphaChannel, j, i) #gets the source image pixel's alpha
        col = sourceBmp.GetPixelDirect(j, i) #gets the source image pixel's color as a Color Vector
        destBmp.SetAlphaPixel(nBmpAlpha, int(new_x), int(new_y), alphaValue) #sets the destination image pixel's alpha
        destBmp.SetPixel(int(new_x), int(new_y), int(col.x), int(col.y), int(col.z)) #sets the destination image pixel's color

1 Answers1

0

I ran accross the same exact problem today. It seems as though there is something about the shearing method that is most optimal between 315 and 45 degrees, and noticeably degrades between 90 and 270. What I did to get around this was flip the image both on x, and y if the rotation is between 90 and 270, and then tack on an extra 180, to get it back into the desired range of rotation.

Here's basically what that was:

if (rotation > 90 && rotation < 270) {
    scale.x = scale.x * -1.0f;
    scale.y = scale.y * -1.0f;
    rotation += 180; 
    if (rotation >= 360) {
        rotation -= 360;
    }
}
Alex Waygood
  • 6,304
  • 3
  • 24
  • 46