how would I go about creating a pixel image from scratch? I am using web technologies (html/css/javascript/react) how would I take some information (such as pixel 1 is #ff5733 color, pixel 2 is #ff3829 color) and generate the corresponding pixel image for that? If anyone could point me in the right direction in generating images at least, that would be awesome.
I can only find information on how to pixelate existing images online. Any help is greatly appreciated. Thank you.
Edit: The two answers below are really good! Thank you all for your fantastic help!
how would I go about creating a pixel image from scratch? I am using web technologies (html/css/javascript/react) how would I take some information (such as pixel 1 is #ff5733 color, pixel 2 is #ff3829 color) and generate the corresponding pixel image for that? If anyone could point me in the right direction in generating images at least, that would be awesome.
I can only find information on how to pixelate existing images online. Any help is greatly appreciated. Thank you.
Edit: The two answers below are really good! Thank you all for your fantastic help!
Share Improve this question edited Jun 28, 2022 at 22:41 Rachel Kim asked Jun 28, 2022 at 7:35 Rachel KimRachel Kim 956 bronze badges 1- 1 There are a vast amount of image processing and creation tools available. Are you asking to create bitmap images on the fly using html/css/js ? Why would you want to do that? – collapsar Commented Jun 28, 2022 at 7:38
2 Answers
Reset to default 6Assuming that you have a two-dimensional array of color values, -- represented below by the variable: mypixels, -- you could use a set of for loops to draw each pixel on a canvas, then convert it to an image:
document.addEventListener('DOMContentLoaded', () => {
var mypixels = [
['#FFF', '#FFF', '#FFF', '#FFF', '#FFF', '#FFF', '#FFF'],
['#FFF', '#FFF', '#F00', '#FFF', '#F70', '#FFF', '#FFF'],
['#FFF', '#FFF', '#F70', '#FFF', '#FF0', '#FFF', '#FFF'],
['#FFF', '#FFF', '#FF0', '#FFF', '#0F0', '#FFF', '#FFF'],
['#FFF', '#FFF', '#FFF', '#FFF', '#FFF', '#FFF', '#FFF'],
['#FFF', '#FF0', '#FFF', '#FFF', '#FFF', '#F0F', '#FFF'],
['#FFF', '#FFF', '#0F0', '#0FF', '#00F', '#FFF', '#FFF'],
['#FFF', '#FFF', '#FFF', '#FFF', '#FFF', '#FFF', '#FFF']
];
function createImage(pixels) {
var canvas = document.createElement('canvas');
canvas.width = pixels[0].length;
canvas.height = pixels.length;
var context = canvas.getContext('2d');
for(var r = 0; r < canvas.height; r++) {
for(var c = 0; c < canvas.width; c++) {
context.fillStyle = pixels[r][c];
context.fillRect(c, r, 1, 1);
}
}
return canvas.toDataURL('image/png');
}
document.querySelector('img').src = createImage(mypixels);
});
img {
width: 200px;
height: 100px;
border: 1px dashed black;
background-color: lightgray;
image-rendering: pixelated;
object-fit: contain;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<img/>
</body>
</html>
For more information on the Javascript Canvas API, MDN Web Docs has a nice reference, and W3Schools has a nice beginner friendly walkthrough. Hopefully this is useful to you!
UPDATE
SVG solution with downloadable image.
Overview
There are various ways to dynamically create a simulation of a bitmap image in the context of html/css/js. None of them is efficient nor do they seem to be particularly useful - - though there is a precedent of a website selling individual pixels for charity purposes ...
The following alternatives are demonstrated:
- A grid of divs representing pixels
- A linear gradient representing a row of pixels
- An embedded svg with rect elements representing pixels (UPDATE: with download link)
1. A grid of divs representing pixels
Idea
Dynamically create 1x1 divs organized in a tabular grid to represent the pixels of the image and set their background color according to the value for the respective pixel.
Code
The image data are the html color codes for the pixels organized as an array of arrays in row-major fashion. For demo purposes the rendered 'pixels' are set to the size of 16x16.
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<meta http-equiv="expires" content="0">
<meta http-equiv="cache-control" content="private">
<meta http-equiv="pragma" content="no-cache">
<title>SO - Bitmap divs</title>
<!--
-->
<style type="text/css">
body {
background-color: #eee;
}
.bitmap {
display: table;
}
.bitmap > div {
display: table-row;
}
.pixel {
width: 16px;
height: 16px;
display: table-cell;
}
</style>
<script type=text/javascript>
document.addEventListener ( 'DOMContentLoaded', () => {
// Image definition as pixel bitmap
let aas_smiley = [
[ ['#aaaaaa'], ['#aaaaaa'], ['#000000'], ['#000000'], ['#000000'], ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'] ]
, [ ['#aaaaaa'], ['#000000'], ['#cccc00'], ['#cccc00'], ['#cccc00'], ['#000000'], ['#aaaaaa'], ['#aaaaaa'] ]
, [ ['#000000'], ['#cccc00'], ['#000000'], ['#cccc00'], ['#000000'], ['#cccc00'], ['#000000'], ['#aaaaaa'] ]
, [ ['#000000'], ['#cccc00'], ['#cccc00'], ['#cccc00'], ['#cccc00'], ['#cccc00'], ['#000000'], ['#aaaaaa'] ]
, [ ['#000000'], ['#cccc00'], ['#cccc00'], ['#000000'], ['#cccc00'], ['#cccc00'], ['#000000'], ['#aaaaaa'] ]
, [ ['#aaaaaa'], ['#000000'], ['#cccc00'], ['#cccc00'], ['#cccc00'], ['#000000'], ['#aaaaaa'], ['#aaaaaa'] ]
, [ ['#aaaaaa'], ['#aaaaaa'], ['#000000'], ['#000000'], ['#000000'], ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'] ]
, [ ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'] ]
];
let e_table = document.querySelector('.bitmap')
;
aas_smiley.forEach ( pa_line => {
let e_row = document.createElement('div')
;
pa_line.forEach ( (pa_pixel, pn_idx) => {
let e_d = document.createElement('div')
;
e_d.classList.add('pixel');
e_d.setAttribute('style', `background-color: ${pa_pixel[0]};`);
e_row.append(e_d);
});
e_table.append(e_row);
});
});
</script>
</head>
<body>
<div class="bitmap"></div>
</body>
</html>
2. A linear gradient representing a row of pixels
Idea
A similar effect can be achieved by creating a somewhat degenerate linear gradient of pixel-wide sub-gradients that interpolate between identical color-value.
A minor technical difference here is that the divs carrying the gradient data cover a whole table row, thus the table layout is nx1.
Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<meta http-equiv="expires" content="0">
<meta http-equiv="cache-control" content="private">
<meta http-equiv="pragma" content="no-cache">
<title>SO - Bitmap divs</title>
<!--
-->
<style type="text/css">
body {
background-color: #eee;
}
.bitmap {
display: table;
}
.bitmap > div {
display: table-row;
width: 128px;
height: 16px;
}
.bitmap > div > div {
width: 128px;
height: 16px;
display: table-cell;
}
</style>
<script type=text/javascript>
document.addEventListener ( 'DOMContentLoaded', () => {
// Image definition as pixel bitmap
let aas_smiley = [
[ ['#aaaaaa'], ['#aaaaaa'], ['#000000'], ['#000000'], ['#000000'], ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'] ]
, [ ['#aaaaaa'], ['#000000'], ['#cccc00'], ['#cccc00'], ['#cccc00'], ['#000000'], ['#aaaaaa'], ['#aaaaaa'] ]
, [ ['#000000'], ['#cccc00'], ['#000000'], ['#cccc00'], ['#000000'], ['#cccc00'], ['#000000'], ['#aaaaaa'] ]
, [ ['#000000'], ['#cccc00'], ['#cccc00'], ['#cccc00'], ['#cccc00'], ['#cccc00'], ['#000000'], ['#aaaaaa'] ]
, [ ['#000000'], ['#cccc00'], ['#cccc00'], ['#000000'], ['#cccc00'], ['#cccc00'], ['#000000'], ['#aaaaaa'] ]
, [ ['#aaaaaa'], ['#000000'], ['#cccc00'], ['#cccc00'], ['#cccc00'], ['#000000'], ['#aaaaaa'], ['#aaaaaa'] ]
, [ ['#aaaaaa'], ['#aaaaaa'], ['#000000'], ['#000000'], ['#000000'], ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'] ]
, [ ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'] ]
];
const n_factor = 16;
let e_table = document.querySelector('.bitmap')
;
aas_smiley.forEach ( pa_line => {
let e_row = document.createElement('div')
, e_cell = document.createElement('div')
, as_gradient = []
, s_gradientStyle
, s_lastPixel
;
pa_line.forEach ( (pa_pixel, pn_idx) => {
if (pn_idx === 0) {
as_gradient.push ( `to right` );
} else {
as_gradient.push ( `${s_lastPixel} ${pn_idx * n_factor}px, ${pa_pixel[0]} ${pn_idx * n_factor}px` );
}
s_lastPixel = pa_pixel[0];
});
s_gradientStyle = `background: linear-gradient(${as_gradient.join(', ')});`;
e_cell.setAttribute('style', s_gradientStyle);
e_row.append(e_cell);
e_table.append(e_row);
});
});
</script>
</head>
<body>
<div class="bitmap"></div>
</body>
</html>
3. An embedded svg with rect elements representing pixels
Idea
Create rect
elements representing pixels.
Note that elements need to be created in the svg namespace.
UPDATE The code below es with the generation of an extra download link by means of a data url. In principle this technique can be applied to generate downloadable data in every format that has a MIME type assigned, in particular traditional image formats like gif, jpeg, png, tiff. Of course, you have to obtain the syntactically well-formed octet sequence first ...
Data urls can also be shown inline. To this behest, create an img
element and set its src
attribute to the data url string. (see the code section mented out).
Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<meta http-equiv="expires" content="0">
<meta http-equiv="cache-control" content="private">
<meta http-equiv="pragma" content="no-cache">
<title>SO - Bitmap (svg)</title>
<!--
-->
<style type="text/css">
body {
background-color: #eee;
}
</style>
<script type=text/javascript>
document.addEventListener ( 'DOMContentLoaded', () => {
// Image definition as pixel bitmap
let aas_smiley = [
[ ['#aaaaaa'], ['#aaaaaa'], ['#000000'], ['#000000'], ['#000000'], ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'] ]
, [ ['#aaaaaa'], ['#000000'], ['#cccc00'], ['#cccc00'], ['#cccc00'], ['#000000'], ['#aaaaaa'], ['#aaaaaa'] ]
, [ ['#000000'], ['#cccc00'], ['#000000'], ['#cccc00'], ['#000000'], ['#cccc00'], ['#000000'], ['#aaaaaa'] ]
, [ ['#000000'], ['#cccc00'], ['#cccc00'], ['#cccc00'], ['#cccc00'], ['#cccc00'], ['#000000'], ['#aaaaaa'] ]
, [ ['#000000'], ['#cccc00'], ['#cccc00'], ['#000000'], ['#cccc00'], ['#cccc00'], ['#000000'], ['#aaaaaa'] ]
, [ ['#aaaaaa'], ['#000000'], ['#cccc00'], ['#cccc00'], ['#cccc00'], ['#000000'], ['#aaaaaa'], ['#aaaaaa'] ]
, [ ['#aaaaaa'], ['#aaaaaa'], ['#000000'], ['#000000'], ['#000000'], ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'] ]
, [ ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'], ['#aaaaaa'] ]
];
const n_factor = 16;
let e_svg = document.querySelector('svg')
;
aas_smiley.forEach ( (pa_line, pn_row) => {
pa_line.forEach ( (pa_pixel, pn_col) => {
let e_rect = document.createElementNS("http://www.w3/2000/svg", 'rect')
;
e_rect.setAttribute('x', `${pn_col}`);
e_rect.setAttribute('y', `${pn_row}`);
e_rect.setAttribute('width' , '1');
e_rect.setAttribute('height', '1');
e_rect.setAttribute('fill' , pa_pixel[0]);
e_svg.append(e_rect);
});
});
// Goodie: Downloadable Image
let s_svg = e_svg.outerHTML
, s_datauri = `data:image/svg+xml;utf8;base64,${btoa(s_svg)}`
, e_a = document.createElement('a')
, e_body = document.querySelector('body')
;
e_a.setAttribute('href' , s_datauri);
e_a.setAttribute('download' , 'smiley.svg');
e_a.innerText = 'Download as "smiley.svg"';
e_body.append(e_a);
// Optional: Render as inline image with data url
// let e_img = document.createElement('img')
// ;
// e_img.setAttribute('src' , s_datauri);
// e_body.append(e_img);
});
</script>
</head>
<body>
<svg
width="128"
height="128"
viewBox="0 0 16 16"
xmlns="http://www.w3/2000/svg"
>
</svg>
</body>
</html>