不斷發展的 SEO 世界中,保持領先地位至關重要。如果你像我一樣,你會發現隨著搜索算法變得越來越復雜和競爭越來越激烈,SEO資源保持不變甚至減少。因此,我們必須不斷尋求創新方法來簡化工作流程并提高生產力,才能維持生計。
我們都知道自動化可以幫助我們完成更多工作,而無需增加人員或預算。我相信你們中的許多人都問過自己是否應該深入編碼世界以學習如何自動化某些任務。或者,你們中的一些人甚至可能嘗試要求一些開發資源來實現這一目標。
如果您仍在閱讀,則意味著您在上面認出了自己。這篇文章是寫給你的,我的病友!
雖然學習如何編碼不一定是解決方案,但仍然有希望的燈塔:進入 ChatGPT。
憑借其處理各種任務的卓越能力,ChatGPT 可以助您一臂之力,在本文中,我們將探討 ChatGPT 如何徹底改變您實現 SEO 自動化的方式,使您無需具備豐富的編碼知識即可取得顯著的成果。
但首先,讓我們更深入地研究自動化的概念及其在 SEO 領域的意義。
自動化是使用技術和工具來簡化和簡化重復性或耗時任務的過程。它可以讓您將寶貴的時間和精力分配給更具戰略性的舉措,而平凡和重復的活動則由其他系統無縫處理。
有效利用自動化的關鍵步驟之一是確定要自動化的正確任務。
雖然并非所有任務都適合自動化,但許多流程可以分解為可成功自動化的可管理組件。從長遠來看,通過識別這些組件,您可以節省大量時間和精力。
清晰的問題定義對于任何自動化項目都是至關重要的。
它包括理解手頭的任務、識別痛點以及定義期望的結果。明確定義的問題陳述為為 ChatGPT 編寫有效的提示奠定了基礎,并確保自動化流程與預期目標保持一致。
一旦任務被識別并分解,就可以為 ChatGPT 編寫提示了。
提示充當提供給模型的指令或查詢以生成所需的響應。編寫有效的提示需要在足夠具體以指導模型和允許模型靈活地生成創造性和準確的響應之間取得平衡。
1. 首先列出您每天或每周執行的任務。這些重復性任務的范圍從數據分析和報告生成到關鍵字研究或內容優化以及您能想到的幾乎所有其他任務。
2. 將您的列表分為您對如何自動化有大致了解的任務以及那些看起來具有挑戰性或不熟悉的任務。前者可能涉及使用現有的工具、腳本或插件,而后者可能需要更多的研究或學習。
3. 優先考慮自動化時能帶來最顯著效益的任務。考慮諸如您將節省的時間、可能的準確性、可擴展性和潛在的投資回報率等因素。或者簡單地考慮一下它是否可以讓你保持理智。選擇一項與您的目標相符且能夠為您的日常工作帶來切實改進的任務。
我曾經考慮過我可能想要自動化哪些重復性任務,并列出了一個非常簡短的列表 - 事實上,從我記事起,我就一直在自動化盡可能多的工作。然而,有一些事情我寧愿不必做,即使它們每個月只發生幾次。
從我的列表中,我找到了一個可以節省我一些時間并且還有可能提升我的報告質量的方法:向 Looker Studio 中的圖表添加 Google 更新注釋。
對于下面的示例,我剛剛使用了以下免費工具和服務:
作為下一步,我開始思考這可能如何運作。我過去確實有自動化經驗,有時可以當場想出一個好的解決方案。
但如果您正在解決一個不容易找到解決方案的問題,請不要擔心。在這里,您可以使用 ChatGPT 尋求潛在的解決方案,也可以進行搜索(通過您最喜歡的搜索引擎)以查找其他人針對同一問題提出的解決方案。由于 ChatGPT 有時可能有點太有創意,我更喜歡堅持經典的“只需 Google 即可”。我堅信我永遠不是第一個遇到特定問題的人。
以下是我對自動化建議任務的想法:
ALT/標題:Google 更新頁面和 Chrome 開發者工具呈現的 HTML 代碼的屏幕截圖,顯示該頁面是使用表格構建的。
為了驗證我的思路,我將快速運行表格中的公式,看看數據是否按需要輸入:
ALT/標題:Google 表格中的屏幕截圖顯示第一個表中的數據
雖然此公式有效,但它僅引入頁面上的第一個表(或特定的一個表,但不是全部)。如果我想要的只是今年的更新,那么使用這個公式就足夠了。不幸的是,我希望在報告中包含歷史數據,因此我需要導入所有表格。
現在我可以將上面的筆記總結為 ChatGPT 的提示:
ALT/標題:ChatGPT 提示的屏幕截圖,詢問:您好,我想使用 ImportHTML 功能將網頁上多個表中的信息獲取到 Google 表格中。如果有多個表,我該怎么辦?
ALT/標題:ChatGPT 響應的屏幕截圖,其中包含有關如何從網頁導入表的詳細信息。
有趣的是——我們肯定會陷入“我需要幫助”的境地,因為我不熟悉 AppScript。我還注意到,除了代碼之外,我還得到了說明和注釋——這對我理解它的功能非常方便。
我轉到 Google Sheets > 擴展 > AppScript 并在此處創建一個新項目。我將其命名為“Google Updates”,然后將此處的代碼替換為 ChatGPT 提供的代碼。
在 AppScript 中進行任何更改時以及運行代碼之前,請務必點擊“保存”。
否則,您可能會因替換但未保存的代碼而出現錯誤,并且必須花時間調試不存在的問題。
看起來 ChatGPT 為我創建了一個特殊的函數,我可以在表格中調用它 - 我按照說明操作,并將該函數與我想要從中獲取更新的 URL 結合使用:
=importMultipleTablesFromURL(" https://status.search.google.com/products/rGHU1u87FJnkP6W2GwMi/history ")
但我收到一個錯誤:
ALT/標題:顯示錯誤的 Google 表格的屏幕截圖
我什至沒有閱讀錯誤消息,我只是將其復制到 ChatGPT 中:
ALT/標題:描述 Google 表格錯誤的 ChatGPT 提示的屏幕截圖
使用我什至不理解的這條消息,ChatGPT 能夠翻譯我需要授權才能在表格中覆蓋。然后它為我更新代碼以包含此內容。
運行新代碼后,我確實收到了“審查權限”對話框:
ALT/標題:AppScript 中的“需要授權”對話框的屏幕截圖
然后我就可以驗證這個腳本并允許它覆蓋我的表格。
我再次運行代碼,令人驚訝的是,我又收到了另一個錯誤:
ALT/Caption:AppScript 執行日志錯誤的屏幕截圖
沖洗并重復,我將這個錯誤反饋給ChatGPT。事實上,我這樣做了幾次,所有的錯誤都出現了,并且我不斷獲得新的代碼供我嘗試。我只是在這里分享錯誤和回復的頂行:
ALT/標題:描述錯誤和響應的 ChatGPT 提示的屏幕截圖
ALT/標題:描述錯誤和響應的 ChatGPT 提示的第二個屏幕截圖
ALT/標題:描述錯誤和響應的 ChatGPT 提示的另一個屏幕截圖
我在這里所做的幾乎就是調試。我沒有自己檢查代碼并試圖找出錯誤是什么以及如何修復它們,而是將它們反饋給 ChatGPT,它會自行調試。
雖然中間有一些來回,但整個過程不到 5 分鐘。我終于得到這個代碼:
ALT/標題:ChatGPT 代碼片段的屏幕截圖
復制粘貼。節省。跑步。我終于成功執行了。切換到我的工作表,這是我看到的:
ALT/標題:顯示 3 個表格的 Google Sheets 數據的屏幕截圖
到目前為止,一切都很好!所有表格都正在導入,是時候進行一些改進了:
現在我可以將所有這些信息一次性或一次部分反饋給 ChatGPT。我覺得我需要按類型對請求進行分組,所以我首先嘗試這樣做:
ALT/標題:ChatGPT 提示的屏幕截圖,要求僅保留第一個表的標題,并且在更新時不要覆蓋數據
從下面的結果可以看出,這個要求不夠明確。 ChatGPT 將所有數據放入一列中:
ALT/標題:Google 表格的屏幕截圖,在一列中顯示所有表格數據
是時候讓我的溝通更加清晰,并解釋我所看到的以及我想要得到的信息了:
ALT/標題:ChatGPT 提示的屏幕截圖更清楚地詢問要保留哪些標頭
ALT/標題:Google 表格的屏幕截圖,顯示三個表格,中間有兩個空行
肯定越來越近了!我現在只需要刪除那些空行。我將再次解釋我所看到的以及我想要的結果。
ALT/標題:ChatGPT 提示要求刪除空行的屏幕截圖
一些改進:
ALT/標題:ChatGPT 提示的屏幕截圖,要求再次刪除空行,因為仍留下一行
并成功:
ALT/標題:Google 表格的屏幕截圖,顯示所有三個表格列為一個表格
現在進行下一個改進:
ALT/標題:ChatGPT 提示要求從 A 列中提取更新名稱的屏幕截圖
結果不是我所期望的,所以我決定舉一些例子,涵蓋我能看到的所有模式。最后,我們到達了那里:
ALT/標題:Google 表格的屏幕截圖,顯示表格和帶有更新名稱的新列
那不是已經很漂亮了嗎?讓我們看看是否還能獲得更新的結束日期,因為該信息不是由 Google 直接提供的。
ALT/標題:ChatGPT 提示要求計算更新長度的屏幕截圖
請注意回復中 ChatGPT 如何知道 B 列和 C 列中有哪些值?那只是因為我們之前提到過它們 – ChatGPT 實際上無法看到我們的 Google 表格。
ALT/標題:Google 表格的屏幕截圖,顯示持續時間為無效持續時間格式
查看具有無效持續時間格式的行,我們可以很快看到只要持續時間不包括小時,它們就會發生。我決定要求 ChatGPT 在計算結束日期之前將持續時間四舍五入到整天 - 這樣我們就可以繞過該列中包含不同類型數據的問題。
ALT/標題:Google 表格的屏幕截圖顯示了預期的持續時間
既然數據看起來不錯,那么只剩下一件事情要做了——把這整件事列入時間表。
這可以通過使用觸發器從 AppScript 完成,但由于我們使用的是 ChatGPT,我們不妨向它詢問最后一個請求:
ALT/標題:ChatGPT 提示要求添加每周觸發器的屏幕截圖
瞧,這是包含觸發器的最終代碼:
function importTableAndCalculateUpdateType() {
var url="https://status.search.google.com/products/rGHU1u87FJnkP6W2GwMi/history"; // Replace with the URL of the webpage containing the tables
var response=UrlFetchApp.fetch(url);
var content=response.getContentText();
var tables=content.match(/<table[\s\S]*?<\/table>/g);
var sheet=SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lastRow=sheet.getLastRow();
// Clear the sheet except for the first row (header)
if (lastRow > 1) {
sheet.getRange("A2:E" + lastRow).clearContent();
}
var data=[];
tables.forEach(function(table, index) {
var tempData=[];
var tableRows=table.match(/<tr[\s\S]*?<\/tr>/g);
tableRows.forEach(function(rowHTML, rowIndex) {
var rowData=[];
var cells=rowHTML.match(/<t[dh][\s\S]*?<\/t[dh]>/g);
cells.forEach(function(cellHTML) {
var cellText=cellHTML.replace(/<[^>]+>/g, '').trim();
rowData.push(cellText);
});
if (rowData.length > 0 && !(index > 0 && rowIndex===0)) {
tempData.push(rowData);
}
});
if (tempData.length > 0) {
data.push(tempData);
}
});
var startColumn=1; // Starting column to paste data
var startRow=1; // Starting row to paste data
for (var i=0; i < data.length; i++) {
var numRows=data[i].length;
var numCols=data[i][0].length;
sheet.getRange(startRow, startColumn, numRows, numCols).setValues(data[i]);
startRow +=numRows;
}
var updateTypeColumn=4; // Column index for "Update Type" (column D)
var endDateColumn=5; // Column index for "End date" (column E)
// Check and set header for "Update Type" and "End date" if they don't exist
if (sheet.getRange(1, updateTypeColumn).getValue() !=='Update Type') {
sheet.getRange(1, updateTypeColumn).setValue('Update Type');
}
if (sheet.getRange(1, endDateColumn).getValue() !=='End date') {
sheet.getRange(1, endDateColumn).setValue('End date');
}
for (var j=2; j <=sheet.getLastRow(); j++) {
var startDate=sheet.getRange(j, 2).getValue(); // Start date from column B
var duration=sheet.getRange(j, 3).getValue(); // Duration from column C
var endDate=calculatePotentialEndDate(startDate, duration);
sheet.getRange(j, endDateColumn).setValue(endDate);
var text=sheet.getRange(j, 1).getValue();
var updateTypes=extractUpdateTypes(text);
if (updateTypes.length > 0) {
var formattedText=updateTypes.map(word=> formatText(word.replace(/^\d{4}\s/, ''))).join(' ');
sheet.getRange(j, updateTypeColumn).setValue(formattedText);
} else {
sheet.getRange(j, updateTypeColumn).setValue('Other');
}
}
}
function createWeeklyTrigger() {
var day=1; // Monday
var hour=1; // 1 a.m. GMT
var timezone="GMT"; // Set the timezone
ScriptApp.newTrigger("importTableAndCalculateUpdateType")
.timeBased()
.onWeekDay(day)
.atHour(hour)
.inTimezone(timezone)
.create();
}
function extractUpdateTypes(text) {
var matches=text.match(/\d{4}\s([\w\s]+?)\supdate/ig);
return matches ? matches.map(match=> match.replace(/\supdate$/i, '').trim()) : [];
}
function formatText(str) {
return str.toLowerCase().replace(/(?:^|\s)\S/g, function(match) {
return match.toUpperCase();
});
}
function calculatePotentialEndDate(startDate, duration) {
var daysMatch=duration.match(/^(\d+)\s+days?/i);
var hoursMatch=duration.match(/^(\d+)\s+hours?,?\s?[\s\S]*/i);
if (daysMatch) {
var days=parseInt(daysMatch[1]);
var endDate=new Date(startDate);
endDate.setDate(startDate.getDate() + days);
return endDate;
} else if (hoursMatch) {
return new Date(startDate.getTime() + 1 * 24 * 60 * 60 * 1000); // Adding 1 day
} else {
return 'Invalid Duration Format';
}
}
這是最好的方法嗎?可能不會。好處是我在 30 分鐘內就完成了,只需要一些會話技巧,而且我不必花幾個月的時間學習腳本語言。但是,如果我將來確實想學習,ChatGPT 會為我提供可能需要的所有解釋。
如果您來這里只是因為想要成品,請隨時創建我的 Google 更新表的副本,您可以將其與 Looker Studio 中的分析數據混合。
以下示例展示了將此數據疊加在流量時間線上后的報告的外觀:
ALT/標題:Looker Studio 儀表板的屏幕截圖,顯示使用 Google 更新注釋的網站流量時間線
您還可以對開始日期和結束日期進行三向混合,然后您可以選擇任何更新并在圖表上查看開始日期和結束日期。您甚至可以給它們不同的顏色。
ALT/標題:Looker Studio 混合面板的屏幕截圖,顯示三向混合
ALT/標題:Looker Studio 儀表板的屏幕截圖,顯示流量時間線上的 Coe 更新注釋
或者,如果您愿意,您可以創建 Looker Studio 儀表板的副本,將 Google Analytics 數據與 Google Sheets 中的 Google Update 注釋結合起來,并查看其設置方式。
如果您有興趣使用 ChatGPT 自動執行不同類型的 SEO 任務,請繼續閱讀:
我希望早點做的事情:
如何改進這個過程:
如果您決定嘗試此過程,請考慮與其他 SEO 分享您的成就。您的成功故事可能會激勵人們采用這種方法并增強他們自己的 SEO 工作流程。
此外,在與 ChatGPT 互動時,請記住使用大量的“請”和“謝謝”——你永遠不知道人工智能最終統治世界時會記住什么!
天小五與大家分享一個常用的查找引用函數即INDEXC函數,該函數表示在給定的單元格區域中,返回特定行列交叉處單元格的值或引用,那具體怎么使用?通過3個示例一起來看看相應的用法吧。
1、制作小抽獎箱
如何利用Excel制作簡單的小抽獎箱?這里與大家分享借用INDEX函數來實現。
在單元格中輸入公式=INDEX(A2:A17,RANDBETWEEN(2,COUNTA(A2:A17)))
公式說明:
COUNTA函數表示統計非空單元格格式
RANDBETWEEN函數表示隨機生成整數
2、隔行提取數據
在單元格中輸入公式=INDEX($A:$A,COLUMN(A1)+(ROW(A1)-1)*2)&""
公式說明:
COLUMN()表示獲取相應的列號
ROW()表示獲取相應的行號
3、一對多查詢
輸入公式=IFERROR(INDEX($A:$F,SMALL(IF($C:$C=$I,ROW(:),4^8),ROW(A1)),COLUMN(A1)),""),按Ctrl+Shift+Enter組合鍵,之后向右向下填充即可。
公式說明:
INDEX表示獲取行列交叉數值
語法結構=INDEX(區域,行號,列號)
SMALL函數表示獲取第幾個最小值
語法結構=SMALL(查找的區域,指定要找第幾個最小值)
IF函數表示根據條件進行判斷并返回不同的值。
語法結構=IF(條件,條件成立時返回的值,條件不成立時返回的值)
者:前端Q
轉發鏈接:https://mp.weixin.qq.com/s/ewFfXptccFs5KvjUINLGbQ
小試牛刀,實現了六款簡單常見HTML5 Canvas特效濾鏡,并且封裝成一個純JavaScript可調用的API文件gloomyfishfilter.js。支持的特效濾鏡分別為:
1.反色
2.灰色調
3.模糊
4.浮雕
5.雕刻
6.合理
2.灰色調:獲取一個預期點RGB值r,g,b則新的RGB值
newr=(r * 0.272)+(g * 0.534)+(b * 0.131);
newg=(r * 0.349)+(g * 0.686)+(b * 0.168);
newb=(r * 0.393)+(g * 0.769)+(b * 0.189);
3.模糊:基于一個5 * 5的卷積核
4.浮雕與雕刻:
根據當前預期的前一個預期RGB值與它的后一個重新的RGB值之差再加上128
5.總體:模擬了物體在鏡子中與之對應的效果。
var canvas=document.getElementById("target");
canvas.width=source.clientWidth;
canvas.height=source.clientHeight;
**if**(!canvas.getContext) {
console.log("Canvas not supported. Please install a HTML5compatible browser.");
**return**;
}
// get 2D context of canvas and draw image
tempContext=canvas.getContext("2d");
var source=document.getElementById("source");
tempContext.drawImage(source, 0, 0, canvas.width,canvas.height);
var canvas=document.getElementById("target");
var len=canvas.width * canvas.height * 4;
var canvasData=tempContext.getImageData(0, 0, canvas.width, canvas.height);
var binaryData=canvasData.data;
function bindButtonEvent(element, type, handler)
{
if(element.addEventListener){
element.addEventListener(type, handler,**false**);
}else{
element.attachEvent('on'+type, handler);// for IE6,7,8
}
}
<scriptsrc=*"gloomyfishfilter.js"*></script> //導入API文件
gfilter.colorInvertProcess(binaryData, len); //調用 API
<meta http-equiv="X-UA-Compatible"*content=*"chrome=IE8">
效果演示:
CSS部分:
#svgContainer {
width:800px;
height:600px;
background-color:#EEEEEE;
}
#sourceDiv { float: left; border: 2px solid blue}
#targetDiv { float: right;border: 2px solid red}
filter1.html中HTML源代碼:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="chrome=IE8">
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Canvas Filter Demo</title>
<link href="default.css" rel="stylesheet" />
<script src="gloomyfishfilter.js"></scrip>
</head>
<body>
<h1>HTML Canvas Image Process - By Gloomy Fish</h1>
<div id="svgContainer">
<div id="sourceDiv">
<img id="source" src="../test.png" />
</div>
<div id="targetDiv">
<canvas id="target"></canvas>
</div>
</div>
<div id="btn-group">
<button type="button" id="invert-button">反色</button>
<button type="button" id="adjust-button">灰色調</button>
<button type="button" id="blur-button">模糊</button>
<button type="button" id="relief-button">浮雕</button>
<button type="button" id="diaoke-button">雕刻</button>
<button type="button" id="mirror-button">鏡像</button>
</div>
</body>
</html>
filter1.html中JavaScript源代碼:
var tempContext=null; // global variable 2d context
window.onload=function() {
var source=document.getElementById("source");
var canvas=document.getElementById("target");
canvas.width=source.clientWidth;
canvas.height=source.clientHeight;
if (!canvas.getContext) {
console.log("Canvas not supported. Please install a HTML5 compatible browser.");
return;
}
// get 2D context of canvas and draw image
tempContext=canvas.getContext("2d");
tempContext.drawImage(source, 0, 0, canvas.width, canvas.height);
// initialization actions
var inButton=document.getElementById("invert-button");
var adButton=document.getElementById("adjust-button");
var blurButton=document.getElementById("blur-button");
var reButton=document.getElementById("relief-button");
var dkButton=document.getElementById("diaoke-button");
var mirrorButton=document.getElementById("mirror-button");
// bind mouse click event
bindButtonEvent(inButton, "click", invertColor);
bindButtonEvent(adButton, "click", adjustColor);
bindButtonEvent(blurButton, "click", blurImage);
bindButtonEvent(reButton, "click", fudiaoImage);
bindButtonEvent(dkButton, "click", kediaoImage);
bindButtonEvent(mirrorButton, "click", mirrorImage);
}
function bindButtonEvent(element, type, handler)
{
if(element.addEventListener) {
element.addEventListener(type, handler, false);
} else {
element.attachEvent('on'+type, handler); // for IE6,7,8
}
}
function invertColor() {
var canvas=document.getElementById("target");
var len=canvas.width * canvas.height * 4;
var canvasData=tempContext.getImageData(0, 0, canvas.width, canvas.height);
var binaryData=canvasData.data;
// Processing all the pixels
gfilter.colorInvertProcess(binaryData, len);
// Copying back canvas data to canvas
tempContext.putImageData(canvasData, 0, 0);
}
function adjustColor() {
var canvas=document.getElementById("target");
var len=canvas.width * canvas.height * 4;
var canvasData=tempContext.getImageData(0, 0, canvas.width, canvas.height);
var binaryData=canvasData.data;
// Processing all the pixels
gfilter.colorAdjustProcess(binaryData, len);
// Copying back canvas data to canvas
tempContext.putImageData(canvasData, 0, 0);
}
function blurImage()
{
var canvas=document.getElementById("target");
var len=canvas.width * canvas.height * 4;
var canvasData=tempContext.getImageData(0, 0, canvas.width, canvas.height);
// Processing all the pixels
gfilter.blurProcess(tempContext, canvasData);
// Copying back canvas data to canvas
tempContext.putImageData(canvasData, 0, 0);
}
function fudiaoImage()
{
var canvas=document.getElementById("target");
var len=canvas.width * canvas.height * 4;
var canvasData=tempContext.getImageData(0, 0, canvas.width, canvas.height);
// Processing all the pixels
gfilter.reliefProcess(tempContext, canvasData);
// Copying back canvas data to canvas
tempContext.putImageData(canvasData, 0, 0);
}
function kediaoImage()
{
var canvas=document.getElementById("target");
var len=canvas.width * canvas.height * 4;
var canvasData=tempContext.getImageData(0, 0, canvas.width, canvas.height);
// Processing all the pixels
gfilter.diaokeProcess(tempContext, canvasData);
// Copying back canvas data to canvas
tempContext.putImageData(canvasData, 0, 0);
}
function mirrorImage()
{
var canvas=document.getElementById("target");
var len=canvas.width * canvas.height * 4;
var canvasData=tempContext.getImageData(0, 0, canvas.width, canvas.height);
// Processing all the pixels
gfilter.mirrorProcess(tempContext, canvasData);
// Copying back canvas data to canvas
tempContext.putImageData(canvasData, 0, 0);
}
濾鏡源代碼(gloomyfishfilter.js):
var gfilter={
type: "canvas",
name: "filters",
author: "zhigang",
getInfo: function () {
return this.author + ' ' + this.type + ' ' + this.name;
},
/**
* invert color value of pixel, new pixel=RGB(255-r, 255-g, 255 - b)
*
* @param binaryData - canvas's imagedata.data
* @param l - length of data (width * height of image data)
*/
colorInvertProcess: function(binaryData, l) {
for (var i=0; i < l; i +=4) {
var r=binaryData[i];
var g=binaryData[i + 1];
var b=binaryData[i + 2];
binaryData[i]=255-r;
binaryData[i + 1]=255-g;
binaryData[i + 2]=255-b;
}
},
/**
* adjust color values and make it more darker and gray...
*
* @param binaryData
* @param l
*/
colorAdjustProcess: function(binaryData, l) {
for (var i=0; i < l; i +=4) {
var r=binaryData[i];
var g=binaryData[i + 1];
var b=binaryData[i + 2];
binaryData[i]=(r * 0.272) + (g * 0.534) + (b * 0.131);
binaryData[i + 1]=(r * 0.349) + (g * 0.686) + (b * 0.168);
binaryData[i + 2]=(r * 0.393) + (g * 0.769) + (b * 0.189);
}
},
/**
* deep clone image data of canvas
*
* @param context
* @param src
* @returns
*/
copyImageData: function(context, src)
{
var dst=context.createImageData(src.width, src.height);
dst.data.set(src.data);
return dst;
},
/**
* convolution - keneral size 5*5 - blur effect filter(模糊效果)
*
* @param context
* @param canvasData
*/
blurProcess: function(context, canvasData) {
console.log("Canvas Filter - blur process");
var tempCanvasData=this.copyImageData(context, canvasData);
var sumred=0.0, sumgreen=0.0, sumblue=0.0;
for ( var x=0; x < tempCanvasData.width; x++) {
for ( var y=0; y < tempCanvasData.height; y++) {
// Index of the pixel in the array
var idx=(x + y * tempCanvasData.width) * 4;
for(var subCol=-2; subCol<=2; subCol++) {
var colOff=subCol + x;
if(colOff <0 || colOff >=tempCanvasData.width) {
colOff=0;
}
for(var subRow=-2; subRow<=2; subRow++) {
var rowOff=subRow + y;
if(rowOff < 0 || rowOff >=tempCanvasData.height) {
rowOff=0;
}
var idx2=(colOff + rowOff * tempCanvasData.width) * 4;
var r=tempCanvasData.data[idx2 + 0];
var g=tempCanvasData.data[idx2 + 1];
var b=tempCanvasData.data[idx2 + 2];
sumred +=r;
sumgreen +=g;
sumblue +=b;
}
}
// calculate new RGB value
var nr=(sumred / 25.0);
var ng=(sumgreen / 25.0);
var nb=(sumblue / 25.0);
// clear previous for next pixel point
sumred=0.0;
sumgreen=0.0;
sumblue=0.0;
// assign new pixel value
canvasData.data[idx + 0]=nr; // Red channel
canvasData.data[idx + 1]=ng; // Green channel
canvasData.data[idx + 2]=nb; // Blue channel
canvasData.data[idx + 3]=255; // Alpha channel
}
}
},
/**
* after pixel value - before pixel value + 128
* 浮雕效果
*/
reliefProcess: function(context, canvasData) {
console.log("Canvas Filter - relief process");
var tempCanvasData=this.copyImageData(context, canvasData);
for ( var x=1; x < tempCanvasData.width-1; x++)
{
for ( var y=1; y < tempCanvasData.height-1; y++)
{
// Index of the pixel in the array
var idx=(x + y * tempCanvasData.width) * 4;
var bidx=((x-1) + y * tempCanvasData.width) * 4;
var aidx=((x+1) + y * tempCanvasData.width) * 4;
// calculate new RGB value
var nr=tempCanvasData.data[aidx + 0] - tempCanvasData.data[bidx + 0] + 128;
var ng=tempCanvasData.data[aidx + 1] - tempCanvasData.data[bidx + 1] + 128;
var nb=tempCanvasData.data[aidx + 2] - tempCanvasData.data[bidx + 2] + 128;
nr=(nr < 0) ? 0 : ((nr >255) ? 255 : nr);
ng=(ng < 0) ? 0 : ((ng >255) ? 255 : ng);
nb=(nb < 0) ? 0 : ((nb >255) ? 255 : nb);
// assign new pixel value
canvasData.data[idx + 0]=nr; // Red channel
canvasData.data[idx + 1]=ng; // Green channel
canvasData.data[idx + 2]=nb; // Blue channel
canvasData.data[idx + 3]=255; // Alpha channel
}
}
},
/**
* before pixel value - after pixel value + 128
* 雕刻效果
*
* @param canvasData
*/
diaokeProcess: function(context, canvasData) {
console.log("Canvas Filter - process");
var tempCanvasData=this.copyImageData(context, canvasData);
for ( var x=1; x < tempCanvasData.width-1; x++)
{
for ( var y=1; y < tempCanvasData.height-1; y++)
{
// Index of the pixel in the array
var idx=(x + y * tempCanvasData.width) * 4;
var bidx=((x-1) + y * tempCanvasData.width) * 4;
var aidx=((x+1) + y * tempCanvasData.width) * 4;
// calculate new RGB value
var nr=tempCanvasData.data[bidx + 0] - tempCanvasData.data[aidx + 0] + 128;
var ng=tempCanvasData.data[bidx + 1] - tempCanvasData.data[aidx + 1] + 128;
var nb=tempCanvasData.data[bidx + 2] - tempCanvasData.data[aidx + 2] + 128;
nr=(nr < 0) ? 0 : ((nr >255) ? 255 : nr);
ng=(ng < 0) ? 0 : ((ng >255) ? 255 : ng);
nb=(nb < 0) ? 0 : ((nb >255) ? 255 : nb);
// assign new pixel value
canvasData.data[idx + 0]=nr; // Red channel
canvasData.data[idx + 1]=ng; // Green channel
canvasData.data[idx + 2]=nb; // Blue channel
canvasData.data[idx + 3]=255; // Alpha channel
}
}
},
/**
* mirror reflect
*
* @param context
* @param canvasData
*/
mirrorProcess : function(context, canvasData) {
console.log("Canvas Filter - process");
var tempCanvasData=this.copyImageData(context, canvasData);
for ( var x=0; x < tempCanvasData.width; x++) // column
{
for ( var y=0; y < tempCanvasData.height; y++) // row
{
// Index of the pixel in the array
var idx=(x + y * tempCanvasData.width) * 4;
var midx=(((tempCanvasData.width -1) - x) + y * tempCanvasData.width) * 4;
// assign new pixel value
canvasData.data[midx + 0]=tempCanvasData.data[idx + 0]; // Red channel
canvasData.data[midx + 1]=tempCanvasData.data[idx + 1]; ; // Green channel
canvasData.data[midx + 2]=tempCanvasData.data[idx + 2]; ; // Blue channel
canvasData.data[midx + 3]=255; // Alpha channel
}
}
},
};
感謝閱讀,如果你覺得我今天分享的內容,不錯,請點一個贊,謝謝!!
*請認真填寫需求信息,我們會在24小時內與您取得聯系。