给爱知乎添加Nodejs拼图模式(mosaic mode)
给爱知乎添加Nodejs拼图模式(mosaic mode)
博客: http://liteneo.com/2014/06/23/mosaic-mode/
之前 爱知乎 的 日历页面 采用的封面视图,每天的封面用的是当天内容的最后一张图片,今天突发奇想用当天所有的图片来拼成封面,于是现在变成了这样:
因为没有降低图片质量,所以现在加载日历页面的图片会比之前慢不少…… <!-- more --> 因为是托管在 JAE ,所以采用GraphicsMagick之类作为后端的module都被排除了,不然我会使用 gm ,于是我使用了国人开发的 images,使用起来非常简单,虽然还有些问题,不过能满足我的需求。
附上代码:
function mosaic(json) {
var size = Math.floor(Math.sqrt(json.news.length));
if (size > 6)size = 6;
var length = size * size;
var width = 600 / size;
var image = images(600, 600);
var idx = 0;
json.news.forEach(function (item, i) {
if (i >= length) return;
request.get(item.image, { encoding: null }, function (err, res, data) {
if (err || res.statusCode != 200 || data.length < 1000) return;
image.draw(images(data).size(width, width), i % size * width, Math.floor(i / size) * width);
if (++idx == length) {
fileUploader.uploadData(image.encode('jpg'), 'mosaic/' + json.date + '.jpg');
log("====== mosaic: " + json.date + " ======");
}
});
});
}
给爱知乎添加Nodejs拼图模式(Mosaic Mode)
博客:http://liteneo.com/2014/06/23/mosaic-mode/
之前爱知乎的日历页面采用的是封面视图,每天的封面用的是当天内容的最后一张图片。今天突发奇想,用当天所有的图片来拼成封面,于是现在变成了这样:
因为没有降低图片质量,所以现在加载日历页面的图片会比之前慢不少。
由于托管在JAE,所以采用GraphicsMagick之类的后端module都被排除了。不然我会使用aheckmann/gm,于是我使用了国人开发的node-images,使用起来非常简单,虽然还有些问题,但能满足我的需求。
附上代码:
const request = require('request');
const images = require('node-images');
const fs = require('fs');
// 拼图函数
function mosaic(json) {
// 计算拼图大小
var size = Math.floor(Math.sqrt(json.news.length));
if (size > 6) size = 6;
var length = size * size;
var width = 600 / size;
// 创建一个空白图像
var image = images(600, 600);
var idx = 0;
// 遍历每一张图片
json.news.forEach(function (item, i) {
if (i >= length) return;
// 下载图片
request.get(item.image, { encoding: null }, function (err, res, data) {
if (err || res.statusCode != 200 || data.length < 1000) return;
// 将下载的图片绘制到拼图中
image.draw(images(data).size(width, width), i % size * width, Math.floor(i / size) * width);
if (++idx == length) {
// 保存最终的拼图
image.save('mosaic-' + json.date + '.jpg', function(err) {
if (err) console.log(err);
else {
console.log("====== mosaic: " + json.date + " ======");
}
});
}
});
});
}
// 示例调用
var json = {
date: '2023-10-01',
news: [
{ image: 'http://example.com/image1.jpg' },
{ image: 'http://example.com/image2.jpg' },
{ image: 'http://example.com/image3.jpg' },
// ... 更多图片
]
};
mosaic(json);
解释
- 引入依赖:使用
request
库下载图片,node-images
处理图片。 - 计算拼图大小:根据新闻数量决定拼图的大小。
- 创建空白图像:使用
node-images
创建一个600x600像素的空白图像。 - 下载并绘制图片:遍历每一张图片,下载并绘制到拼图中。
- 保存拼图:当所有图片都绘制完成后,将拼图保存为文件。
通过这种方式,我们可以将当天的所有图片拼接成一张大图,作为日历页面的封面。
学习一下
看上去不错。Mark,回头来看。
昨晚回去看了。楼主写的不错,学习了。
要给爱知乎添加Node.js拼图模式(Mosaic Mode),可以参考以下步骤和代码实现。这里我们使用request
库来下载图片,使用node-images
库来处理图像拼接。
首先安装所需的库:
npm install request node-images
接下来是具体的代码实现:
const request = require('request');
const images = require('images');
function mosaic(json) {
// 计算拼图大小
let size = Math.floor(Math.sqrt(json.news.length));
if (size > 6) size = 6;
const length = size * size;
const width = 600 / size;
const height = 600 / size;
// 创建一个空画布
let canvas = images(600, 600);
let idx = 0;
json.news.forEach((item, i) => {
if (i >= length) return;
request.get({ url: item.image, encoding: null }, (err, res, data) => {
if (err || res.statusCode !== 200 || data.length < 1000) return;
// 将每张小图绘制到画布上
canvas.draw(images(data).size(width, height), (i % size) * width, Math.floor(i / size) * height);
if (++idx === length) {
// 保存最终的拼图
canvas.save('output.jpg', { quality: 90 });
console.log("====== mosaic: " + json.date + " ======");
}
});
});
}
// 示例输入数据
const json = {
news: [
{ image: 'http://example.com/image1.jpg' },
{ image: 'http://example.com/image2.jpg' },
// 更多图片...
],
date: '2023-10-10'
};
mosaic(json);
这段代码中,我们首先计算出拼图的大小,并创建一个画布。然后遍历输入的图片列表,将每张图片缩放到指定大小并绘制到画布上。最后,当所有图片都绘制完毕后,保存生成的拼图。
请注意,这里假设json.news
包含一系列图片URL。你需要根据实际情况调整输入数据格式。此外,保存图像的部分使用了canvas.save
方法,如果你需要上传到服务器或其他地方,可以替换为相应的文件上传逻辑。