Skip to content

Commit a1c00c3

Browse files
committed
1.1.0 Migrate from Vite to CRA. Add JBX instead of local components. Add base64 output option
1 parent acb3430 commit a1c00c3

11 files changed

Lines changed: 15476 additions & 3919 deletions

File tree

.eslintrc.js

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,16 @@
11
module.exports = {
2-
"env": {
3-
"browser": true,
4-
"es2021": true
2+
env: {
3+
browser: true,
4+
es2021: true,
5+
},
6+
extends: ["eslint:recommended", "plugin:react/recommended"],
7+
parserOptions: {
8+
ecmaFeatures: {
9+
jsx: true,
510
},
6-
"extends": [
7-
"eslint:recommended",
8-
"plugin:react/recommended"
9-
],
10-
"parserOptions": {
11-
"ecmaFeatures": {
12-
"jsx": true
13-
},
14-
"ecmaVersion": 12,
15-
"sourceType": "module"
16-
},
17-
"plugins": [
18-
"react"
19-
],
20-
"rules": {
21-
}
11+
ecmaVersion: 12,
12+
sourceType: "module",
13+
},
14+
plugins: ["react"],
15+
rules: {},
2216
};

.gitignore

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,24 @@
1-
node_modules/
2-
dist
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# production
12+
/build
13+
/dist
14+
15+
# misc
16+
.DS_Store
17+
.env.local
18+
.env.development.local
19+
.env.test.local
20+
.env.production.local
21+
22+
npm-debug.log*
23+
yarn-debug.log*
24+
yarn-error.log*

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# 1.1.0
2+
- Add base64 output option
3+
- Replace internal components for JBX
4+
5+
# 1.0.0

package-lock.json

Lines changed: 15255 additions & 3526 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,55 @@
11
{
22
"name": "img2css",
3-
"version": "1.0.0",
3+
"version": "1.1.0",
44
"description": "Convert any image to pure css.",
55
"scripts": {
6-
"dev": "vite",
7-
"build": "vite build",
8-
"deploy": "rm -rf dist && npm run build && touch dist/.nojekyll && gh-pages -d dist --dotfiles"
6+
"dev": "react-scripts start",
7+
"build": "react-scripts build",
8+
"test": "react-scripts test",
9+
"eject": "react-scripts eject",
10+
"predeploy": "npm run build",
11+
"deploy": "gh-pages -d build"
912
},
13+
"homepage": "https://javier.xyz/img2css/",
1014
"repository": {
1115
"type": "git",
1216
"url": "https://github.com/javierbyte/img2css.git"
1317
},
14-
"keywords": [],
18+
"keywords": [
19+
"img2css",
20+
"images",
21+
"css",
22+
"experiments",
23+
"pixelart"
24+
],
1525
"author": "Javier Bórquez <hi@javier.xyz> (http://github.com/javierbyte)",
1626
"license": "CC0-1.0",
1727
"devDependencies": {
1828
"eslint": "^7.11.0",
1929
"eslint-plugin-react": "^7.21.4",
20-
"gh-pages": "^3.2.3",
21-
"vite": "^1.0.0-rc.1",
22-
"vite-plugin-react": "^3.0.0"
30+
"gh-pages": "^3.2.3"
2331
},
2432
"dependencies": {
25-
"@pika/react": "^16.13.1",
26-
"@pika/react-dom": "^16.13.1",
2733
"canvas-image-utils": "^2.0.2",
2834
"capsize": "^1.1.0",
35+
"jbx": "^1.0.0",
2936
"lodash": "^4.17.20",
37+
"react": "^17.0.2",
38+
"react-dom": "^17.0.2",
39+
"react-scripts": "^4.0.0",
3040
"styled-components": "^5.2.0",
3141
"tinycolor2": "^1.4.2"
42+
},
43+
"browserslist": {
44+
"production": [
45+
">0.2%",
46+
"not dead",
47+
"not op_mini all"
48+
],
49+
"development": [
50+
"last 1 chrome version",
51+
"last 1 firefox version",
52+
"last 1 safari version"
53+
]
3254
}
3355
}

index.html renamed to public/index.html

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,42 @@
88
<title>img2css | Convert any image to pure CSS</title>
99
<meta property="og:title" content="img2css" />
1010

11-
<meta name="description" content="This is a tool that can convert any image into a pure css image." />
12-
<meta property="og:description" content="This is a tool that can convert any image into a pure css image." />
11+
<meta
12+
name="description"
13+
content="This is a tool that can convert any image into a pure css image."
14+
/>
15+
<meta
16+
property="og:description"
17+
content="This is a tool that can convert any image into a pure css image."
18+
/>
1319

1420
<meta property="og:url" content="https://javier.xyz/img2css/" />
1521
<link rel="canonical" href="https://javier.xyz/img2css/" />
1622

17-
<meta property="og:image" content="https://javier.xyz/img2css/docs-assets/thumbnail.jpg" />
23+
<meta
24+
property="og:image"
25+
content="https://javier.xyz/img2css/docs-assets/thumbnail.jpg"
26+
/>
1827
</head>
1928
<body>
2029
<div id="root"></div>
2130

22-
<a href="https://github.com/javierbyte/img2css/" aria-label="github:@javierbyte" class="github-corner"
31+
<a
32+
href="https://github.com/javierbyte/img2css/"
33+
aria-label="github:@javierbyte"
34+
class="github-corner"
2335
><svg
2436
width="80"
2537
height="80"
2638
viewBox="0 0 250 250"
27-
style="fill: #fd6c6c; color: #fff; position: absolute; top: 0; border: 0; right: 0"
39+
style="
40+
fill: #fd6c6c;
41+
color: #fff;
42+
position: absolute;
43+
top: 0;
44+
border: 0;
45+
right: 0;
46+
"
2847
>
2948
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
3049
<path
@@ -72,8 +91,10 @@
7291
}
7392
</style>
7493

