Skip to content

[WIP] Easily generate images on-the-fly with node.js using wide range of templates

License

Notifications You must be signed in to change notification settings

juwennn/canvacord

 
 

Repository files navigation

SWUbanner

Canvacord

Easily generate images on-the-fly with node.js using wide range of templates.

Warning

You are looking at the next version of canvacord, which is under development. Go to the legacy branch to view legacy codebase.

Features

  • image generation (wip)
  • image manipulation (wip)
  • image templates (wip)
  • image filters (wip)
  • complex layouts (wip)
  • templates api (wip)
  • builder api (wip)

Example

Image Generation

Using built-in templates (New "Legacy api")

import { canvacord } from 'canvacord';
import fs from 'node:fs';

// triggered gif
const triggered = await canvacord.triggered(image);
triggered.pipe(fs.createWriteStream('triggered.gif'));

// image generation
const beautiful = await canvacord.beautiful(img);
const facepalm = await canvacord.facepalm(img);

// filters
const filtered = await canvacord
    .filters(512, 512)
    .drawImage(image)
    .hueRotate(90)
    .invert(2)
    .sepia(1)
    .opacity(0.5)
    .saturate(2)
    .encode();

// alternative syntax
const filtered = await canvacord(image, 512, 512)
    .hueRotate(90)
    .invert(2)
    .sepia(1)
    .opacity(0.5)
    .saturate(2)
    .encode();

fs.writeFileSync('filtered.png', filtered);

XP Card

import { Font, RankCardBuilder } from 'canvacord';
import { writeFile } from 'fs/promises';

// load default font
Font.loadDefault();

const card = new RankCardBuilder()
  .setUsername('Lost Ctrl')
  .setDisplayName('thearchaeopteryx')
  .setAvatar('...')
  .setCurrentXP(3800)
  .setRequiredXP(2500)
  .setLevel(54)
  .setRank(32)
  .setStatus('online');

const image = await card.build({
  format: 'png'
});

await writeFileSync('./card.png', data);

xp-card

Creating images using custom template

import { createTemplate, ImageFactory, TemplateImage, createImageGenerator } from 'canvacord';

const AffectedMeme = createTemplate((image: ImageSource) => {
  return {
    steps: [
      {
        image: [
          {
            source: new TemplateImage(ImageFactory.AFFECT),
            x: 0,
            y: 0
          }
        ]
      },
      {
        image: [
          {
            source: new TemplateImage(image),
            x: 180,
            y: 383,
            width: 200,
            height: 157
          }
        ]
      }
    ]
  };
});

// get target photo to use on "affected" meme image
const photo = await getPhotoForMemeSomehow();
const generator = createImageGenerator(AffectedMeme(photo));

// render out the image
await generator.render();

// get the resulting image in png format
const affectedMeme = await generator.encode('png');

Result

output

Creating images using custom builder

This is an advanced method of creating images. Canvacord builder api allows you to create your own image generator using JSX elements and a subset of tailwind class names. This is also possible without JSX, you can find an example here.

Note It does not support many css features such as grid layout. You can use flexbox instead.

If you want to use JSX with typescript, you need to add the following options to your tsconfig.json:

{
  "compilerOptions": {
    // other options
    "jsx": "react",
    "jsxFactory": "JSX.createElement",
    "jsxFragmentFactory": "JSX.Fragment"
  }
  // other options
}

You can also use pragma comments to define JSX factory and fragment factory:

/** @jsx JSX.createElement */
/** @jsxFrag JSX.Fragment */
// JSX import is required if you want to use JSX syntax
// Builder is a base class to create your own builders
// Font is a utility class to load fonts
import { JSX, Builder, Font } from 'canvacord';
import { writeFile } from 'fs/promises';

// declare props types
interface Props {
  text: string;
}

class Design extends Builder<Props> {
  constructor() {
    // set width and height
    super(500, 500);
    // initialize props
    this.bootstrap({ text: '' });
  }

  // define custom methods for your builder
  setText(text: string) {
    this.options.set('text', text);
    return this;
  }

  // this is where you have to define how the resulting image should look like
  async render() {
    return (
      <div className="flex items-center justify-center h-full w-full bg-teal-500">
        <h1 className="text-white font-bold text-7xl">{this.options.get('text')}</h1>
      </div>
    );
  }
}

// usage
// load font
Font.loadDefault();

// create design
const design = new Design().setText('Hello World');
const image = await design.build({ format: 'png' });

// do something with generated image
await writeFile('./test.png', image);

Result

output

About

[WIP] Easily generate images on-the-fly with node.js using wide range of templates

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 98.6%
  • JavaScript 1.4%