{"version":3,"sources":["jsdelivr-header.js","/npm/nudity@0.0.2/index.js"],"names":[],"mappings":"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","file":"/npm/nudity@0.0.2/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/nudity@0.0.2/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","/*\n * Nudity - Node.js nudity detector based on Nude.js\n * \n * Author: Harry Lee\n * Version: 0.0.1\n * License: MIT License\n */\n\nvar Canvas = require('canvas');\nvar Image = Image = Canvas.Image;\nvar fs = require('fs');\n\nexports.scanFile = function(path, cb) {\n\tfs.readFile(path, function(err, data) {\n\t\tif (err)\n\t\t\treturn cb(err);\n\n\t\texports.scanData(data, cb);\n\t});\n};\n\nexports.scanData = function(data, cbPrimary) {\n\t// private var definition\n\tvar canvas = null,\n\tctx = null,\n\tskinRegions = [],\n\t// private functions\n\tinitCanvas = function(){\n\t\tcanvas = new Canvas();\n\t\tctx = canvas.getContext('2d');\n\t},\n\tloadImage = function(){\n\t\tvar img = new Image;\n\t\timg.src = data;\n\t\t// apply the width and height to the canvas element\n\t\tcanvas.width = img.width;\n\t\tcanvas.height = img.height;\n\t\t// reset the result function\n\t\t// draw the image into the canvas element\n\t\tctx.drawImage(img, 0, 0);\n\t},\n\tscanImage = function(cb){\n\t\tprocess.nextTick(function() {\n\t\t\t// get the image data\n\t\t\tvar image = ctx.getImageData(0, 0, canvas.width, canvas.height),\n\t\t\timageData = image.data;\n\t\t\tskinMap = [],\n\t\t\t\tdetectedRegions = [],\n\t\t\t\tmergeRegions = [],\n\t\t\t\twidth = canvas.width,\n\t\t\t\tlastFrom = -1,\n\t\t\t\tlastTo = -1;\n\n\n\t\t\tvar addMerge = function(from, to){\n\t\t\t\tlastFrom = from;\n\t\t\t\tlastTo = to;\n\t\t\t\tvar len = mergeRegions.length,\n\t\t\t\tfromIndex = -1,\n\t\t\t\ttoIndex = -1;\n\n\n\t\t\t\twhile(len--){\n\n\t\t\t\t\tvar region = mergeRegions[len],\n\t\t\t\t\trlen = region.length;\n\n\t\t\t\t\twhile(rlen--){\n\n\t\t\t\t\t\tif(region[rlen] == from){\n\t\t\t\t\t\t\tfromIndex = len;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif(region[rlen] == to){\n\t\t\t\t\t\t\ttoIndex = len;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif(fromIndex != -1 && toIndex != -1 && fromIndex == toIndex){\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif(fromIndex == -1 && toIndex == -1){\n\n\t\t\t\t\tmergeRegions.push([from, to]);\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif(fromIndex != -1 && toIndex == -1){\n\n\t\t\t\t\tmergeRegions[fromIndex].push(to);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif(fromIndex == -1 && toIndex != -1){\n\t\t\t\t\tmergeRegions[toIndex].push(from);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif(fromIndex != -1 && toIndex != -1 && fromIndex != toIndex){\n\t\t\t\t\tmergeRegions[fromIndex] = mergeRegions[fromIndex].concat(mergeRegions[toIndex]);\n\t\t\t\t\t//mergeRegions.remove(toIndex);\n\t\t\t\t\tmergeRegions.splice(toIndex, 1);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t};\n\n\t\t\t// iterate the image from the top left to the bottom right\n\t\t\tvar length = imageData.length,\n\t\t\twidth = canvas.width;\n\n\t\t\tfor(var i = 0, u = 1; i < length; i+=4, u++){\n\n\t\t\t\tvar r = imageData[i],\n\t\t\t\tg = imageData[i+1],\n\t\t\t\tb = imageData[i+2],\n\t\t\t\tx = (u>width)?((u%width)-1):u,\n\t\t\t\ty = (u>width)?(Math.ceil(u/width)-1):1;\n\n\t\t\t\tif(classifySkin(r, g, b)){ // \n\t\t\t\t\tskinMap.push({\"id\": u, \"skin\": true, \"region\": 0, \"x\": x, \"y\": y, \"checked\": false});\n\n\t\t\t\t\tvar region = -1,\n\t\t\t\t\tcheckIndexes = [u-2, (u-width)-2, u-width-1, (u-width)],\n\t\t\t\t\tchecker = false;\n\n\t\t\t\t\tfor(var o = 0; o < 4; o++){\n\t\t\t\t\t\tvar index = checkIndexes[o];\n\t\t\t\t\t\tif(skinMap[index] && skinMap[index].skin){\n\t\t\t\t\t\t\tif(skinMap[index].region!=region && region!=-1 && lastFrom!=region && lastTo!=skinMap[index].region){\n\t\t\t\t\t\t\t\taddMerge(region, skinMap[index].region);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tregion = skinMap[index].region;\n\t\t\t\t\t\t\tchecker = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif(!checker){\n\t\t\t\t\t\tskinMap[u-1].region = detectedRegions.length;\n\t\t\t\t\t\tdetectedRegions.push([skinMap[u-1]]);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}else{\n\n\t\t\t\t\t\tif(region > -1){\n\n\t\t\t\t\t\t\tif(!detectedRegions[region]){\n\t\t\t\t\t\t\t\tdetectedRegions[region] = [];\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tskinMap[u-1].region = region;\t\t\t\t\t\n\t\t\t\t\t\t\tdetectedRegions[region].push(skinMap[u-1]);\n\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t}else{\n\t\t\t\t\tskinMap.push({\"id\": u, \"skin\": false, \"region\": 0, \"x\": x, \"y\": y, \"checked\": false});\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tmerge(detectedRegions, mergeRegions);\n\t\t\t\n\t\t\treturn cb(null, analyseRegions());\n\t\t}); // process.nextTick()\n\t},\n\t// function for merging detected regions\n\tmerge = function(detectedRegions, mergeRegions){\n\n\t\tvar length = mergeRegions.length,\n\t\tdetRegions = [];\n\n\n\t\t// merging detected regions \n\t\twhile(length--){\n\n\t\t\tvar region = mergeRegions[length],\n\t\t\trlen = region.length;\n\n\t\t\tif(!detRegions[length])\n\t\t\t\tdetRegions[length] = [];\n\n\t\t\twhile(rlen--){\n\t\t\t\tvar index = region[rlen];\n\t\t\t\tdetRegions[length] = detRegions[length].concat(detectedRegions[index]);\n\t\t\t\tdetectedRegions[index] = [];\n\t\t\t}\n\n\t\t}\n\n\t\t// push the rest of the regions to the detRegions array\n\t\t// (regions without merging)\n\t\tvar l = detectedRegions.length;\n\t\twhile(l--){\n\t\t\tif(detectedRegions[l].length > 0){\n\t\t\t\tdetRegions.push(detectedRegions[l]);\n\t\t\t}\n\t\t}\n\n\t\t// clean up\n\t\tclearRegions(detRegions);\n\n\t},\n\t// clean up function\n\t// only pushes regions which are bigger than a specific amount to the final result\n\tclearRegions = function(detectedRegions){\n\n\t\tvar length = detectedRegions.length;\n\n\t\tfor(var i=0; i < length; i++){\n\t\t\tif(detectedRegions[i].length > 30){\n\t\t\t\tskinRegions.push(detectedRegions[i]);\n\t\t\t}\n\t\t}\n\n\t},\n\tanalyseRegions = function(){\n\n\t\t// sort the detected regions by size\n\t\tvar length = skinRegions.length,\n\t\ttotalPixels = canvas.width * canvas.height,\n\t\ttotalSkin = 0;\n\n\t\t// if there are less than 3 regions\n\t\tif(length < 3){\n\t\t\treturn false;\n\t\t}\n\n\t\t// sort the skinRegions with bubble sort algorithm\n\t\t(function(){ \n\t\t\tvar sorted = false;\n\t\t\twhile(!sorted){\n\t\t\t\tsorted = true;\n\t\t\t\tfor(var i = 0; i < length-1; i++){\n\t\t\t\t\tif(skinRegions[i].length < skinRegions[i+1].length){\n\t\t\t\t\t\tsorted = false;\n\t\t\t\t\t\tvar temp = skinRegions[i];\n\t\t\t\t\t\tskinRegions[i] = skinRegions[i+1];\n\t\t\t\t\t\tskinRegions[i+1] = temp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t})();\n\n\t\t// count total skin pixels\n\t\twhile(length--){\n\t\t\ttotalSkin += skinRegions[length].length;\n\t\t}\n\n\t\t// check if there are more than 15% skin pixel in the image\n\t\tif((totalSkin/totalPixels)*100 < 15){\n\t\t\t// if the percentage lower than 15, it's not nude!\n\t\t\t//console.log(\"it's not nude :) - total skin percent is \"+((totalSkin/totalPixels)*100)+\"% \");\n\t\t\treturn false;\n\t\t}\n\n\n\t\t// check if the largest skin region is less than 35% of the total skin count\n\t\t// AND if the second largest region is less than 30% of the total skin count\n\t\t// AND if the third largest region is less than 30% of the total skin count\n\t\tif((skinRegions[0].length/totalSkin)*100 < 35 \n\t\t\t\t&& (skinRegions[1].length/totalSkin)*100 < 30\n\t\t\t\t&& (skinRegions[2].length/totalSkin)*100 < 30){\n\t\t\t// the image is not nude.\n\t\t\t//console.log(\"it's not nude :) - less than 35%,30%,30% skin in the biggest areas :\" + ((skinRegions[0].length/totalSkin)*100) + \"%, \" + ((skinRegions[1].length/totalSkin)*100)+\"%, \"+((skinRegions[2].length/totalSkin)*100)+\"%\");\n\t\t\treturn false;\n\t\t}\n\n\t\t// check if the number of skin pixels in the largest region is less than 45% of the total skin count\n\t\tif((skinRegions[0].length/totalSkin)*100 < 45){\n\t\t\t// it's not nude\n\t\t\t//console.log(\"it's not nude :) - the biggest region contains less than 45%: \"+((skinRegions[0].length/totalSkin)*100)+\"%\");\n\t\t\treturn false;\n\t\t}\n\n\t\t// TODO:\n\t\t// build the bounding polygon by the regions edge values:\n\t\t// Identify the leftmost, the uppermost, the rightmost, and the lowermost skin pixels of the three largest skin regions.\n\t\t// Use these points as the corner points of a bounding polygon.\n\n\t\t// TODO:\n\t\t// check if the total skin count is less than 30% of the total number of pixels\n\t\t// AND the number of skin pixels within the bounding polygon is less than 55% of the size of the polygon\n\t\t// if this condition is true, it's not nude.\n\n\t\t// TODO: include bounding polygon functionality\n\t\t// if there are more than 60 skin regions and the average intensity within the polygon is less than 0.25\n\t\t// the image is not nude\n\t\tif(skinRegions.length > 60){\n\t\t\t//console.log(\"it's not nude :) - more than 60 skin regions\");\n\t\t\treturn false;\n\t\t}\n\n\n\t\t// otherwise it is nude\n\t\treturn true;\n\n\t},\n\t// colorizeRegions function is for testdevelopment only\n\t// the detected skinRegions will be painted in random colors (one color per region)\n\tcolorizeRegions = function(){\n\n\t\tvar length = skinRegions.length;\n\t\tfor(var i = 0; i < length; i++){\n\n\t\t\tvar region = skinRegions[i],\n\t\t\tregionLength = region.length,\n\t\t\trandR = Math.ceil(Math.random()*255),\n\t\t\trandG = Math.ceil(Math.random()*255),\n\t\t\trangB = Math.ceil(Math.random()*255);\n\n\t\t\tfor(var o = 0; o < regionLength; o++){\n\n\t\t\t\tvar pixel = ctx.getImageData(region[o].x, region[o].y, 1,1),\n\t\t\t\tpdata = pixel.data;\n\n\t\t\t\tpdata[0] = randR;\n\t\t\t\tpdata[1] = randG;\n\t\t\t\tpdata[2] = rangB;\n\n\t\t\t\tpixel.data = pdata;\n\n\t\t\t\tctx.putImageData(pixel, region[o].x, region[o].y);\n\n\t\t\t}\n\n\t\t}\n\n\t}, \n\tclassifySkin = function(r, g, b){\n\t\t// A Survey on Pixel-Based Skin Color Detection Techniques\n\t\tvar rgbClassifier = ((r>95) && (g>40 && g <100) && (b>20) && ((Math.max(r,g,b) - Math.min(r,g,b)) > 15) && (Math.abs(r-g)>15) && (r > g) && (r > b)),\n\t\tnurgb = toNormalizedRgb(r, g, b),\n\t\tnr = nurgb[0],\n\t\tng = nurgb[1],\n\t\tnb = nurgb[2],\n\t\tnormRgbClassifier = (((nr/ng)>1.185) && (((r*b)/(Math.pow(r+g+b,2))) > 0.107) && (((r*g)/(Math.pow(r+g+b,2))) > 0.112)),\n\t\t//hsv = toHsv(r, g, b),\n\t\t//h = hsv[0]*100,\n\t\t//s = hsv[1],\n\t\t//hsvClassifier = (h < 50 && h > 0 && s > 0.23 && s < 0.68);\n\t\thsv = toHsvTest(r, g, b),\n\t\th = hsv[0],\n\t\ts = hsv[1],\n\t\thsvClassifier = (h > 0 && h < 35 && s > 0.23 && s < 0.68);\n\t\t/*\n\t\t * ycc doesnt work\n\n\t\tycc = toYcc(r, g, b),\n\t\ty = ycc[0],\n\t\tcb = ycc[1],\n\t\tcr = ycc[2],\n\t\tyccClassifier = ((y > 80) && (cb > 77 && cb < 127) && (cr > 133 && cr < 173));\n\t\t*/\n\n\t\treturn (rgbClassifier || normRgbClassifier || hsvClassifier); // \n\t},\n\ttoYcc = function(r, g, b){\n\t\tr/=255,g/=255,b/=255;\n\t\tvar y = 0.299*r + 0.587*g + 0.114*b,\n\t\tcr = r - y,\n\t\tcb = b - y;\n\n\t\treturn [y, cr, cb];\n\t},\n\ttoHsv = function(r, g, b){\n\t\treturn [\n\t\t\t\t// hue\n\t\t\t\tMath.acos((0.5*((r-g)+(r-b)))/(Math.sqrt((Math.pow((r-g),2)+((r-b)*(g-b)))))),\n\t\t\t\t// saturation\n\t\t\t\t1-(3*((Math.min(r,g,b))/(r+g+b))),\n\t\t\t\t// value\n\t\t\t\t(1/3)*(r+g+b)\n\t\t\t\t];\n\t},\n\ttoHsvTest = function(r, g, b){\n\t\tvar h = 0,\n\t\tmx = Math.max(r, g, b),\n\t\tmn = Math.min(r, g, b),\n\t\tdif = mx - mn;\n\n\t\tif(mx == r){\n\t\t\th = (g - b)/dif;\n\t\t}else if(mx == g){\n\t\t\th = 2+((g - r)/dif)\n\t\t}else{\n\t\t\th = 4+((r - g)/dif);\n\t\t}\n\t\th = h*60;\n\t\tif(h < 0){\n\t\t\th = h+360;\n\t\t}\n\n\t\treturn [h, 1-(3*((Math.min(r,g,b))/(r+g+b))),(1/3)*(r+g+b)] ;\t\n\n\t},\n\ttoNormalizedRgb = function(r, g, b){\n\t\tvar sum = r+g+b;\n\t\treturn [(r/sum), (g/sum), (b/sum)];\n\t};\n\t\n\t\n\tinitCanvas();\n\tloadImage();\n\tscanImage(function(err, result) {\n\t\tif (err)\n\t\t\treturn cbPrimary(err);\n\n\t\treturn cbPrimary(null, result);\n\t});\n};\n"]}