2017-12-06 11 views
2

170×200ピクセルの画像に従って、元画像(JPGファイル)を縮小する関数を作成していました。元のJPGイメージをTImage(Image1、400×400pxの固定サイズ、アスペクト比に合わせて伸ばす)にロードした後、ユーザーはコピーする領域を設定する選択矩形を作成し、イメージをコピーしますコピー先のTImage(Image2)にCopyRect()を使用します。CopyRectを使用して大きな画像を小さなキャンバスにコピーするときの色が間違っています

void __fastcall TSizePhotoForm::Button3Click(TObject *Sender) 
{ 
    float scale, base = 400.0f; 
    TRect crect; // copy rect 

    Image2->Width = 170; 
    Image2->Height = 200; 

    Image2->Canvas->CopyMode = cmSrcCopy; 
    TJPEGImage *img = new TJPEGImage(); 
    img->LoadFromFile(fname); 
    Graphics::TBitmap *bmp = new Graphics::TBitmap; 
    bmp->Assign(img); 
    scale = (float)img->Width/base; 
    crect.Left = srect.Left * scale; // srect = source rect 
    crect.Top = srect.Top * scale; 
    crect.Right = crect.Left + (srect.Width() * scale); 
    crect.Bottom = crect.Top + (srect.Height() * scale); 
    Image2->Canvas->CopyRect(TRect(0, 0, w, h), bmp->Canvas, crect); 
    delete img; 
    delete bmp; 
} 

問題は、得られる画像の色が適切ではない、であり、そしてIは、ソース画像が大きいほど、得られる画像の色ずれがより悪いことを観察しました。ここで

は、結果のスクリーンショットです: Color shifted

間違って何任意のアイデアとどのように私はこの色ずれの問題を取り除くのですか?前もって感謝します。

+0

'CopyRect'がはるかに優れたスケールを変更することで良くない(全体のキャンバスをカバーしていない場合がありますが、ターゲットのサイズとそれのための一時的なビットマップを必要とするかもしれない)の代わりに' StretchDraw'です。問題は、ターゲットピクセル形式でも、8または8ビットの代わりに24または32ビットに設定しようとしている可能性があります。 – Spektre

+0

あなたの提案をお寄せいただきありがとうございます。ソースイメージの一部をデスティネーションにコピーする必要があります。ストレッチドローはソースイメージ全体をコピーし、デスティネーションイメージ上で縮小/ストレッチします。また、TImageやTBitmapのピクセル形式をどのように変更できるかわからないので、ピクセル形式に関連するこれらのオブジェクトのメソッドやプロパティを見つけることができませんでした。 –

+0

私は私の答えあなたの答えのための – Spektre

答えて

1

いいえ私はあなたの問題を作り直そうとしました。あなたのImage2ピクセルフォーマットが見えると思われます。私はあなたがpf8bitを設定していると仮定し、jpgpf24bitですので、緑色に切り捨てられます...また、コピーの矩形は不安定で、StretchDrawは非常にスムーズです。ここで比較:

とあなたの更新されたコード(Image1が右にズーム画像イメージとImage2を左源であると仮定):

preview

あなたがStretchDrawが最善ではありません見ることができるように彼らが同じスケーリング技術を使用しない理由を確かめてください。

int h,w; 
float scale, base = 400.0f; 
TRect crect; // copy rect 
TRect srect; // I assume some mouse selected rectangle I set it manualy instead 
// init and load 
Image2->Canvas->CopyMode = cmSrcCopy; 
TJPEGImage *img = new TJPEGImage(); 
img->LoadFromFile("in.jpg"); 
Graphics::TBitmap *bmp = new Graphics::TBitmap; 
bmp->Assign(img); 
// I assume this is how you are rendering/store your left (source) image 
Image1->Width = bmp->Width;   // set dersired size 
Image1->Height = bmp->Height; 
Image1->Left = 10; 
Image1->Top = 10; 
Image1->Canvas->Draw(0,0,bmp); 
// I assume this is your mouse selection 
srect=TRect(90,34,192,154); 
h=120; w=102; 
// just render into Image1 for visual check 
Image1->Canvas->Pen->Color=clYellow; 
Image1->Canvas->Pen->Style=psDashDot; 
Image1->Canvas->Brush->Style=bsClear; 
Image1->Canvas->Rectangle(srect); 
Image1->Canvas->Pen->Style=psSolid; 
Image1->Canvas->Brush->Style=bsSolid; 
// place and resize Image2 next to Image1 
Image2->Top=10; 
Image2->Left=Image1->Width+20; 
Image2->Width = 170; 
Image2->Height = 200; 
// scaling 
scale = (float)img->Width/base; 
crect.Left = srect.Left * scale; // srect = source rect 
crect.Top = srect.Top * scale; 
crect.Right = crect.Left + (srect.Width() * scale); 
crect.Bottom = crect.Top + (srect.Height() * scale); 
// this is how you change the pixelformat 
Image2->Picture->Bitmap->PixelFormat=pf32bit; 

// your copy rect alternative 
// Image2->Canvas->CopyRect(TRect(0,0,h,w), bmp->Canvas, crect); 

// my stretch draw alternative 
Graphics::TBitmap *tmp=new Graphics::TBitmap; 
tmp->PixelFormat=pf32bit; 
tmp->SetSize(srect.Width(),srect.Height()); 
tmp->Canvas->CopyRect(TRect(0,0,srect.Width(),srect.Height()), bmp->Canvas, srect); 
Image2->Canvas->StretchDraw(TRect(0,0,srect.Width(),srect.Height()),tmp); 
delete tmp; 

// exit 
delete img; 
delete bmp; 

ビットマップのピクセル形式についての詳細を知りたいと高速ダイレクトピクセルフォーマットが表示された場合:

またAssignLoadFrom...呼び出しはピクセルフォーマットを変更することに注意して取ります...

8ビットのプレビュー画像はあなたとは少し異なりますが、私はしました代わりに、私は色の中で最もlikelly diferencesがあるピクセルごとにJPGようにあなたがPNGとしてエンコード掲示スクリーンショットトリミングや再エンコードを使用しても、+/-1px

あなたが気づいたような位置にあることも、あなたの入力イメージを持っていません面積が大きいほど色の歪みが大きくなります。これは、8ビットのピクセルフォーマットでは、パレットで256色しか得られないため、画像にもっと多くの色が含まれていると、より多くの色が切り捨てられてしまいます。選択された領域が大きくなればなるほど、画像にはより多くのピクセル、したがって異なる色が現れます。 GDIはあなたが見るものの結果として、色の量子化が少し劣っています...あなたがより良い何かをしたい場合(ケースには、あなたが出力として8ビット画像を使用して)これらを試してみてください。また、

あなたはCopyRect可能性が最も高い選択矩形に適合していなかった見ることができるようにスケーリングの切り捨て(より細かい整数計算を行うように見えます)DDAまたは双線形フィルタリング速度を "最適化"する

+0

感謝を参照してください....私はあなたの問題を再作成し、それがピクセルフォーマットと 'CopyRect'両方だったと思う、それは私がよりよく問題を理解して助けました。私はあなたの最初のコメントを読んだ後に解決策を見つけました。一時的なビットマップを作成し、元のイメージ上の選択した領域と同じサイズに設定し、縮小しないでCopyRectを使用してjpgイメージから一時ビットマップに領域をコピーし、Image2にストレッチドローします。結果は満足です。 –

関連する問題