2017-12-18 17 views
0

画像をピクセル単位で90度回転させようとしていますが、計算できない問題があるようです...そして範囲外の配列 はここにあります私の試み画像を時計回りに90度回転する

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

は、 '*' – user463035818

+0

まだdstDataは= srcData [(幅* BPP)* J + 1 [iがj個の*幅* BPPを+]いくつかの限界を有している(数学及びC++で同じ)より高い-' 'よりも優先を有します - j]; –

+0

dstPitchを既に持っていますが、内側ループのためにあなたの条件でそれを使用していない理由はわかりません。 – Eddge

答えて

1

まず、次元を追跡するための画像記述子を構築しましょう。

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(); } 
}; 

ここでは、2つの画像の寸法を記録するために2つのImageDescriptorが必要です。元の画像が四角形でない限り、回転された画像の幅と高さが異なるため、ストライドになります。具体的には、回転イメージの幅はソースイメージの高さになります(またその逆もあります)。

const ImageDescriptor source(width, height, bpp); 
ImageDescriptor target(height, width, bpp); // note width/height swap 

変換を行う一般的な方法は、コピー先のピクセルをループしてソースピクセルをルックアップすることです。

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)]; 
    } 
    } 
} 

正しくなったら、不要な計算を排除することができます。最初の機会は、すべてのものがメモリの順序であるので、宛先イメージを辿るだけです。第2の機会は、ソース・オフセット計算をチャネル・ループから引き上げることである。最後に、bppが定数の場合は、最も内側のループをアンロールできます。

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

すばらしい答えをありがとう。しかし、私はまだスキャンライン画像を取得します。 –

+0

@ahmed andre: "スキャンライン画像"が何を意味するのか分かりません。 –

0

は、このいずれかを試してみてくださいされています

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]; 
     } 
    } 

とdstDataが乗されていない場合:

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

私はそれを試しましたが、私はスキャンラインを取得..正常に動作していないようです –

+0

forループをどのように繰り返すのですか? –

+0

@ahmedandreがforループを追加しました。 – ariaman5