Load fonts directly from assets directory, fix image buffer issues

This commit is contained in:
Essem 2022-09-22 23:44:54 -05:00
parent 273e5b94d7
commit 4f66519aa7
No known key found for this signature in database
GPG key ID: 7D497397CC3A2A8C
22 changed files with 188 additions and 111 deletions

View file

@ -1,3 +1,4 @@
#include "common.h"
#include <napi.h>
#include <vips/vips8>
@ -15,6 +16,7 @@ Napi::Value Caption(const Napi::CallbackInfo &info) {
string caption = obj.Get("caption").As<Napi::String>().Utf8Value();
string font = obj.Get("font").As<Napi::String>().Utf8Value();
string type = obj.Get("type").As<Napi::String>().Utf8Value();
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
VOption *options = VImage::option()->set("access", "sequential");
@ -31,17 +33,27 @@ Napi::Value Caption(const Napi::CallbackInfo &info) {
int nPages = vips_image_get_n_pages(in.get_image());
int textWidth = width - ((width / 25) * 2);
string font_string = (font == "roboto" ? "Roboto Condensed" : font) + " " +
string font_string = "Twemoji Color Emoji, " +
(font == "roboto" ? "Roboto Condensed" : font) + " " +
(font != "impact" ? "bold" : "normal") + " " +
to_string(size);
string captionText = "<span background=\"white\">" + caption + "</span>";
VImage text =
VImage::text(captionText.c_str(), VImage::option()
VImage text;
auto findResult = fontPaths.find(font);
if (findResult != fontPaths.end()) {
text = VImage::text(
".", VImage::option()->set("fontfile",
(basePath + findResult->second).c_str()));
}
text = VImage::text(
captionText.c_str(),
VImage::option()
->set("rgba", true)
->set("align", VIPS_ALIGN_CENTRE)
->set("font", font_string.c_str())
->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str())
->set("width", textWidth));
VImage captionImage =
((text == (vector<double>){0, 0, 0, 0}).bandand())

View file

@ -1,3 +1,4 @@
#include "common.h"
#include <napi.h>
#include <vips/vips8>
@ -16,6 +17,7 @@ Napi::Value CaptionTwo(const Napi::CallbackInfo &info) {
bool top = obj.Get("top").As<Napi::Boolean>().Value();
string font = obj.Get("font").As<Napi::String>().Utf8Value();
string type = obj.Get("type").As<Napi::String>().Utf8Value();
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
VOption *options = VImage::option()->set("access", "sequential");
@ -32,17 +34,27 @@ Napi::Value CaptionTwo(const Napi::CallbackInfo &info) {
int nPages = vips_image_get_n_pages(in.get_image());
int textWidth = width - ((width / 25) * 2);
string font_string =
(font == "roboto" ? "Roboto Condensed" : font) + " " + to_string(size);
string font_string = "Twemoji Color Emoji, " +
(font == "roboto" ? "Roboto Condensed" : font) + " " +
to_string(size);
string captionText = "<span background=\"white\">" + caption + "</span>";
VImage text =
VImage::text(captionText.c_str(), VImage::option()
->set("rgba", true)
->set("font", font_string.c_str())
->set("align", VIPS_ALIGN_LOW)
->set("width", textWidth));
VImage text;
auto findResult = fontPaths.find(font);
if (findResult != fontPaths.end()) {
text = VImage::text(
".", VImage::option()->set("fontfile",
(basePath + findResult->second).c_str()));
}
text = VImage::text(
captionText.c_str(),
VImage::option()
->set("rgba", true)
->set("font", font_string.c_str())
->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str())
->set("align", VIPS_ALIGN_LOW)
->set("width", textWidth));
VImage captionImage =
((text == (vector<double>){0, 0, 0, 0}).bandand())
.ifthenelse(255, text)

10
natives/common.h Normal file
View file

@ -0,0 +1,10 @@
#pragma once
#include <string>
#include <unordered_map>
const std::unordered_map<std::string, std::string> fontPaths {
{"futura", "assets/fonts/caption.otf"},
{"helvetica", "assets/fonts/caption2.ttf"},
{"roboto", "assets/fonts/reddit.ttf"}
};

View file

@ -17,14 +17,18 @@ Napi::Value Homebrew(const Napi::CallbackInfo &info) {
string assetPath = basePath + "assets/images/hbc.png";
VImage bg = VImage::new_from_file(assetPath.c_str());
VImage text =
VImage::text(("<span letter_spacing=\"-5120\" color=\"white\">" +
caption + "</span>")
.c_str(),
VImage::option()
->set("rgba", true)
->set("align", VIPS_ALIGN_CENTRE)
->set("font", "PF Square Sans Pro 96"));
VImage text = VImage::text(
".", VImage::option()->set(
"fontfile", (basePath + "assets/fonts/hbc.ttf").c_str()));
text = VImage::text(
("<span letter_spacing=\"-5120\" color=\"white\">" + caption +
"</span>")
.c_str(),
VImage::option()
->set("rgba", true)
->set("align", VIPS_ALIGN_CENTRE)
->set("font", "Twemoji Color Font, PF Square Sans Pro 96")
->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str()));
VImage out = bg.composite2(text, VIPS_BLEND_MODE_OVER,
VImage::option()

View file

@ -1,3 +1,4 @@
#include "common.h"
#include <napi.h>
#include <vips/vips8>
@ -16,6 +17,7 @@ Napi::Value Meme(const Napi::CallbackInfo &info) {
string bottom = obj.Get("bottom").As<Napi::String>().Utf8Value();
string font = obj.Get("font").As<Napi::String>().Utf8Value();
string type = obj.Get("type").As<Napi::String>().Utf8Value();
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
VOption *options = VImage::option()->set("access", "sequential");
@ -23,7 +25,8 @@ Napi::Value Meme(const Napi::CallbackInfo &info) {
VImage::new_from_buffer(data.Data(), data.Length(), "",
type == "gif" ? options->set("n", -1) : options)
.colourspace(VIPS_INTERPRETATION_sRGB);
if (!in.has_alpha()) in = in.bandjoin(255);
if (!in.has_alpha())
in = in.bandjoin(255);
int width = in.width();
int pageHeight = vips_image_get_page_height(in.get_image());
@ -33,7 +36,8 @@ Napi::Value Meme(const Napi::CallbackInfo &info) {
int rad = 1;
vector<double> zeroVec = {0, 0, 0, 0};
string font_string = (font == "roboto" ? "Roboto Condensed" : font) + " " +
string font_string = "Twemoji Color Font, " +
(font == "roboto" ? "Roboto Condensed" : font) + " " +
(font != "impact" ? "bold" : "normal") + " " +
to_string(size);
@ -48,6 +52,13 @@ Napi::Value Meme(const Napi::CallbackInfo &info) {
VImage::option()->set("fill", true));
}
auto findResult = fontPaths.find(font);
if (findResult != fontPaths.end()) {
VImage::text(
".", VImage::option()->set("fontfile",
(basePath + findResult->second).c_str()));
}
VImage topText;
if (top != "") {
VImage topIn = VImage::text(
@ -56,6 +67,7 @@ Napi::Value Meme(const Napi::CallbackInfo &info) {
->set("rgba", true)
->set("align", VIPS_ALIGN_CENTRE)
->set("font", font_string.c_str())
->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str())
->set("width", width));
topIn = topIn.embed(rad + 10, rad + 10, (topIn.width() + 2 * rad) + 20,
@ -70,10 +82,11 @@ Napi::Value Meme(const Napi::CallbackInfo &info) {
}
topOutline = (topOutline == zeroVec);
VImage topInvert = topOutline.extract_band(3).invert();
topOutline = topOutline
.extract_band(0, VImage::option()->set(
"n", topOutline.bands() - 1))
.bandjoin(topInvert);
topOutline =
topOutline
.extract_band(0,
VImage::option()->set("n", topOutline.bands() - 1))
.bandjoin(topInvert);
topText = topOutline.composite2(topIn, VIPS_BLEND_MODE_OVER);
}
@ -85,6 +98,7 @@ Napi::Value Meme(const Napi::CallbackInfo &info) {
->set("rgba", true)
->set("align", VIPS_ALIGN_CENTRE)
->set("font", font_string.c_str())
->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str())
->set("width", width));
bottomIn =
bottomIn.embed(rad + 10, rad + 10, (bottomIn.width() + 2 * rad) + 20,
@ -130,7 +144,8 @@ Napi::Value Meme(const Napi::CallbackInfo &info) {
size_t length;
final.write_to_buffer(
("." + type).c_str(), &buf, &length,
type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) : 0);
type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
: 0);
result.Set("data", Napi::Buffer<char>::Copy(env, (char *)buf, length));
result.Set("type", type);

View file

@ -1,3 +1,4 @@
#include "common.h"
#include <napi.h>
#include <vips/vips8>
@ -16,6 +17,7 @@ Napi::Value Motivate(const Napi::CallbackInfo &info) {
string bottom_text = obj.Get("bottom").As<Napi::String>().Utf8Value();
string font = obj.Get("font").As<Napi::String>().Utf8Value();
string type = obj.Get("type").As<Napi::String>().Utf8Value();
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
VOption *options = VImage::option()->set("access", "sequential");
@ -32,7 +34,15 @@ Napi::Value Motivate(const Napi::CallbackInfo &info) {
int nPages = vips_image_get_n_pages(in.get_image());
int textWidth = width - ((width / 25) * 2);
string font_string = font == "roboto" ? "Roboto Condensed" : font;
string font_string =
"Twemoji Color Font, " + (font == "roboto" ? "Roboto Condensed" : font);
auto findResult = fontPaths.find(font);
if (findResult != fontPaths.end()) {
VImage::text(
".", VImage::option()->set("fontfile",
(basePath + findResult->second).c_str()));
}
VImage topImage;
if (top_text != "") {
@ -45,6 +55,7 @@ Napi::Value Motivate(const Napi::CallbackInfo &info) {
->set("rgba", true)
->set("align", VIPS_ALIGN_CENTRE)
->set("font", (font_string + " " + to_string(size)).c_str())
->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str())
->set("width", textWidth));
}
@ -59,6 +70,7 @@ Napi::Value Motivate(const Napi::CallbackInfo &info) {
->set("rgba", true)
->set("align", VIPS_ALIGN_CENTRE)
->set("font", (font_string + " " + to_string(size * 0.4)).c_str())
->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str())
->set("width", textWidth));
}
@ -96,7 +108,8 @@ Napi::Value Motivate(const Napi::CallbackInfo &info) {
VImage::option()->set("background", 0x000000)->set("expand", true));
}
if (bottom_text != "") {
if (top_text == "") frame = bordered3;
if (top_text == "")
frame = bordered3;
frame = frame.join(
bottomImage.gravity(VIPS_COMPASS_DIRECTION_NORTH, bordered3.width(),
bottomImage.height() + (size / 4),

View file

@ -8,7 +8,7 @@ using namespace vips;
Napi::Value Reddit(const Napi::CallbackInfo &info) {
Napi::Env env = info.Env();
Napi::Object result = Napi::Object::New(env);
try {
Napi::Object obj = info[0].As<Napi::Object>();
Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>();
@ -22,7 +22,8 @@ Napi::Value Reddit(const Napi::CallbackInfo &info) {
VImage::new_from_buffer(data.Data(), data.Length(), "",
type == "gif" ? options->set("n", -1) : options)
.colourspace(VIPS_INTERPRETATION_sRGB);
if (!in.has_alpha()) in = in.bandjoin(255);
if (!in.has_alpha())
in = in.bandjoin(255);
string assetPath = basePath + "assets/images/reddit.png";
VImage tmpl = VImage::new_from_file(assetPath.c_str());
@ -33,11 +34,16 @@ Napi::Value Reddit(const Napi::CallbackInfo &info) {
string captionText = "<span foreground=\"white\">" + text + "</span>";
VImage textImage =
VImage::text(captionText.c_str(), VImage::option()
->set("rgba", true)
->set("font", "Roboto 62")
->set("align", VIPS_ALIGN_LOW));
VImage textImage = VImage::text(
".", VImage::option()->set(
"fontfile", (basePath + "assets/fonts/reddit.ttf").c_str()));
textImage = VImage::text(
captionText.c_str(),
VImage::option()
->set("rgba", true)
->set("font", "Twemoji Color Font, Roboto 62")
->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str())
->set("align", VIPS_ALIGN_LOW));
VImage composited =
tmpl.composite2(textImage, VIPS_BLEND_MODE_OVER,
@ -61,7 +67,8 @@ Napi::Value Reddit(const Napi::CallbackInfo &info) {
size_t length;
final.write_to_buffer(
("." + type).c_str(), &buf, &length,
type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) : 0);
type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
: 0);
result.Set("data", Napi::Buffer<char>::Copy(env, (char *)buf, length));
result.Set("type", type);

View file

@ -16,6 +16,7 @@ Napi::Value Snapchat(const Napi::CallbackInfo &info) {
float pos =
obj.Has("pos") ? obj.Get("pos").As<Napi::Number>().FloatValue() : 0.5;
string type = obj.Get("type").As<Napi::String>().Utf8Value();
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
VOption *options = VImage::option()->set("access", "sequential");
@ -23,7 +24,8 @@ Napi::Value Snapchat(const Napi::CallbackInfo &info) {
VImage::new_from_buffer(data.Data(), data.Length(), "",
type == "gif" ? options->set("n", -1) : options)
.colourspace(VIPS_INTERPRETATION_sRGB);
if (!in.has_alpha()) in = in.bandjoin(255);
if (!in.has_alpha())
in = in.bandjoin(255);
int width = in.width();
int pageHeight = vips_image_get_page_height(in.get_image());
@ -31,17 +33,22 @@ Napi::Value Snapchat(const Napi::CallbackInfo &info) {
int size = width / 20;
int textWidth = width - ((width / 25) * 2);
string font_string = "Helvetica Neue " + to_string(size);
string font_string =
"Twemoji Color Font, Helvetica Neue " + to_string(size);
VImage textIn =
VImage::text(("<span foreground=\"white\" background=\"#000000B2\">" +
caption + "</span>")
.c_str(),
VImage::option()
->set("rgba", true)
->set("align", VIPS_ALIGN_CENTRE)
->set("font", font_string.c_str())
->set("width", textWidth));
VImage textIn = VImage::text(
".", VImage::option()->set(
"fontfile", (basePath + "assets/fonts/caption2.ttf").c_str()));
textIn = VImage::text(
("<span foreground=\"white\" background=\"#000000B2\">" + caption +
"</span>")
.c_str(),
VImage::option()
->set("rgba", true)
->set("align", VIPS_ALIGN_CENTRE)
->set("font", font_string.c_str())
->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str())
->set("width", textWidth));
int bgHeight = textIn.height() + (width / 25);
textIn =
((textIn == (vector<double>){0, 0, 0, 0}).bandand())
@ -68,7 +75,8 @@ Napi::Value Snapchat(const Napi::CallbackInfo &info) {
size_t length;
final.write_to_buffer(
("." + type).c_str(), &buf, &length,
type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) : 0);
type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
: 0);
result.Set("data", Napi::Buffer<char>::Copy(env, (char *)buf, length));
result.Set("type", type);

View file

@ -18,13 +18,16 @@ Napi::Value Sonic(const Napi::CallbackInfo &info) {
VImage bg = VImage::new_from_file(assetPath.c_str());
VImage textImage =
VImage::text(("<span foreground=\"white\">" + text + "</span>").c_str(),
VImage::option()
->set("rgba", true)
->set("align", VIPS_ALIGN_CENTRE)
->set("font", "Bitstream Vera Sans")
->set("width", 542)
->set("height", 390))
VImage::text(
("<span foreground=\"white\">" + text + "</span>").c_str(),
VImage::option()
->set("rgba", true)
->set("align", VIPS_ALIGN_CENTRE)
->set("font", "Twemoji Color Font, Bitstream Vera Sans")
->set("fontfile",
(basePath + "assets/fonts/twemoji.otf").c_str())
->set("width", 542)
->set("height", 390))
.gravity(VIPS_COMPASS_DIRECTION_CENTRE, 542, 390);
VImage out = bg.composite2(textImage, VIPS_BLEND_MODE_OVER,

View file

@ -1,3 +1,4 @@
#include "common.h"
#include <napi.h>
#include <vips/vips8>
@ -17,6 +18,7 @@ Napi::Value Uncanny(const Napi::CallbackInfo &info) {
string font = obj.Get("font").As<Napi::String>().Utf8Value();
string type = obj.Get("type").As<Napi::String>().Utf8Value();
string path = obj.Get("path").As<Napi::String>().Utf8Value();
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
VOption *options = VImage::option()->set("access", "sequential");
@ -28,7 +30,8 @@ Napi::Value Uncanny(const Napi::CallbackInfo &info) {
VImage base = VImage::black(1280, 720, VImage::option()->set("bands", 3));
string font_string = (font == "roboto" ? "Roboto Condensed" : font) + " " +
string font_string = "Twemoji Color Font, " +
(font == "roboto" ? "Roboto Condensed" : font) + " " +
(font != "impact" ? "bold" : "normal") + " 72";
string captionText = "<span background=\"black\" foreground=\"white\">" +
@ -36,25 +39,36 @@ Napi::Value Uncanny(const Napi::CallbackInfo &info) {
string caption2Text =
"<span background=\"black\" foreground=\"red\">" + caption2 + "</span>";
VImage text =
VImage::text(captionText.c_str(), VImage::option()
->set("rgba", true)
->set("align", VIPS_ALIGN_CENTRE)
->set("font", font_string.c_str())
->set("width", 588)
->set("height", 90));
auto findResult = fontPaths.find(font);
if (findResult != fontPaths.end()) {
VImage::text(
".", VImage::option()->set("fontfile",
(basePath + findResult->second).c_str()));
}
VImage text = VImage::text(
captionText.c_str(),
VImage::option()
->set("rgba", true)
->set("align", VIPS_ALIGN_CENTRE)
->set("font", font_string.c_str())
->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str())
->set("width", 588)
->set("height", 90));
VImage captionImage =
text.extract_band(0, VImage::option()->set("n", 3))
.gravity(VIPS_COMPASS_DIRECTION_CENTRE, 640, text.height() + 40,
VImage::option()->set("extend", "black"));
VImage text2 = VImage::text(caption2Text.c_str(),
VImage::option()
->set("rgba", true)
->set("align", VIPS_ALIGN_CENTRE)
->set("font", font_string.c_str())
->set("width", 588)
->set("height", 90));
VImage text2 = VImage::text(
caption2Text.c_str(),
VImage::option()
->set("rgba", true)
->set("align", VIPS_ALIGN_CENTRE)
->set("font", font_string.c_str())
->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str())
->set("width", 588)
->set("height", 90));
VImage caption2Image =
text2.extract_band(0, VImage::option()->set("n", 3))
.gravity(VIPS_COMPASS_DIRECTION_CENTRE, 640, text.height() + 40,
@ -66,7 +80,7 @@ Napi::Value Uncanny(const Napi::CallbackInfo &info) {
int pageHeight = vips_image_get_page_height(in.get_image());
int nPages = vips_image_get_n_pages(in.get_image());
VImage uncanny = VImage::new_from_file(path.c_str());
VImage uncanny = VImage::new_from_file((basePath + path).c_str());
base = base.insert(uncanny, 0, 130);

View file

@ -14,6 +14,7 @@ Napi::Value Whisper(const Napi::CallbackInfo &info) {
Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>();
string caption = obj.Get("caption").As<Napi::String>().Utf8Value();
string type = obj.Get("type").As<Napi::String>().Utf8Value();
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
VOption *options = VImage::option()->set("access", "sequential");
@ -21,7 +22,8 @@ Napi::Value Whisper(const Napi::CallbackInfo &info) {
VImage::new_from_buffer(data.Data(), data.Length(), "",
type == "gif" ? options->set("n", -1) : options)
.colourspace(VIPS_INTERPRETATION_sRGB);
if (!in.has_alpha()) in = in.bandjoin(255);
if (!in.has_alpha())
in = in.bandjoin(255);
int width = in.width();
int pageHeight = vips_image_get_page_height(in.get_image());
@ -30,7 +32,7 @@ Napi::Value Whisper(const Napi::CallbackInfo &info) {
int dividedWidth = width / 175;
int rad = 1;
string font_string = "Upright " + to_string(size);
string font_string = "Twemoji Color Font, Upright " + to_string(size);
VImage mask;
if (dividedWidth >= 1) {
@ -44,11 +46,15 @@ Napi::Value Whisper(const Napi::CallbackInfo &info) {
}
VImage textIn = VImage::text(
".", VImage::option()->set(
"fontfile", (basePath + "assets/fonts/whisper.otf").c_str()));
textIn = VImage::text(
("<span foreground=\"white\">" + caption + "</span>").c_str(),
VImage::option()
->set("rgba", true)
->set("align", VIPS_ALIGN_CENTRE)
->set("font", font_string.c_str())
->set("fontfile", (basePath + "assets/fonts/twemoji.otf").c_str())
->set("width", width));
textIn = textIn.embed(rad + 10, rad + 10, (textIn.width() + 2 * rad) + 20,
@ -82,7 +88,8 @@ Napi::Value Whisper(const Napi::CallbackInfo &info) {
size_t length;
final.write_to_buffer(
("." + type).c_str(), &buf, &length,
type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1) : 0);
type == "gif" ? VImage::option()->set("dither", 0)->set("reoptimise", 1)
: 0);
result.Set("data", Napi::Buffer<char>::Copy(env, (char *)buf, length));
result.Set("type", type);