繼續上次的問題 http://bbs.csdn.net/topics/390962881?page=1#post-398737904
已經將液化公式U解出,但實際使用後圖片出現非預期變形,不確定是哪個環節出錯,請大神指導
以下是My Code:
var r, alpha, angle, sourcePosition, destPosition, rmax, M, C, X; for (y = -radius; y < radius; ++y) { //取得圓範圍 for (x = -radius; x < radius; ++x) { if (x * x + y * y <= radius * radius) { destPosition = (y + centerY) * width + x + centerX; //移動後圓內1點(此為pixel位置,非座標) destPosition *= 4; var rmax = radius; //圓半徑 C = {x:centerX+80,y:centerY};//移動前原點C (假設右往左移動80 pixel) M = {x:centerX,y:centerY}; //移動後原點M X = {x:(x + centerX) , y: (y+ centerY)};//移動後圓內1點座標 var U = Liquify(M,X,C,rmax); //液化運算得到 U 座標 sourcePosition = ((Math.ceil(U.y))*width)+Math.ceil(U.x); //粗略取整數 U 座標(尚未用線性插值法) 並轉換為pixel位置 sourcePosition *= 4; //用U取代原X像素 dstPixels[destPosition + 0] = srcPixels[sourcePosition + 0]; dstPixels[destPosition + 1] = srcPixels[sourcePosition + 1]; dstPixels[destPosition + 2] = srcPixels[sourcePosition + 2]; dstPixels[destPosition + 3] = srcPixels[sourcePosition + 3]; } } } drawPixels(canvasId, destImgData); //繪圖開始
運行後圖片結果:
回複討論(解決方案)
用 Canvas 處理?
你的 dstPixels、srcPixels 分別是什嗎?怎麼賦值的?
看演算法 srcPixels 應該是 getImageData 方法取得的圖片資料
那麼 dstPixels 是如何賦值的?因為你只修改了矩形的內接圓部分
js 的數組是引用傳遞的
如果代碼中有 dstPixels = srcPixels 的話,那麼對 dstPixels 的修改就會作用到 srcPixels
於是 srcPixels[sourcePosition + 0] 得到的可能是前面剛被修改後的 dstPixels[destPosition + 0]
這樣就不對了
只有在 變形資料全部產生後,才可寫回去
謝謝回覆,抱歉,我把漏掉的代碼補上
1. 對的,是用canvas
2. 遺漏代碼:
var sourceImgData = originalImageData; //原始圖片image data var destImgData = createCompatibleImageData(canvasId,sourceImgData); //將image 寫入Canvas var srcPixels = sourceImgData.data; //取得image data var dstPixels = destImgData.data; //取得Canvas內image data
目前不太理解您的意思,我的具體思維是只對圓內pixel做替換,的確是全部替換完之後才寫回canvas,也確定U算出來的值是正確的,是否有我誤解的地方?目前不確定的我這樣替換的邏輯是否正確,對於那個公式無法理解,我的資質太淺好睏擾..
謝謝回覆,抱歉,我把漏掉的代碼補上
1. 對的,是用canvas
2. 完整代碼:
var sourceImgData = originalImageData; //原始圖片image data var destImgData = createCompatibleImageData(canvasId,sourceImgData); //將image 寫入Canvas var srcPixels = sourceImgData.data; //取得image data var dstPixels = destImgData.data; //取得Canvas內image data width = sourceImgData.width; height = sourceImgData.height; centerX = Math.floor(width / 2); centerY = Math.floor(height / 2); radius = 100; copyImageData(srcPixels, dstPixels, width, height); drawPixels(canvasId, destImgData); //繪出整張原圖 var r, alpha, angle, sourcePosition, destPosition, rmax, M, C, X; for (y = -radius; y < radius; ++y) { //取得圓範圍 for (x = -radius; x < radius; ++x) { if (x * x + y * y <= radius * radius) { destPosition = (y + centerY) * width + x + centerX; //移動後圓內1點(此為pixel位置,非座標) destPosition *= 4; var rmax = radius; //圓半徑 C = {x:centerX+80,y:centerY};//移動前原點C (假設右往左移動80 pixel) M = {x:centerX,y:centerY}; //移動後原點M X = {x:(x + centerX) , y: (y+ centerY)};//移動後圓內1點座標 var U = Liquify(M,X,C,rmax); //液化運算得到 U 座標 sourcePosition = ((Math.ceil(U.y))*width)+Math.ceil(U.x); //粗略取整數 U 座標(尚未用線性插值法) 並轉換為pixel位置 sourcePosition *= 4; //用U取代原X像素 dstPixels[destPosition + 0] = srcPixels[sourcePosition + 0]; dstPixels[destPosition + 1] = srcPixels[sourcePosition + 1]; dstPixels[destPosition + 2] = srcPixels[sourcePosition + 2]; dstPixels[destPosition + 3] = srcPixels[sourcePosition + 3]; } } } drawPixels(canvasId, destImgData); //繪出圓形部分
目前不太理解您的意思,我的具體思維是只對圓內pixel做替換,的確是全部替換完之後才寫回canvas,也確定U算出來的值是正確的,是否有我誤解的地方?目前不確定的我這樣替換的邏輯是否正確,對於那個公式無法理解,我的資質太淺好睏擾..
createCompatibleImageData 是個什麼函數
如果 他返回的 destImgData 是傳入的 sourceImgData 的引用的話,就會出現你遇到的情況
function createCompatibleImageData(canvasId, imgData) { "use strict"; var context2d = getContext2d(canvasId); return context2d.createImageData(imgData.width, imgData.height);}
就只是定義canvas context2d 而已,所以我的pixwel替換的思維是錯誤的嗎?應該怎麽做才對?
感謝!
流程大致是這樣
var c=document.getElementById("myCanvas"); //擷取 Canvas 控制項var ctx=c.getContext("2d"); var img=new Image()img.src = '/photo.jpg';img.onload = function() { //載入圖片 source = ctx.getImageData( x, y, w, h) //讀取一個矩形地區 //在這裡進行處理,注意事項在下面 ctx.putImageData(source, x, y) //寫回去}
處理時
srcPixels = source.data.concat([]); //這樣產生副本(非引用)
dstPixels 就是 source.data
不太清楚您指的引用是什麽意思,是參照的意思嗎?(2者會同步變化)
My Code部分應該是複製一份暫存,不是參照(或引用)
我想了一下所看的問題,是否可能是作用地區有問題?
應該受影響的地區從原點C移動到M時(紅色區塊)
我的做法只有取得M圓內X點並算出U替換,作用區塊也只有M圓,是否是這原因引起非預期圖片變形?
我寫了個完整的測試例,你可參考一下(當然毛病很多,但意思到了)
在圖片上按下滑鼠鍵並拖動滑鼠就可看到效果
Your browser does not support the canvas element.滑鼠位置:取景框:工作半徑遞減
哇...謝謝xuzuning大神,太強大了!!
剛剛無聊也在板上亂晃回答問題 挺好玩的~
已經測試過您給的代碼,也仔細看過,執行原理似乎跟您上次給的php版本代碼一樣(用遞減半徑的方式運行?)
這樣子的確有達到目的,但是可能無法實際應用在瘦身功能。
xuzuning覺得我用那個公式的方式還有討論的空間嗎?還是我應該做罷尋求其他方式?
當你將滑鼠從邊緣向中心移動時,的確有所謂“?身“的效果(改變參數試試)
不過這個這個公式似乎並不像他描述的那樣(好像反了)
當然也可能是程式寫錯了,我嘗試了集中寫法,大多都不能實現期望的結果。只有上次那個php版的效果最明顯
你可以再看看
剛剛一直在玩您提供的那個代碼 的確可以達到瘦身,但我想應該無法使用在商業用途,使用者用起來可能無法達到他們預期的效果(要做到像美圖秀秀那樣)。目前在網路上,也沒找到半個實作類別似功能的人,我想這可能真的相當困難,感謝xuzuning熱心協助!我再花些時間研究看看,如果xuzuning有發現新思維,也懇請您與我討論分享。
另外PHP板無法編輯文章是正常的嗎? 這樣很困擾,我在回答別人問題時寫錯字卻無法修改,一直說我許可權不足,即使此篇我是發帖者,一樣無法編輯自己的文章。
貼子只在發布後數分鐘內貼主可修改
其他時間修改的許可權在版主,CSDN就是這樣規定的
演算法問題待想明白後在於你商討,你可以私信發個 email 給我
貼子只在發布後數分鐘內貼主可修改
其他時間修改的許可權在版主,CSDN就是這樣規定的
演算法問題待想明白後在於你商討,你可以私信發個 email 給我
瞭解,謝謝您!