Creating JPEG images with specified dimensions. How can you add W x H sizing to an image?

I have been searching for a Deno/TypeScript code snippet that can create basic images with dimensions embedded on them. I have provided an example of the code below, which generates images in JPEG format, base64, and dataURL.

The code works by adding RGB pixels one by one into a Number Array to build the image.

// Import jpeg encoder
import { encode as pixelsToBin } from "https://deno.land/x/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2d474d584e5d5a7948504f">[email protected]</a>/mod.ts";
// Import std base64 encoder
import { encode as binTob64 } from "https://deno.land/std/encoding/base64.ts";

// Create a jpeg Image with RED, GREEN, BLUE & ALPHA colors

/***
 * 
 * Material Design Colors | Scale 500
 * 
 * 19 colors
 * 
 * RED ---------> #f44336 -> rgba(244, 67, 54, 1)
 * PINK --------> #e91e63 -> rgba(233, 30, 99, 1)
 * PURPLE ------> #9c27b0 -> rgba(156, 39, 176, 1)
 * DEEP-PURPLE --> #673ab7 -> rgba(103, 58, 183, 1)
 * INDIGO ------> #3f51b5 -> rgba(63, 81, 181, 1)
 * BLUE --------> #2196f3 -> rgba(63, 81, 181, 1)
 * LIGHT-BLUE --> #03a9f4 -> rgba(3, 169, 244, 1)
 * CYAN --------> #00bcd4 -> rgba(0, 188, 212, 1)
 * TEAL --------> #009688 -> rgba(0, 150, 136, 1)
 * GREEN -------> #4caf50 -> rgba(76, 175, 80, 1)
 * LIGHT-GREEN -> #8bc34a -> rgba(139, 195, 74, 1)
 * LIME --------> #cddc39 -> rgba(205, 220, 57, 1)
 * YELLOW ------> #ffeb3b -> rgba(255, 235, 59, 1)
 * AMBER -------> #ffc107 -> rgba(255, 193, 7, 1)
 * ORANGE ------> #ff9800 -> rgba(255, 152, 0, 1)
 * DEEP-ORANGE -> #ff5722 -> rgba(255, 87, 34, 1)
 * BROWN -------> #795548 -> rgba(121, 85, 72, 1)
 * GREY --------> #9e9e9e -> rgba(158, 158, 158, 1)
 * BLUE-GREY ---> #607d8b -> rgba(96, 125, 139, 1)
 * 
 */

// Function to convert HEX color to RGB color
function hexToRgb(cHex): Array<number> {
  const r = parseInt(cHex.slice(1, 3), 16);
  const g = parseInt(cHex.slice(3, 5), 16);
  const b = parseInt(cHex.slice(5, 7), 16);
  // return {r, g, b} // return an object
  return [ r, g, b ];
}

async function saveJpeg(w: number, h: number, cHex: string, fileName: string) {

  // Dimensions of the generated jpeg image
  const jpegWidth:  number = w;
  const jpegHeight: number = h;
  const jpegArea:   number = (jpegWidth * jpegHeight);

  // Set RGB color based on input HEX color
  const jpegPixelColor: number[] = hexToRgb(cHex);

  // Initialize the array to store pixel values
  let jpegPixels: number[] = [];

  for(let i=0; i < jpegArea; i++) {
    jpegPixels.push(jpegPixelColor[0]);
    jpegPixels.push(jpegPixelColor[1]);
    jpegPixels.push(jpegPixelColor[2]);
    jpegPixels.push(1); // alpha channel value - ignored in JPEGs
  }

  // Define the structure of the image
  const jpegImage: Image = {
    width: jpegWidth,
    height: jpegHeight,
    data: new Uint8Array(jpegPixels)
  }

  // Encode image data to jpeg format
  const jpegRaw: Image = pixelsToBin(jpegImage, 100); //Quality 100 (default is 50)

  // Save the binary image to the file system
  await Deno.writeFile(`${fileName}.jpg`, jpegRaw.data);
}

// Save the jpeg image with specified dimensions, color, and name
await saveJpeg(640, 360, "#f44336", "red-500");
await saveJpeg(640, 360, "#4caf50", "green-500");
await saveJpeg(640, 360, "#2196f3", "blue-500");

Given the capabilities of this library, achieving embedding image dimensions onto the image itself would involve implementing additional logic within the code.

Answer №1

Great news! I conducted some thorough research and managed to utilize a different library to accomplish the task successfully.

Below are the outcomes:

// Utilizing Canvas API for Deno, which is adapted from canvaskit-wasm (Skia)
import { createCanvas } from "https://deno.land/x/canvas/mod.ts";
// Incorporating std base64 encoder
import { encode as binTob64 } from "https://deno.land/std/encoding/base64.ts";

