さて、YUV画像回転の話も
4回目に突入した。
Visual Studio Expressの
カラースキーマ
今使っているのはC#ではいいが、C++の表示だとコードが読みにくいか...
前回に続き、残りのメンバ関数の説明である。
// 回転角度とオリジナル画像のサイズを指定する
void YuvImageRotate::SetYuvRawData(int orient, unsigned char *src_data, int width, int height)
{
unsigned char *pNew_src = NULL;
//check the image size, even or odd
if ((width % 2 == 0) && (height % 2 == 0)) {
pNew_src = new unsigned char[width * height + (width / 2 * height / 2) * 2];
if (pNew_src != NULL) {
memcpy(pNew_src, src_data, width*height + (width / 2 * height / 2) * 2);
m_pSrc = pNew_src;
m_SrcWidth = width;
m_SrcHeight = height;
}
}
else {
if (width % 2 && height % 2) {
// odd x odd
m_SrcWidth = width + 1;
m_SrcHeight = height + 1;
int NewSize = m_SrcWidth * m_SrcHeight + (m_SrcWidth / 2 * m_SrcHeight / 2) * 2;
pNew_src = new unsigned char[NewSize];
if (pNew_src != NULL) {
// Y成分
for (int i = 0; i < height; i++) {
memcpy(&pNew_src[i * m_SrcWidth], &src_data[i * width], width);
memcpy(&pNew_src[i * m_SrcWidth + width], &src_data[i * width + width - 1], sizeof(unsigned char));
}
memcpy(&pNew_src[height * m_SrcWidth], &pNew_src[(height - 1) * m_SrcWidth], m_SrcWidth);
}
}
else if (width % 2) {
// odd x even
m_SrcWidth = width + 1;
m_SrcHeight = height;
int NewSize = m_SrcWidth * m_SrcHeight + (m_SrcWidth / 2 * m_SrcHeight / 2) * 2;
pNew_src = new unsigned char[NewSize];
if (pNew_src != NULL) {
// Y成分
for (int i = 0; i < height; i++) {
memcpy(&pNew_src[i * m_SrcWidth], &src_data[i * width], width);
memcpy(&pNew_src[i * m_SrcWidth + width], &src_data[i * width + width - 1], sizeof(unsigned char));
}
}
}
else {
//even x odd
m_SrcWidth = width;
m_SrcHeight = height + 1;
int NewSize = m_SrcWidth * m_SrcHeight + (m_SrcWidth / 2 * m_SrcHeight / 2) * 2;
pNew_src = new unsigned char[NewSize];
if (pNew_src != NULL) {
// Y成分
for (int i = 0; i < height; i++) {
memcpy(&pNew_src[i * m_SrcWidth], &src_data[i * width], width);
}
memcpy(&pNew_src[height * m_SrcWidth], &pNew_src[(height - 1) * m_SrcWidth], m_SrcWidth);
}
}
if (pNew_src != NULL) {
// U成分
memcpy(&pNew_src[m_SrcWidth * m_SrcHeight], &src_data[width * height], m_SrcWidth / 2 * m_SrcHeight / 2);
// V成分
memcpy(&pNew_src[m_SrcWidth * m_SrcHeight + m_SrcWidth / 2 * m_SrcHeight / 2],
&src_data[width * height + m_SrcWidth / 2 * m_SrcHeight / 2], m_SrcWidth / 2 * m_SrcHeight / 2);
m_pSrc = pNew_src;
}
}
if (m_pSrc != NULL) {
// 回転情報を取得し、メンバ変数に格納
getRotateInfo(orient);
if (m_bHorizon) {
// 水平反転を実行
invokeReverse();
}
// 回転を実行
invokeRotate();
}
return;
}
ここでのポイントは、与えられた画像のサイズが、都合よく 偶数 × 偶数 であれば
問題ないが、そうでない場合もあるということである。
偶数サイズでは、U成分、V成分の割合がY成分の半分でこのようになる。
YYYY
YYYY
UUVV
奇数サイズでは、U成分、V成分の割合がY成分の半分だとすると
YYY YYY
YYY あるいは YYY
UUVV UV
切り上げなのか、切り捨てとなるのかで、扱いには少々都合が悪い。
今回は切り上げ方式として、奇数 × 偶数 あるいは 偶数 × 奇数の場合は
奇数の辺を無理やり偶数にするよう拡張を行っている。
最後のデータをコピーしてちょうど、1ピクセル分増加させることで
すべての画像を 偶数 × 偶数 として扱えるようにしている。
さらに残りのメンバ関数の説明は次回に続く(最終回)
今日の名言
幸不幸は、財産、地位、職業などで決まるものではない。何を幸福と考え、
また不幸と考えるか - その考え方が、幸不幸の分かれ目なのである。
例えば、同じ場所で同じ仕事をしている人がいるとする。二人は、だいたい同じ
財産と地位を持っているにもかかわらず、一方は不幸で他方は幸福だという
ことがよくある。なぜか?気の持ち方が違うからだ。
デール・カーネギー
事の成り行きを運命の女神のせいにするのは大きな心得違いだ。
彼女自身は全く無力で「分別」の神に支配されているからだ。
ジョン・ドライデン
上着は布地に合わせて裁断すべきだ。同様に、変化する環境に対して
自分自身を合わせるようにした方がよい。
ウィリアム・R・イング
いつ機会をつかむべきかということの次に、人生で最も重要なことは、
いつ先立って利益をつかむかである。
ベンジャミン・ディズレーリ