2012-10-12 1 views
1

좋아 나는이 좀 더 명확하게하기 위해 :회전 imageData의는

내 코드는 정사각형 이미지 노력하고 있지만, 직사각형 이미지 아무것도 없다 생각. imageData.width와 imageData.height는 여전히 동일하므로 변경할 수 없기 때문에 생각합니다.

내가 어떻게 작동하는지 알 수 있습니까?

var canvas = document.getElementById("canvas0calc"); 
var ctx = canvas.getContext('2d'); 

var objImageData = ctx.getImageData(0, 0, canvas.width, canvas.height); 

// swap canvas size 
var temp = canvas.width; 
canvas.width = canvas.height; 
canvas.height = temp; 


//create new Array for Data 
var newImageData = new Array(objImageData.height); 
for (var k = 0; k < newImageData.length; k++) { 
    newImageData[k] = new Array(objImageData.width); 
} 

//the actual matrix-rotate algorithm which is working perfectly 
for (var i = 0; i < objImageData.height; i++) { 
    for (var j = 0; j < objImageData.width; j++) { 
     newImageData[i][j] = [objImageData.data[((i*(objImageData.width*4)) + ((objImageData.width - j - 1)*4))], objImageData.data[((i*(objImageData.width*4)) + ((objImageData.width - j - 1)*4)) + 1],objImageData.data[((i*(objImageData.width*4)) + ((objImageData.width - j - 1)*4)) + 2],objImageData.data[((i*(objImageData.width*4)) + ((objImageData.width - j - 1)*4)) + 3]]; 
    } 
} 

var resultArray = new Array(objImageData.width * objImageData.height * 4); 
var count = 0; 
for (var y = 0; y < newImageData.length; y++) { 
    for (var x = 0; x < newImageData[0].length; x++) { 
     for (var z = 0; z < 4; z++) { 
      resultArray[count++] = newImageData[x][y][z]; 
     } 
    } 
} 

for (var u = 0; u < objImageData.data.length; u++) { 
    objImageData.data[u] = resultArray[u]; 
} 

ctx.putImageData(objImageData, 0, 0); 
+0

jsFiddle이 있습니까? – alex

+0

회전 알고리즘의 구현을 보여줄 수 있습니까? – Philipp

+0

나는 질문을 업데이트했다, 나는 그것이 더 분명해야한다고 생각한다 : D – kaljak

답변

3

