给爱知乎添加Nodejs拼图模式(mosaic mode)

给爱知乎添加Nodejs拼图模式(mosaic mode)

博客: http://liteneo.com/2014/06/23/mosaic-mode/

之前 爱知乎日历页面 采用的封面视图,每天的封面用的是当天内容的最后一张图片,今天突发奇想用当天所有的图片来拼成封面,于是现在变成了这样:

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 + " ======");
      }
    });
  });
}

5 回复

给爱知乎添加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);

解释

  1. 引入依赖:使用request库下载图片,node-images处理图片。
  2. 计算拼图大小:根据新闻数量决定拼图的大小。
  3. 创建空白图像:使用node-images创建一个600x600像素的空白图像。
  4. 下载并绘制图片:遍历每一张图片,下载并绘制到拼图中。
  5. 保存拼图:当所有图片都绘制完成后,将拼图保存为文件。

通过这种方式,我们可以将当天的所有图片拼接成一张大图,作为日历页面的封面。


学习一下

看上去不错。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方法,如果你需要上传到服务器或其他地方,可以替换为相应的文件上传逻辑。

回到顶部