液化變形(向前變形)問題求教

來源:互聯網
上載者:User
繼續上次的問題 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 給我



瞭解,謝謝您!
  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.