75-
<script type="module" src="./src/main.jsx"></script>
76-
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-44329676-12"></script>
94+
<script
95+
async
96+
src="https://www.googletagmanager.com/gtag/js?id=UA-44329676-12"
97+
></script>
7798
<script>
7899
window.dataLayer = window.dataLayer || [];
79100
function gtag() {

src/app.jsx

Lines changed: 113 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
import React, { useState } from "react";
1+
import React, { Fragment, useState } from "react";
22
import tinycolor from "tinycolor2";
33
import _ from "lodash";
44

55
import {
66
HeaderH1,
7-
HeaderH2,
87
Text,
98
Space,
109
Box,
@@ -13,11 +12,14 @@ import {
1312
Dropzone,
1413
Ul,
1514
Li,
16-
} from "./jbx.jsx";
15+
Tabs,
16+
Tab,
17+
Inline,
18+
} from "jbx";
1719

1820
import Styled from "styled-components";
1921

20-
import { imageToRGBMatrix } from "canvas-image-utils";
22+
import { imageToRGBMatrix, imageToRawData } from "canvas-image-utils";
2123

2224
const Textarea = Styled.textarea({
2325
fontFamily: "monaco, monospace",
@@ -65,6 +67,9 @@ function compressColor(rgb) {
6567
}
6668

6769
function App() {
70+
const [outputType, outputTypeSet] = useState("SHADOW");
71+
const [originalSize, originalSizeSet] = useState(0);
72+
const [base64Data, base64DataSet] = useState("");
6873
const [rgbMatrix, rgbMatrixSet] = useState(null);
6974
const [loadingImage, loadingImageSet] = useState(false);
7075

@@ -76,14 +81,21 @@ function App() {
7681
const files = dt ? dt.files : event.target.files;
7782
const file = files[0];
7883

84+
originalSizeSet(file.size);
85+
7986
const fr = new window.FileReader();
8087

8188
loadingImageSet(true);
8289

8390
fr.onload = async (data) => {
8491
const base64src = data.currentTarget.result;
85-
const dataMatrix = await imageToRGBMatrix(base64src, { size: 150 });
92+
const dataMatrix = await imageToRGBMatrix(base64src, { size: 200 });
93+
const canvasRawData = await imageToRawData(base64src, {
94+
size: 1080,
95+
crop: false,
96+
});
8697

98+
base64DataSet(canvasRawData.ctx.canvas.toDataURL("image/jpeg", 0.66));
8799
rgbMatrixSet(dataMatrix);
88100
loadingImageSet(false);
89101
};
@@ -168,35 +180,104 @@ function App() {
168180
</Text>
169181

170182
{rgbMatrix && (
171-
<div>
183+
<Fragment>
172184
<Space h={2} />
173-
<HeaderH2>The result</HeaderH2>
174-
<Space h={1} />
175-
<Text>This is your pure css (and single div) image! Enjoy!</Text>
176-
<Space h={1} />
177-
<div
178-
style={{
179-
height: 1,
180-
width: 1,
181-
boxShadow: masterShadow,
182-
marginBottom: rgbMatrix[0].length * scale,
183-
marginRight: rgbMatrix.length * scale,
184-
}}
185-
/>
185+
<Tabs>
186+
<Inline>
187+
<Tab
188+
active={outputType === "SHADOW"}
189+
key={"SHADOW"}
190+
onClick={() => {
191+
outputTypeSet("SHADOW");
192+
}}>
193+
<Text>{"Pure CSS"}</Text>
194+
</Tab>
195+
<Tab
196+
active={outputType === "BASE64"}
197+
key={"BASE64"}
198+
onClick={() => {
199+
outputTypeSet("BASE64");
200+
}}>
201+
<Text>{"Base64"}</Text>
202+
</Tab>
203+
</Inline>
204+
</Tabs>
186205
<Space h={1} />
187-
<Textarea
188-
onFocus={handleFocus}
189-
onChange={() => {}}
190-
className="code"
191-
value={`<div style="margin-right: ${
192-
rgbMatrix[0].length * scale
193-
}px; margin-bottom: ${
194-
rgbMatrix.length * scale
195-
}px; height: 1px; width: 1px; box-shadow: ${masterShadow}"></div>`}
196-
/>
197-
<Space h={1} />
198-
<Text>Size: {masterShadow.length.toLocaleString()}b</Text>
199-
</div>
206+
207+
{outputType === "BASE64" && (
208+
<Fragment>
209+
<Text>
210+
<strong>The result (base64).</strong>{" "}
211+
{
212+
"This is your image tag a base64 output. The entire image file is embedded inside the `<img>` tag using base64, so no need external hosting is needed."
213+
}
214+
</Text>
215+
<Space h={1} />
216+
217+
<img
218+
src={base64Data}
219+
style={{ maxWidth: "100%", height: "auto", display: "block" }}
220+
/>
221+
222+
<Space h={1} />
223+
224+
<Textarea
225+
onFocus={handleFocus}
226+
onChange={() => {}}
227+
className="code"
228+
value={`<img src="${base64Data}" />`}
229+
/>
230+
<Space h={1} />
231+
<Text>
232+
Output size (resized): {base64Data.length.toLocaleString()}b
233+
</Text>
234+
<Text>
235+
Original size: {Number(originalSize).toLocaleString()}b
236+
</Text>
237+
</Fragment>
238+
)}
239+
240+
{outputType === "SHADOW" && (
241+
<Fragment>
242+
<Text>
243+
<strong>The result (pure CSS).</strong> This is your pure CSS
244+
(and single div) image, enjoy! This output was created by
245+
resizing and setting each pixel as a box-shadow of a single pixel div, so
246+
no `img` tag or `background-image` is needed. This can result
247+
in huge outputs, and the use of this output is not recommended
248+
for production unless there is no other option.
249+
</Text>
250+
<Space h={1} />
251+
<div
252+
style={{
253+
height: 1,
254+
width: 1,
255+
boxShadow: masterShadow,
256+
marginBottom: rgbMatrix[0].length * scale,
257+
marginRight: rgbMatrix.length * scale,
258+
}}
259+
/>
260+
<Space h={1} />
261+
<Textarea
262+
onFocus={handleFocus}
263+
onChange={() => {}}
264+
className="code"
265+
value={`<div style="margin-right: ${
266+
rgbMatrix[0].length * scale
267+
}px; margin-bottom: ${
268+
rgbMatrix.length * scale
269+
}px; height: 1px; width: 1px; box-shadow: ${masterShadow}"></div>`}
270+
/>
271+
<Space h={1} />
272+
<Text>
273+
Output size (resized): {masterShadow.length.toLocaleString()}b
274+
</Text>
275+
<Text>
276+
Original size: {Number(originalSize).toLocaleString()}b
277+
</Text>
278+
</Fragment>
279+
)}
280+
</Fragment>
200281
)}
201282

202283
<Space h={2} />

0 commit comments

Comments
 (0)