為什麼要把彩色轉黑白兩色呢?
這不是為了耍帥,而是因為點陣式印表機,只能印出黑白兩色 (連灰色都沒有)
(非黑即白,機器撞下去的點就是黑,沒有撞的就是白)
如果你的印表機,是點陣印表機,
把你的圖片用這個程式跑一下,可以確保你印出來的是相同的結果。
使用程式說明:
不要直接開啟程式
請在 我的電腦 或 檔案總管 (或桌面)
將圖片的圖示 移到程式的圖示上
就可以跑了
使用程式請注意:
1. 請用 24 位元 BMP檔, 最快的轉檔方法,就是用小畫家開你的圖,
然後另存新檔成 24 bit 點陣圖。
2. 如果圖跑不出來,請盡量把原圖的長和寬改成24的倍數,再跑一次。
相關討論
目前這方面的演算法,分為混色(dithering) 和 誤差擴散法 (error diffusion)
這支程式使用的是後者,
之所以叫做誤差擴散,是因為一個點算出來的結果會影響下一個點
可以修正某些在中間亮度判定錯誤的問題。
而目前有三種演算法可以選用
分別是Floyd-Steinberg、Jarvis-Judice-Ninke 和 Stucki
效果其實差不多,不過還是有細微的差異。
由於太多人用這些演算法跑Lena圖,所以我就不用Lena圖了...
上面這張圖,用三種演算法跑起來的結果都差不多。
(僅在於點的位置不同而已)
讓我們換一張圖來試試看 (三張圖演算法擺放位置不變,懶得標了..)
這張圖就有細微的差別
我的感覺是
Floyd-Steinburg:顆粒最細
Jarvis-Judice-Ninke:顆粒最濃
Stucki:折衷
Jarvis-Judice-Ninke演算法
function y = jj_ninke(x)
height=size(x,1);
width=size(x,2);
y=uint8(zeros(height,width));
z=zeros(height+3,width+3);
z(2:height+1,2:width+1)=x;
for i=3:height+1,
for j=3:width+1,
if z(i,j)<128
y(i-1,j-1)=0;
e=z(i,j);
else
y(i-1,j-1)=255;
e=z(i,j)-255;
end
z(i,j+1)=z(i,j+1)+7*e/48;
z(i,j+2)=z(i,j+2)+5*e/48;
z(i+1,j-2)=z(i+1,j-2)+3*e/48;
z(i+1,j-1)=z(i+1,j-1)+5*e/48;
z(i+1,j)=z(i+1,j)+7*e/48;
z(i+1,j+1)=z(i+1,j+1)+5*e/48;
z(i+1,j+2)=z(i+1,j+2)+3*e/48;
z(i+2,j-2)=z(i+2,j-2)+1*e/48;
z(i+2,j-1)=z(i+2,j-1)+3*e/48;
z(i+2,j)=z(i+2,j)+5*e/48;
z(i+2,j+1)=z(i+2,j+1)+3*e/48;
z(i+2,j+2)=z(i+2,j+2)+1*e/48;
end
end
Floyd Steinburg用的擴散法 (用上述程式e去乘)
Jarvis-Judice-Ninke用的擴散法 (用上述程式e去乘)
參考書目:Introduction to digital processing with MATLAB, MacAndrew/Wang/Tseng, CENGAGE Learning.

不好意思喔,這篇雖然讓我獲益良多,但是最後程式的部份有點錯誤, 我做出來的圖片左邊和上邊會出現一條黑線,我怎樣都消不掉它們= = 可以看看是哪裡的問題嗎?謝謝!
演算法是正確的,而且照這方法做不太可能出現您說的問題~ 換一張圖試試看?
我是用MATLAB2010b做的我同學也是用您寫的程式做過一遍,一樣出現了我剛剛說的情形,換了很多圖也是一樣的情形,用老師給的程式就沒有這條黑線了,可是老師給的程式是:Floyd Steinburg用的擴散法,我們不曉得怎麼改成Jarvis-Judice-Ninke用的擴散法 我認為應該是在 height=size(x,1); width=size(x,2); y=uint8(zeros(height,width)); z=zeros(height+3,width+3); z(2:height+1,2:width+1)=x; for i=3:height+1, for j=3:width+1, 這裡有出錯, 我們有辦法將那兩邊變粗,但是要讓那兩邊消失卻一直沒辦法...
我是2009b所以沒出錯... 的確是哪幾行可能出問題 (那幾行設定起始邊界) 如果老師給了Floyd,改了參數就會變Jarvis-Judice-Ninke了喔
可是老師給的Floyd Steinburg用的擴散法陣列比Jarvis-Judice-Ninke小,不曉得要怎麼改,他陣列部分是這樣做的: height=size(x,1); width=size(x,2); y=uint8(zeros(height,width)); z=zeros(height+2,width+2); z(2:height+1,2:width+1)=x; for i=2:height+1, for j=2:width+1,
Floyd的遮罩比較小,所以陣列也比較小 還有,他這個code真的可以跑嗎...
可以,之後在接上一些程式就可以跑了,而且不會出現黑線,還有我剛剛解決了上面出現黑線的問題: height=size(x,1); width=size(x,2); y=uint8(zeros(height,width)); z=zeros(height+3,width+3); z(2:height+1,2:width+1)=x; for i=2:height+1, for j=3:width+1, 可是無法用同樣的方法解決左邊出現黑線的問題...
for i=2:height+1, for j=2:width+1, 這裡應該要改成這樣才不會出現黑線,可是拿去跑時就一直ERROR... Error in ==> jj_ninke at 18 z(i+1,j-2)=z(i+1,j-2)+3*e/48; 也不知道要改其他甚麼地方才不會ERROR...
檢查一下,如果把i、j代入迴圈的值,會不會超出範圍?
應該會超出範圍,所以要像for j=3:width+1,這樣才行,可是又會出現黑線...
您好,我按下載卻沒有東西,請問檔案移除掉了嗎? 工作上需要,感謝您。
您好,剛好我也在工作上有這種轉圖的需求,檔案似乎被刪除了。請問可以重新上傳嗎?