// Generating a PNG Image in Deno using the Canvas API

/***
 * 
 * Material Design Colors
 * 
 * 19 background colors in the 500 range
 * 
 * RED ---------> #f44336 -> rgba(244,  67,  54, 1)
 * PINK --------> #e91e63 -> rgba(233,  30,  99, 1)
 * PURPLE ------> #9c27b0 -> rgba(156,  39, 176, 1)
 * DEEP-PURPLE -> #673ab7 -> rgba(103,  58, 183, 1)
 * INDIGO ------> #3f51b5 -> rgba( 63,  81, 181, 1)
 * BLUE --------> #2196f3 -> rgba( 63,  81, 181, 1)
 * LIGHT-BLUE --> #03a9f4 -> rgba(  3, 169, 244, 1)
 * CYAN --------> #00bcd4 -> rgba(  0, 188, 212, 1)
 * TEAL --------> #009688 -> rgba(  0, 150, 136, 1)
 * GREEN -------> #4caf50 -> rgba( 76, 175,  80, 1)
 * LIGHT-GREEN -> #8bc34a -> rgba(139, 195,  74, 1)
 * LIME --------> #cddc39 -> rgba(205, 220,  57, 1)
 * YELLOW ------> #ffeb3b -> rgba(255, 235,  59, 1)
 * AMBER -------> #ffc107 -> rgba(255, 193,   7, 1)
 * ORANGE ------> #ff9800 -> rgba(255, 152,   0, 1)
 * DEEP-ORANGE -> #ff5722 -> rgba(255,  87,  34, 1)
 * BROWN -------> #795548 -> rgba(121,  85,  72, 1)
 * GREY --------> #9e9e9e -> rgba(158, 158, 158, 1)
 * BLUE-GREY ---> #607d8b -> rgba( 96, 125, 139, 1)
 * 
 */

async function savePNG(w: number, h: number, bgHex: string, fgHex: string, fileName: string) {

  const pngWidth: number = w;
  const pngHeight: number = h;

  const canvas = createCanvas(pngWidth, pngHeight);

  const canvasCenter: any = {
    x: Math.floor(canvas.width / 2),
    y: Math.floor(canvas.height / 2),
  };

  const context2d = canvas.getContext("2d");

  context2d.fillStyle = bgHex;
  context2d.fillRect(0, 0, pngWidth, pngHeight); // X, Y, W, H

  // Setting font sizes: 12, 18, 24, 36, 48, 60, 72
  const fontSize: number = Math.floor(pngHeight * 0.125); // Defined as % of pngHeight

  context2d.fillStyle = fgHex;
  context2d.font = `${fontSize}px sans-serif`;

  // Text to be displayed
  const text: string = `${pngWidth}x${pngHeight}`;

  const charWidth: number = Math.floor(context2d.measureText("X").width);
  const textLength: number = text.length;
  const textWidth: number = charWidth * textLength;

  const textHeight: number = parseInt(context2d.font);

  context2d.fillText(text, Math.floor(canvasCenter.x - (textWidth / 2)), Math.floor(canvasCenter.y + (textHeight / 2))); // X, Y position

  await Deno.writeFile(`${fileName}.png`, canvas.toBuffer());

}

// Save the jpeg file with dimensions, colors & file name
await savePNG(1000, 1000, "#f44336", "#ffcdd2", "red-500");

// Save the jpeg file with dimensions, colors & file name
await savePNG(750, 750, "#4caf50", "#c8e6c9", "green-500");

// Save the jpeg file with dimensions, colors & file name
await savePNG(50, 50, "#2196f3", "#bbdefb", "blue-500");

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unlocking Column Data Tooltips in Angular Datatables: A Step-by-Step Guide

I have a single datatable and was wondering how to implement tooltips for when hovering over table cells. I tried the following code snippet, which successfully populated the tooltips. However, I am interested in achieving the same functionality using Angu ...

The significance of zone.js and rxjs within the context of Angular 2

As a newcomer to Angular2, I recently learned about zone.js and rxjs. I'm curious to know if they both serve the same purpose for handling asynchronous tasks, or if each has its own specific role. Can someone explain to me the exact reasons why zone.j ...

Typescript Routing Issue - This call does not match any overloads

Need assistance with redirecting to a sign-up page upon button click. Currently encountering a 'no overload matches this call' error in TypeScript. Have tried researching the issue online, but it's quite broad, and being new to Typescript ma ...

How to set up Angular 5 with Express

