如何讓放大縮小品質不錯 |
答題得分者是:daldal
|
linly
一般會員 發表:42 回覆:37 積分:15 註冊:2007-10-07 發送簡訊給我 |
您好:
我一開始先從其他的程式模組取得圖片(1240x1754 RGB) 的 row data (in memory),接著將這張圖片的 row dara 利用內插法處理成 827x1169 的內容( 寬高的數據僅供參考)。 [code cpp] void Interpolation( unsigned char* source, unsigned char* dest, int i_width, int i_height, int o_width, int o_height ); [/code] 然後再把這些資料利用 mommove 的方式一列一列的複製到 TImage::Pictrure::Bitmap 的元件中來呈現。所以我處理的重點就是 "內插法"、"Image 元件呈現"...etc。 接下來就是我想請教各位有經驗的板大的部分:我想在程式中製作放大縮小的功能,若執行這個功能會有兩頁(張)須處理。 嘗試簡單的方式: 1. 改變 TImage::Width、TImage::Height,不好。 2. 利用 TImage::Picture::Bitmap::Canvas::StrectchDraw 重繪,放大在縮小、或者縮小再放大,失真度明顯。 如果這裡用內插法去處理放大縮小的功能,因為我是用 TImage 元件呈現,所以需要考慮如何將"內插法配合ScanLine",搜尋板上文章似乎這在實作上有點麻煩,而且容易出錯(考慮相鄰兩列之類的問題); 如果說我先把 Image::Picture::Bitmap 一列一列利用 mommove 先複製出來放在 unsigned char* 的陣列,然後利用我文章一開始的那個內插法處理後,再複製回來 Image::Picture::Bitmap,這樣速度有點小慢。 小弟還有待磨練,以上描述若有不清楚之處,還請告知,這裡先謝謝各位寶貴的意見 編輯記錄
linly 重新編輯於 2008-04-21 12:41:11, 註解 無‧
|
brook
資深會員 發表:57 回覆:323 積分:371 註冊:2002-07-12 發送簡訊給我 |
|
linly
一般會員 發表:42 回覆:37 積分:15 註冊:2007-10-07 發送簡訊給我 |
我剛剛試了一下,拿一張都是文字的 .bmp 測試,然後利用 CopyRect 把內容縮小成原先的 1/4,程式碼如下:
[code cpp] Graphics::TBitmap *pBMP = new Graphics::TBitmap(); pBMP->LoadFromFile("1.bmp"); TRect rectSource = TRect(0,0,pBMP->Width-1,pBMP->Height-1); this->Image1->Width = WIDTH/2; this->Image1->Height = HEIGHT/2; this->Image1->Left = (this->ClientWidth - this->Image1->Width)>>1; this->Image1->Top = 0; this->Image1->Stretch = true; this->Image1->Canvas->CopyMode = cmSrcCopy; this->Image1->Canvas->CopyRect(TRect(0,0,this->Image1->Width-1,this->Image1->Height-1), pBMP->Canvas, rectSource); delete pBMP; [/code] 視覺感官上,文字都變成粗體,怎麼會這樣XD 連結是圖片片段,還請指教 謝謝 ^_^ 處理前: http://www.flickr.com/photos/23700932@N07/2451701046/ 處理後: http://www.flickr.com/photos/23700932@N07/2451701168/ ===================引 用 brook 文 章=================== 我之前用過CopyRect,不知合和合用.
編輯記錄
linly 重新編輯於 2008-04-30 13:15:12, 註解 無‧
|
linly
一般會員 發表:42 回覆:37 積分:15 註冊:2007-10-07 發送簡訊給我 |
解決方式:利用 StretchBlt,不過還是希望能有強者可以解釋一下上一篇的原因為何,謝謝!!
[code cpp] ... ... ::SetStretchBltMode(this->Image1->Canvas->Handle,HALFTONE); ::StretchBlt(this->Image1->Canvas->Handle,0,0,this->Image1->Width,this->Image1->Height,pBMP->Canvas->Handle,0,0,pBMP->Width,pBMP->Height,SRCCOPY); // this->Image1->Canvas->CopyMode = cmSrcCopy; // this->Image1->Canvas->CopyRect(TRect(0,0,this->Image1->Width-1,this->Image1->Height-1), pBMP->Canvas, rectDisplay); [/code] |
daldal
高階會員 發表:6 回覆:102 積分:226 註冊:2007-06-18 發送簡訊給我 |
1.結果不同是因為你多了這一行,不然CopyRect跟StretchBlt結果是相同的
(詳細內容可以看source code, CopyRect就是使用StretchBlt畫出來的) [code cpp] SetStretchBltMode(this->Image1->Canvas->Handle,HALFTONE); [/code] 2.其實就TImage的draw function來看的話, 他也是使用StretchBlt來顯示 (依照不同格式會使用HALFONE or STRETCH_DELETESCANS ...) 至於Bitmap畫出來到Image的做法也就是使用CopyRect 所以你程式碼的動作 [code cpp] SetStretchBltMode(this->Image1->Canvas->Handle,HALFTONE); this->Image1->Canvas->CopyRect(TRect(0,0,this->Image1->Width-1,this->Image1->Height-1),pBMP->Canvas,rectSource); [/code] 會等同於 [code cpp] this->Image1->Picture->Bitmap->Assign(pBMP); [/code] 只是圖片一個存放在pBMP, 一個放在Image裡的Bitmap 若是你不想要多一次(Assign)複製的話, 就直接使用Image->Picture->Bitmap->LoadFromFile即可 |
linly
一般會員 發表:42 回覆:37 積分:15 註冊:2007-10-07 發送簡訊給我 |
首先,謝謝 daldal 的回覆,不過真的會等同於 Assign 嗎!? ( 是不是還有甚麼屬性需要設定 )
因為我要做縮放的動作,直接用 Assign 的話,只會複製到一部分的內容( 根據我的程式碼敘述則為左上方區塊 ) 如果去設定 Stretch 那效果就不好了。 另外照你所描述的,TImage 元件把 StretchBlt 的模式給限制住了,變成它自己決定使用何種 mode,有點不方便。 最後,我把分數給你囉... 不好意思前一位回我的版友
編輯記錄
linly 重新編輯於 2008-04-30 18:50:02, 註解 無‧
|
daldal
高階會員 發表:6 回覆:102 積分:226 註冊:2007-06-18 發送簡訊給我 |
1.若是在Bitmap內容縮放顯示到Image顯示圖層的話
在條件BITSPIXEL(一個pixel多少bits)*PLANES(多少圖層,ex rgb=3) <=8 且< DIB原始資料的bmBitsPixel*bmPlanes 兩者都符合才會使用HALFTONE模式 我用Assign只是複製到Bitmap讓他使用Image顯示,測試結果是不是相同而已 2.若是要自己決定使用何種Mode, 那就如同之前您所打的程式碼 用手工設定SetStretchMode CopyRect,來達到你的需求 不然就是自己改寫Image元件,全部照抄,只要把Draw部分的Function 改成手動去設定StretchMode,而非自行判斷 ===================引 用 linly 文 章=================== 首先,謝謝 daldal 的回覆,不過真的會等同於 Assign 嗎!? ( 是不是還有甚麼屬性需要設定 ) 因為我要做縮放的動作,直接用 Assign 的話,只會複製到一部分的內容( 根據我的程式碼敘述則為左上方區塊 ) 如果去設定 Stretch 那效果就不好了。 另外照你所描述的,TImage 元件把 StretchBlt 的模式給限制住了,變成它自己決定使用何種 mode,有點不方便。 最後,我把分數給你囉... 不好意思前一位回我的版友
編輯記錄
daldal 重新編輯於 2008-04-30 19:12:39, 註解 無‧
|
linly
一般會員 發表:42 回覆:37 積分:15 註冊:2007-10-07 發送簡訊給我 |
|
daldal
高階會員 發表:6 回覆:102 積分:226 註冊:2007-06-18 發送簡訊給我 |
dear linly,
不好意思,可否請教一下 第一篇中提到的內插函式 [code cpp] void Interpolation( unsigned char* source, unsigned char* dest, int i_width, int i_height, int o_width, int o_height ); [/code] 執行的內插法放大縮小,大概會花多久時間(ms)? (整數倍以及非整數倍的縮放) 看您之前提到速度有點小慢,所以有點好奇處理的速度
編輯記錄
daldal 重新編輯於 2008-05-01 10:00:12, 註解 無‧
|
linly
一般會員 發表:42 回覆:37 積分:15 註冊:2007-10-07 發送簡訊給我 |
我採用的是 bilinear 的方式,測試了一下時間
[code cpp] 請在此區域輸入程式碼 #include #include using namespace std; ... ... clock_t start, end; start = clock(); Reduce( pSource, pInterpolation, i_width, i_height, o_width, o_height, 3, 1 ) // 後面的 3 = RGB, 1 = bilinear,給使用者自訂 end = clock(); double total_time = ofstream outfile("time.txt"); outfile << "The time was : " << total_time; outfile.close(); [/code] 上述單單做內插法的結果為:The time was: 0.718 s ( Source 為 1240 x 1754;內插後 827 x 1169 ) 由於我是使用 Image 元件,所以內插法處理完後,還要做 memmove 的方式,一列一列的複製到 TImage::Picture::Bitmap 的 ScanLine 中。所以說,依照我的處理方式,如果我要做放大縮小,我就需要先把資料從Timage 元件搬動到一塊記憶空間,然後做內插法,然後在複製回 Image 元件中,每次放大縮小都有兩張需要處理(需求)。這樣看來 StretchBlt 的函式介面比較符合我實作方式的需要與便利。 也許有更好的方式,不過我目前只想到這樣的方式 ^_^ P.S.:Pentium 4 CPU 3.00 GHz,1 GB RAM |
daldal
高階會員 發表:6 回覆:102 積分:226 註冊:2007-06-18 發送簡訊給我 |
|
linly
一般會員 發表:42 回覆:37 積分:15 註冊:2007-10-07 發送簡訊給我 |
|
perrychu
一般會員 發表:0 回覆:1 積分:0 註冊:2004-06-13 發送簡訊給我 |
曾看過日本一篇圖面處理分享, 內容摘要如下: 若要放大圖面. 採用Bi-Linear 內插法會有不錯的效果.
若要縮小圖面. 則使用積分法(面積平圴法) 則較理想.不宜使用內插法. 若大家對這有興趣的話. 可至以下網站去下載demo 及 tool http://www.asahi-net.or.jp/~HA3T-NKMR/DGS/DownLoad.htm DHGL 1.2 下載解壓後. 有一目錄 common, 裏有一 BitmapUtils. 這就是圖面縮小. 放大的程式. 最主要有3個功能: enlarge(純放大). shrink(純縮小). stretch(可放大或縮小), 這3個功能都是使用 scanline 及快取功能(使用記憶體). 執行速度很快... 若要使用demo的話. 可把 common 加入 Environment 的 library. 然後去找第4章第5節的sample . 若想提昇圖面處理技術. 一定要去下載. 工具程式內都有註解. 但都是日文. 若本身電腦無法看日文. 則會顯示 ? 或亂碼. 但. 不會影響執行... |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |