Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* -------------------- Data -------------------- */
- const sobelLeftEdge = [
- [-1,0,1],
- [-2,0,2],
- [-1,0,1],
- ]
- const sobelRightEdge = [
- [1,0,-1],
- [2,0,-2],
- [1,0,-1],
- ]
- const sobelBottomEdge = [
- [1,2,1],
- [0,0,0],
- [-1,-2,-1],
- ]
- const sobelTopEdge = [
- [-1,-2,-1],
- [0,0,0],
- [1,2,1],
- ]
- const blurMatrix = [
- [1/9,1/9,1/9],
- [1/9,1/9,1/9],
- [1/9,1/9,1/9]
- ]
- const outlineMatrix = [
- [-1,-1,-1],
- [-1,8,-1],
- [-1,-1,-1],
- ]
- const sharpenMatrix = [
- [-1,-1,-1],
- [-1,9,-1],
- [-1,-1,-1],
- ]
- /*-------------------- Google Docs UI Callbacks -------------------- */
- function onOpen() {
- var ui = SpreadsheetApp.getUi();
- //Create the custom menu
- ui.createMenu('Convolutions')
- .addSubMenu(
- ui.createMenu('Sobel')
- .addItem('Left edge','sobelLeft')
- .addItem('Right edge','sobelRight')
- .addItem('Top edge','sobelTop')
- .addItem('Bottom edge','sobelBottom')
- )
- .addSubMenu(
- ui.createMenu("Effects")
- .addItem('Blur','doBlur')
- .addItem('Sharpen','doSharpen')
- .addItem('Outline','doOutline')
- )
- .addItem('Highlight','applyHighlight')
- .addToUi()
- }
- /*------------------- Menu Callbacks -------------------- */
- function sobelRight(){
- applyMatrix(sobelRightEdge)
- }
- function sobelTop(){
- applyMatrix(sobelTopEdge)
- }
- function sobelLeft(){
- applyMatrix(sobelLeftEdge)
- }
- function sobelBottom(){
- applyMatrix(sobelBottomEdge)
- }
- function doSharpen(){
- let activeRange = SpreadsheetApp.getActiveSheet().getSelection().getActiveRange()
- let reply = SpreadsheetApp.getUi().prompt("Amount (0%-100%)")
- let amount = parseFloat(reply.getResponseText())
- amount = (amount/100)
- //--------------------
- //Perform the math
- //--------------------
- let grid = activeRange.getValues()
- sharpMask = convolute(grid,sharpenMatrix)
- for( y = 0; y < grid.length; y++ ){
- for ( x = 0; x < grid[y].length; x++ ){
- grid[y][x] += sharpMask[y][x] * amount
- }
- }
- grid = clamp(grid,0,255)
- grid = quantize(grid)
- //--------------------
- //Apply the grid
- //--------------------
- activeRange.setValues(grid)
- highlightRange(activeRange)
- }
- function doOutline(){
- applyMatrix(outlineMatrix)
- }
- function doBlur(){
- applyMatrix(blurMatrix)
- }
- /*-------------------- Spreadsheet functions -------------------- */
- function applyMatrix(matrix){
- let activeRange = SpreadsheetApp.getActiveSheet().getSelection().getActiveRange()
- //--------------------
- //Perform the math
- //--------------------
- let grid = activeRange.getValues()
- grid = convolute(grid,matrix)
- grid = clamp(grid,0,255)
- grid = quantize(grid)
- //--------------------
- //Apply the grid
- //--------------------
- activeRange.setValues(grid)
- highlightRange(activeRange)
- }
- function applyHighlight(){
- activeRange = SpreadsheetApp.getActiveSheet().getSelection().getActiveRange()
- highlightRange(activeRange)
- }
- function highlightRange(activeRange){
- let grid = activeRange.getValues()
- let color = []
- for( y = 0; y < grid.length; y++ ){
- color[y] = []
- for ( x = 0; x < grid[y].length; x++ ){
- let i = Math.max(0,Math.min(255,grid[y][x]))
- color[y][x] = `rgb(${i},${i},${i})`
- }
- }
- activeRange.setBackgrounds(color)
- }
- /*-------------------- Math -------------------- */
- //Clamp every item in a grid
- function clamp(grid,lowest,highest){
- for (y = 0; y < grid.length ; y++ ){
- for ( x = 0; x < grid[y].length ; x++ ){
- grid[y][x] = Math.max(lowest,Math.min(highest,grid[y][x]))
- }
- }
- return grid
- }
- //Floor every item in a grid
- function quantize(grid){
- for (y = 0; y < grid.length ; y++ ){
- for ( x = 0; x < grid[y].length ; x++ ){
- grid[y][x] = Math.floor(grid[y][x])
- }
- }
- return grid
- }
- //Apply a convolution matrix to a grid
- function convolute(inputGrid,matrix) {
- let gridHeight = inputGrid.length
- if ( gridHeight <= 1 ) throw "Selected items must be larger than 1 tall"
- let gridWidth = inputGrid[0].length
- if ( gridWidth <= 1 ) throw "Selected items must be larger than 1 wide"
- let matrixHeight = matrix.length
- if ( matrixHeight <= 1 ) throw "Matrix must be at least 1 cell tall"
- if ( matrixHeight%2 == 0 ) throw "Matrix height must be an odd number of cells"
- let matrixWidth = matrix[0].length
- if ( matrixWidth <= 1 ) throw "Matrix must be at least 1 cell width"
- if ( matrixWidth%2 == 0 ) throw "Matrix width must be an odd number of cells"
- //Calculate temporary values for working with the matrix
- let halfMatrixHeight = Math.floor(matrixHeight/2)
- let halfMatrixWidth = Math.floor(matrixWidth/2)
- //Create a new grid to return so our values don't influence
- //eachother during the sweep
- let newGrid = []
- for ( gridY = 0; gridY < gridHeight; gridY++ ){
- newGrid[gridY] = []
- for ( gridX = 0; gridX < gridWidth; gridX++ ){
- newGrid[gridY][gridX] = 0
- }
- }
- //for every item in the grid
- for ( gridY = 1; gridY < gridHeight - 1; gridY++ ){
- for ( gridX = 1; gridX < gridWidth - 1; gridX++ ){
- //We'll sum up the values we sampled from nearby cells
- let sum = 0
- //for every item in the matrix
- for ( matrixY = 0; matrixY < matrixHeight; matrixY++ ){
- for ( matrixX = 0; matrixX < matrixWidth; matrixX++ ){
- //calculate the offset in the main grid
- let offsetY = matrixY - halfMatrixHeight
- let offsetX = matrixX - halfMatrixWidth
- //grab the value from the INPUT grid + offset
- let gridValue = inputGrid[gridY+offsetY][gridX+offsetX]
- //grab the value from the matrix
- let matrixValue = matrix[matrixY][matrixX]
- //multiply the grid value * matrix value
- //and add to the sum
- sum += ( gridValue * matrixValue )
- }
- }
- //set the NEW grid item
- newGrid[gridY][gridX] = sum
- }
- }
- return newGrid
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement