Open yyman001 opened 6 years ago
使用node jimp 处理图片,并生成裁剪后的图片
var path = require("path")
var Jimp = require("jimp");
let test_img = 'test/n2.png'
// open a file called "lenna.png"
// Jimp.read(test_img, function (err, lenna) {
// if (err) throw err;
// lenna
// .autocrop(0.0003, false, function(){ console.log('callback') })
// .write("test/render.png"); // save
// });
// image.getBuffer( mime, cb )
// image.getBase64( mime, cb )
// image.getPixelIndex(x, y);
// todo
// 生成图片配置文件json [原图片信息-尺寸大小/裁剪后的坐标信息,以及大小]
// 批量读取图片
// 批量裁剪生成图片
Jimp.read(test_img).then(function (image) {
// do stuff with the image
let post = {}
let data = image.bitmap.data,
imgWidth = image.bitmap.width,
imgHeight = image.bitmap.height,
getRBG = function(x, y) {
var offset = imgWidth * y + x;
return {
red: data[offset * 4],
green: data[offset * 4 + 1],
blue: data[offset * 4 + 2],
opacity: data[offset * 4 + 3]
};
},
isWhite = function(rgb) {
// many images contain noise, as the white is not a pure #fff white
return rgb.red > 200 && rgb.green > 200 && rgb.blue > 200;
},
isTransparent = function(rgba){
return rgba.opacity === 0
},
scanY = function(fromTop) {
var offset = fromTop ? 1 : -1;
// loop through each row
for (
var y = fromTop ? 0 : imgHeight - 1;
fromTop ? y < imgHeight : y > -1;
y += offset
) {
// loop through each column
for (var x = 0; x < imgWidth; x++) {
var rgb = getRBG(x, y);
if (!isWhite(rgb) && !isTransparent(rgb)) {
if (fromTop) {
return y;
} else {
return Math.min(y + 1, imgHeight - 1);
}
}
}
}
return null; // all image is white
},
scanX = function(fromLeft) {
var offset = fromLeft ? 1 : -1;
// loop through each column
for (
var x = fromLeft ? 0 : imgWidth - 1;
fromLeft ? x < imgWidth : x > -1;
x += offset
) {
// loop through each row
for (var y = 0; y < imgHeight; y++) {
var rgb = getRBG(x, y);
if (!isWhite(rgb) && !isTransparent(rgb)) {
if (fromLeft) {
return x;
} else {
return Math.min(x + 1, imgWidth - 1);
}
}
}
}
return null; // all image is white
};
var cropTop = scanY(true),
cropBottom = scanY(false),
cropLeft = scanX(true),
cropRight = scanX(false),
cropWidth = cropRight - cropLeft,
cropHeight = cropBottom - cropTop;
post.top = cropTop;
post.left = cropLeft;
post.right = cropRight;
post.bottom = cropBottom;
post.width = cropWidth;
post.height = cropHeight;
console.log(
"cropTop:",
cropTop,
'cropBottom:',
cropBottom,
"cropLeft:",
cropLeft,
'cropRight:',
cropRight,
'cropWidth:',cropWidth,
'cropHeight:',cropHeight
);
// 拷贝对象生成裁剪图片
image.clone().crop(post.left,post.top, post.width,post.height)
.write("test/1.png");
}).catch(function (err) {
// handle an exception
console.log('error:', err)
});
可以使用版本/生成配置会报错,具体不清,查了很多都没解决,暂时就这样
var fs = require('fs')
var path = require("path")
var Jimp = require("jimp")
let directory = 'test'
let dir = path.resolve(directory)
// image.getBuffer( mime, cb )
// image.getBase64( mime, cb )
// image.getPixelIndex(x, y);
// image.getExtension() 后缀
// todo
// 生成图片配置文件json [原图片信息-尺寸大小/裁剪后的坐标信息,以及大小]
// 批量读取图片
// 批量裁剪生成图片
var spriteJson = {
name: '裁剪图片信息json',
version: '1.0',
sprite: []
}
var outputFilename = path.resolve(`${directory}/spriteMap.json`)
// 雪碧图信息
let spriteJsonArray = []
let imagesArray = []
// 记录扫描文件路径
let fileList = []
function walk(path) {
var dirList = fs.readdirSync(path);
dirList.forEach(function (item) {
if (fs.statSync(path + '/' + item).isFile()) {
fileList.push(path + '/' + item);
}
});
dirList.forEach(function (item) {
if (fs.statSync(path + '/' + item).isDirectory()) {
walk(path + '/' + item);
}
});
}
walk(dir)
console.log(fileList);
// spritePath data => 'D:\\gulp\\test/top.png'
function cutSprite(spritePath) {
return new Promise((resolve, reject) => {
Jimp.read(spritePath).then(function (image) {
// do stuff with the image
let post = {}
let path = spritePath.split('/')[0]
post.name = spritePath.split('/').slice(-1)[0]
post.outPutDir = path
post.filePath = spritePath
post.ow = image.bitmap.width
post.oh = image.bitmap.height
let data = image.bitmap.data,
imgWidth = image.bitmap.width,
imgHeight = image.bitmap.height,
getRBG = function (x, y) {
var offset = imgWidth * y + x;
return {
red: data[offset * 4],
green: data[offset * 4 + 1],
blue: data[offset * 4 + 2],
opacity: data[offset * 4 + 3]
};
},
isWhite = function (rgb) {
// many images contain noise, as the white is not a pure #fff white
return rgb.red > 200 && rgb.green > 200 && rgb.blue > 200;
},
isTransparent = function (rgba) {
return rgba.opacity === 0
},
scanY = function (fromTop) {
var offset = fromTop ? 1 : -1;
// loop through each row
for (
var y = fromTop ? 0 : imgHeight - 1;
fromTop ? y < imgHeight : y > -1;
y += offset
) {
// loop through each column
for (var x = 0; x < imgWidth; x++) {
var rgb = getRBG(x, y);
if (!isWhite(rgb) && !isTransparent(rgb)) {
if (fromTop) {
return y;
} else {
return Math.min(y + 1, imgHeight - 1);
}
}
}
}
return null; // all image is white
},
scanX = function (fromLeft) {
var offset = fromLeft ? 1 : -1;
// loop through each column
for (
var x = fromLeft ? 0 : imgWidth - 1;
fromLeft ? x < imgWidth : x > -1;
x += offset
) {
// loop through each row
for (var y = 0; y < imgHeight; y++) {
var rgb = getRBG(x, y);
if (!isWhite(rgb) && !isTransparent(rgb)) {
if (fromLeft) {
return x;
} else {
return Math.min(x + 1, imgWidth - 1);
}
}
}
}
return null; // all image is white
};
var cropTop = scanY(true),
cropBottom = scanY(false),
cropLeft = scanX(true),
cropRight = scanX(false),
cropWidth = cropRight - cropLeft,
cropHeight = cropBottom - cropTop
post.top = cropTop
post.left = cropLeft
post.right = cropRight
post.bottom = cropBottom
post.width = cropWidth
post.height = cropHeight
console.log(
post.name,
"cropTop:",
cropTop,
'cropBottom:',
cropBottom,
"cropLeft:",
cropLeft,
'cropRight:',
cropRight,
'cropWidth:', cropWidth,
'cropHeight:', cropHeight
)
spriteJsonArray.push(post)
// 拷贝对象生成裁剪图片
image.clone().crop(post.left, post.top, post.width, post.height)
.write(`${post.outPutDir}/cut/${post.name}`)
resolve(post)
}).catch(function (err) {
// handle an exception
console.log('error:', err)
reject(err)
});
})
}
// 判断文件是否存在
function hasFile(path) {
return new Promise((resolve, reject) => {
fs.stat(path, function (err, stat) {
if (stat && stat.isFile()) {
console.log('文件存在')
resolve(true)
} else {
console.log('文件不存在或不是标准文件')
resolve(false)
}
})
})
}
//删除文件
function delFile(path) {
return new Promise((resolve, reject) => {
fs.unlink(path, function (err) {
if (err) {
reject()
}
console.log('文件删除成功')
resolve(true)
})
})
}
// 删除文件夹及内容
function deleteall(path) {
var files = [];
if (fs.existsSync(path)) {
files = fs.readdirSync(path);
files.forEach(function (file, index) {
var curPath = path + "/" + file;
if (fs.statSync(curPath).isDirectory()) { // recurse
deleteall(curPath);
} else { // delete file
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(path);
} else {
}
};
// 创建配置文件
function cearteMap() {
fs.writeFileSync(outputFilename, JSON.stringify(spriteJson, null, 4), 'utf8', function (err) {
if (err) {
console.log('writeFileSync:', err)
} else {
console.log("生成配置文件:" + outputFilename)
}
})
}
let toCutSprite = async function () {
let spriteInfoArray = fileList.slice()
let temp = null
console.log('/*****删除裁剪后的文件夹start*****/')
deleteall(`${dir}/cut`)
console.log('/*****删除裁剪后的文件夹end*****/')
//判断旧的文件夹是否有配置文件,有就删除
let has_map = await hasFile(outputFilename)
if (has_map) {
await delFile(outputFilename)
}
// for (let i = 0, length = spriteInfoArray.length; i < length; i++) {
// let data = await cutSprite(spriteInfoArray[i])
// }
console.log('/****开始裁剪图片*****/')
while (spriteInfoArray.length) {
temp = spriteInfoArray.shift()
let result = await cutSprite(temp)
}
console.log('/******图片处理完毕!*******/')
spriteJson.sprite = spriteJsonArray
// bug 生成配置文件,如果存在再次生成会报错
await cearteMap()
}
// 开始裁剪图片
toCutSprite()