2017-12-18 3 views
0

Ich versuche, ein Bild Pixel für Pixel um 90 Grad zu drehen, es scheint, es gibt ein mathematisches Problem, das ich nicht herausfinden konnte ... und Array außerhalb der Grenzen Ausnahme hier mein Versuch istDrehen Sie ein Bild um 90 Grad im Uhrzeigersinn

const unsigned char *srcData = source.getData(); 
unsigned char *dstData = new unsigned char[width * height * bpp]; 


size_t srcPitch = source.getRowSpan(); 
    size_t dstPitch = width * bpp; 

    for(int i=0; i<height; i++) 
    { 
     for(int j=0; j<width * bpp; j++) 
     { 
      rotatedData[(i * dstPitch) + j]= dstData[(height-i) * dstPitch + j]; 
     } 
    } 
+2

'*' hat höheren precendence als '-' (gleiche in Mathematik und C++) – user463035818

+0

hat noch einige Grenzen dstData = srcData [(Breite * bpp) [i j * Breite * bpp +] * j + 1 - j]; –

+0

Sie haben bereits dstPitch, nicht sicher, warum Sie das nicht in Ihrem Zustand für die innere for-Schleife verwenden. – Eddge

Antwort

1

Zuerst erstellen wir einen Image-Deskriptor, um die Dimensionen zu verfolgen.

struct ImageDescriptor { 
    std::size_t width; 
    std::size_t height; 
    std::size_t channels; 

    std::size_t stride() const { return width * channels; } 
    std::size_t offset(std::size_t row, std::size_t col, std::size_t chan) { 
    assert(0 <= row && row < height); 
    assert(0 <= col && col < width); 
    assert(0 <= chan && chan < channels); 
    return row*stride() + col*channels + chan; 
    // or, depending on your coordinate system ... 
    // return (height - row - 1)*stride() + col*channels + chan; 
    } 
    std::size_t size() const { return height * stride(); } 
}; 

Nun müssen wir zwei ImageDescriptors den Überblick über die Dimensionen unserer beiden Bilder zu halten. Beachten Sie, dass das gedrehte Bild eine andere Breite und Höhe (und damit ein größeres Schrittmaß) hat, wenn das ursprüngliche Bild nicht quadratisch ist. Insbesondere ist die Breite des gedrehten Bildes die Höhe des Quellbildes (und umgekehrt).

Eine gängige Methode für eine Transformation besteht darin, die Zielpixel zu durchlaufen und die Quellpixel nachzuschlagen.

unsigned char *rotated = new[target.size()]; 

for (std::size_t row = 0; row < target.height; ++row) { 
    for (std::size_t col = 0; col < target.width; ++col) { 
    for (std::size_t chan = 0; chan < target.channels; ++chan) { 
     rotated[target.offset(row, col, chan)] = 
      original[source.offset(col, row, chan)]; 
    } 
    } 
} 

Sobald Sie es richtig gemacht haben, können Sie arbeiten, um unnötige Berechnungen zu vermeiden. Die erste Möglichkeit besteht darin, einfach durch das Zielbild zu gehen, da alles in der Speicherreihenfolge ist. Die zweite Möglichkeit besteht darin, die Quellenoffsetberechnung aus der Kanalschleife herauszuheben. Schließlich, wenn Bpp eine Konstante ist, können Sie die innerste Schleife ausrollen.

unsigned char *p = rotated; 
for (std::size_t row = 0; row < target.height; ++row) { 
    for (std::size_t col = 0; col < target.width; ++col) { 
    const std::size_t base = source.offset(col, row, 0); 
    for (std::size_t chan = 0; chan < target.channels; ++chan) { 
     *p++ = original[base + chan]; 
    } 
    } 
} 
+0

Danke für diese großartige Antwort. Aber ich bekomme immer noch scanlined Bild –

+0

@ahmed andre: Ich weiß nicht, was Sie mit "scanlined Bild" meinen. –

0

Versuchen Sie dieses:

for (int j = 0; j<width * bpp; j++) 
    { 
     for (int i = 0 ; i<height; i++) 
     { 
      rotatedData[(height)*(dstPitch - j - 1) + i] = dstData[(i * dstPitch) + j]; 
     } 
    } 

und wenn dstData nicht im Quadrat:

//define rotatedData_height before. 
    rotatedData[(rotatedData_height)*(dstPitch - j - 1) + i] = dstData[(i * dstPitch) + j]; 
+0

Ich habe es versucht, aber ich bekomme Scanlines .. scheint es nicht richtig funktioniert –

+0

können Sie zeigen, wie iterieren Sie über die for-Schleifen? –

+0

@ahmedandre hinzugefügt die for-Schleifen. – ariaman5

Verwandte Themen