What is the best way to add Angular 5 to an existing Express project? Below are my files: https://i.stack.imgur.com/DPgMs.png Package.json: https://i.stack.imgur.com/iVVxA.png I am looking to integrate Angular 5 into this express project and develop t ...

Node.js is raising an error because it cannot locate the specified module, even though the path

Currently in the process of developing my own npm package, I decided to create a separate project for testing purposes. This package is being built in typescript and consists of a main file along with several additional module files. In the main file, I ha ...

A Step-by-Step Guide on Updating Your Angular 7 Project to Angular Version

I am facing a challenge with my Angular material project, which is currently outdated and needs to be updated to version 13. Running npm outdated revealed the following results: https://i.stack.imgur.com/ayjDu.png The Angular update guide suggests upgra ...

Using React to map and filter nested arrays while also removing duplicates

Hello, I recently started working with react and I've encountered a challenge while trying to map an array. const fullMen = LocationMenuStore.menuItems['menu']['headings'].map((headings: any) => { <Typography>{ ...

How to Retrieve an Array from a Promise Using Angular 4 and Typescript

I am encountering difficulties when trying to store data from a returned promise. To verify that the desired value has been returned, I log it in this manner: private fetchData() { this._movieFranchiseService.getHighestGrossingFilmFranchises() ...

Tips for preventing circular dependencies in JavaScript/TypeScript

How can one effectively avoid circular dependencies? This issue has been encountered in JavaScript, but it can also arise in other programming languages. For instance, there is a module called translationService.ts where upon changing the locale, settings ...

What leads to the inability to utilize environment variables in this TypeScript app built with Vue 3?

Currently, I am developing a single page application utilizing Vue 3 and TypeScript. The main purpose of this app is to interact with an API. All the necessary information including the API's URL and key are stored in the 'src\env.js' f ...

Creating an enum from an associative array for restructuring conditions

Hey everyone, I have a situation where my current condition is working fine, but now I need to convert it into an enum. Unfortunately, the enum doesn't seem to work with my existing condition as mentioned by the team lead. Currently, my condition loo ...

Encountering Duplicate Identifier Error while working on Angular 2 Typescript in Visual Studio Code

Currently attempting to configure a component in Angular 2 with Typescript using Visual Studio Code on Mac. Encounter the following errors when trying the code below: duplicate identifier 'Component'. and Duplicate identifier' DashboardCompo ...

Whenever I navigate to a new page in my NEXTJS project, it loads an excessive number of modules

I am currently working on a small Next.js project and facing an issue where the initial load time is excessively long. Whenever I click on a link to navigate to a page like home/product/[slug], it takes around 12 seconds to load due to compiling over 2000 ...

React: Function is missing a return type declaration. eslint plugin @typescript-eslint urges for explicit function return types

I'm just starting out with Typescript in React. I've created a simple functional component, but eslint is giving me an error saying that the return type for the functional component itself is missing. Can anyone help me figure out what I'm d ...

The issue with Angular's Mat Option selected values not functioning properly

We have a scenario where there are two form fields, and the second field needs to be disabled or enabled based on the selected value from the first field. The first field contains 5 values: 'a', 'b', 'c', 'd', ' ...

The object assigned in the Facebook login method cannot be utilized

I'm working on integrating Facebook login with Angular 2. Here's the button for logging in: <button ion-button (click)="fbLogin()"><ion-icon name="logo-facebook"></ion-icon>Login using Facebook</button> Below is the clic ...

Is it possible to generate a Date object from a predetermined string in typescript?

I have a string with values separated by commas, and I'm trying to create a Date object from it. It seems like this is not doable -- can someone verify this and provide a solution if possible? This code snippet doesn't work : let dateString=&a ...

MUI options - The specified type 'string' cannot be matched with type '"icon" | "iconOnly" | "text" | "outlined" | "contained" | undefined'

Is it possible to utilize custom variants in MUI v5? I am having trouble using a custom variant according to their documentation: https://mui.com/material-ui/customization/theme-components/#creating-new-component-variants declare module "@mui/material ...

Unable to reference the namespace 'ThemeDefinition' as a valid type within Vuetify

Looking to develop a unique theme for Vuetify v3.0.0-alpha.10 and I'm working with my vuetify.ts plugin file. import "@mdi/font/css/materialdesignicons.css"; import "vuetify/lib/styles/main.sass"; import { createVuetify, ThemeDefinition } from "v ...

Tips for validating duplicate entries in dynamically added form fields

I have a form called verification form and a form array named RepDetails with three fields. Initially, the form displays three fields, but users can add more details by clicking on "add more". I need assistance in ensuring that Mydetails[0].name is not ide ...