너비와 높이 값을 바꾸는 것 이상의 것이 있습니다! 사각형을 가져 와서 45도 회전하면 너비와 높이를 바꿀 필요가 없습니다. 이미지는 실제로는 이전과 같은 넓이와 높이로 sqrt (2) 배가됩니다 (대각선 모서리에서 다른 구석으로의 길이는 sqrt입니다. (1^2 + 1^2)에 인접한 모서리 사이의 길이를 곱한 것입니다. 요점은 간단한 스왑보다 조금 더 나은 새로운 이미지 크기를 계산해야한다는 것입니다.

이미지 회전 루틴을 찾을 수 없습니다. 10 년 또는 15 년 전과 마찬가지로 손쉽게 가까운 곳에서 그물을 볼 수 있습니다. 이제 우리가 가지고있는 모든 빠른 그래픽 하드웨어가 많은 사람들의 필요를 충족시켜줍니다.

90 °, 180 ° 또는 270 ° - 나는 확실히 할 수는 없지만 폭과 높이의 단순한 교환으로 의심해 봅니다. 여기 기사 : http://www.codeproject.com/Articles/21446/Fast-Image-Rotation-For-NET-Compact-Framework

그러나 임의의 각도로 회전하려면 다음을 읽으십시오.

나는 그것이 C이고 자바 스크립트를 사용하고 있다는 것을 알았지 만, 회전 수학은 단지 동일하고, 필요에 따라 equiv javascript 함수를 무시/사용합니다.

// RotateMemoryDC rotates a memory DC and returns the rotated DC as well as its dimensions 
HBITMAP RotateMemoryDC(HBITMAP hBmpSrc, float angleDeg) 
{ 
    HBITMAP hBmpDst; 
    float x1, x2, x3, x4, y1, y2, y3, y4, cA, sA; 
    float CtX, CtY, orgX, orgY, divisor; 
    int OfX, OfY; 
    int stepX, stepY; 
    int iorgX, iorgY; 
    RECT rt; 
    pBGR src, dst, dstLine; 
    BITMAPINFO bi; 
    // my edits 
    BITMAP bm; 
    int SrcX, SrcY, dstX, dstY;  // were input variables, with the & symbol in front of them (input/output vars)\ 

    HDC hdcSrc, hdcDst, hdcScreen; 

    HBITMAP oldDstBmp, oldSrcBmp; 

    GetObject(hBmpSrc, sizeof(bm), &bm); 
    SrcX = bm.bmWidth; 
    SrcY = bm.bmHeight; 

    // Rotate the bitmap around the center 
    CtX = ((float) SrcX)/2; 
    CtY = ((float) SrcY)/2; 

    // First, calculate the destination positions for the four courners to get dstX and dstY 
    float angleRad = angleDeg * 3.1415926/180.0; 
    cA = (float) cos(angleRad); 
    sA = (float) sin(angleRad); 

    x1 = CtX + (-CtX) * cA - (-CtY) * sA; 
    x2 = CtX + (SrcX - CtX) * cA - (-CtY) * sA; 
    x3 = CtX + (SrcX - CtX) * cA - (SrcY - CtY) * sA; 
    x4 = CtX + (-CtX) * cA - (SrcY - CtY) * sA; 

    y1 = CtY + (-CtY) * cA + (-CtX) * sA; 
    y2 = CtY + (SrcY - CtY) * cA + (-CtX) * sA; 
    y3 = CtY + (SrcY - CtY) * cA + (SrcX - CtX) * sA; 
    y4 = CtY + (-CtY) * cA + (SrcX - CtX) * sA; 

    OfX = ((int) floor(min4(x1, x2, x3, x4))); 
    OfY = ((int) floor(min4(y1, y2, y3, y4))); 

    dstX = ((int) ceil(max4(x1, x2, x3, x4))) - OfX; 
    dstY = ((int) ceil(max4(y1, y2, y3, y4))) - OfY; 

    // Create the new memory DC 
    hdcScreen = GetDC(NULL); 
    hdcDst = CreateCompatibleDC(hdcScreen); 
    hdcSrc = CreateCompatibleDC(hdcScreen); 
    hBmpDst = CreateCompatibleBitmap(hdcScreen, dstX, dstY); 
    oldDstBmp = (HBITMAP)SelectObject(hdcDst, hBmpDst); 
    oldSrcBmp = (HBITMAP)SelectObject(hdcSrc, hBmpSrc); 

    // Fill the new memory DC with the current Window color 
    rt.left = 0; 
    rt.top = 0; 
    rt.right = dstX; 
    rt.bottom = dstY; 
    HBRUSH redBrush = CreateSolidBrush(RGB(255,0,0)); 

    FillRect(hdcDst, &rt, redBrush); 
    DeleteObject(redBrush); 

    // Get the bitmap bits for the source and destination 
    src = MyGetDibBits(hdcSrc, hBmpSrc, SrcX, SrcY); 
    dst = MyGetDibBits(hdcDst, hBmpDst, dstX, dstY); 

    dstLine = dst; 
    divisor = cA*cA + sA*sA; 
    // Step through the destination bitmap 
    for (stepY = 0; stepY < dstY; stepY++) 
    { 
     for (stepX = 0; stepX < dstX; stepX++) 
     { 
      // Calculate the source coordinate 
      orgX = (cA * (((float) stepX + OfX) + CtX * (cA - 1)) + sA * (((float) stepY + OfY) + CtY * (sA - 1)))/divisor; 
      orgY = CtY + (CtX - ((float) stepX + OfX)) * sA + cA *(((float) stepY + OfY) - CtY + (CtY - CtX) * sA); 
      iorgX = (int) orgX; 
      iorgY = (int) orgY; 
      if ((iorgX >= 0) && (iorgY >= 0) && (iorgX < SrcX) && (iorgY < SrcY)) 
      { 
       // Inside the source bitmap -> copy the bits 
       dstLine[dstX - stepX - 1] = src[iorgX + iorgY * SrcX]; 
      } 
      else 
      { 
       // Outside the source -> set the color to light grey 
       // dstLine[dstX - stepX - 1].b = 240; 
       // dstLine[dstX - stepX - 1].g = 20; 
       // dstLine[dstX - stepX - 1].r = 240; 
      } 
     } 
     dstLine = dstLine + dstX; 
    } 

    // Set the new Bitmap 
    bi.bmiHeader.biSize = sizeof(bi.bmiHeader); 
    bi.bmiHeader.biWidth = dstX; 
    bi.bmiHeader.biHeight = dstY; 
    bi.bmiHeader.biPlanes = 1; 
    bi.bmiHeader.biBitCount = 32; 
    bi.bmiHeader.biCompression = BI_RGB; 
    bi.bmiHeader.biSizeImage = dstX * 4 * dstY; 
    bi.bmiHeader.biClrUsed = 0; 
    bi.bmiHeader.biClrImportant = 0; 
    SetDIBits(hdcDst, hBmpDst, 0, dstY, dst, &bi, DIB_RGB_COLORS); 

    // Free the color arrays 
    free(src); 
    free(dst); 
    SelectObject(hdcSrc, oldSrcBmp); 
    SelectObject(hdcDst, oldDstBmp); 
    ReleaseDC(NULL, hdcScreen); 
    DeleteDC(hdcSrc); 
    DeleteDC(hdcDst); 
    return hBmpDst; 
}