Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
alselawi committed Jun 7, 2019
0 parents commit df15c30
Show file tree
Hide file tree
Showing 21 changed files with 1,333 additions and 0 deletions.
14 changes: 14 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# OS generated files #
######################
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.dbma

# Node.js Files #
######################
/node_modules/*
*.log
3 changes: 3 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/*
/*/
!/dist/
29 changes: 29 additions & 0 deletions build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const fs = require("fs");

const libheif = fs.readFileSync("./src/libheif.js", { encoding: "utf8" });
let src = fs.readFileSync("./dist/index.js", { encoding: "utf8" });
const umdString = `
(function (global, factory) {
if(typeof exports === 'object' && typeof module !== 'undefined') {
module.exports = factory();
module.exports.default = factory();
}
else if(typeof define === 'function' && define.amd) {
define(factory);
}
else {
(global = global || self, global.heic2any = factory())
}
}(this, function () { 'use strict';
`;
const returnString = `
return heic2any;
}));
`;

src = src.replace(`import "./libheif";`, "");
src = src.replace(`export default heic2any;`, "");

const result = libheif + umdString + src + returnString;
fs.writeFileSync("./dist/index.js", result);
console.log("# Build finished successfully");
Binary file added demo/1.heic
Binary file not shown.
Binary file added demo/2.heic
Binary file not shown.
Binary file added demo/3.heic
Binary file not shown.
Binary file added demo/4.heic
Binary file not shown.
Binary file added demo/5.heic
Binary file not shown.
Binary file added demo/6.heic
Binary file not shown.
Binary file added demo/7.heic
Binary file not shown.
7 changes: 7 additions & 0 deletions dist/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import "./libheif";
declare function heic2any({ blob, toType, quality }: {
blob: Blob;
toType?: string;
quality?: number;
}): Promise<Blob>;
export default heic2any;
497 changes: 497 additions & 0 deletions dist/index.js

Large diffs are not rendered by default.

128 changes: 128 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<html>
<head>
<title>HEIC2ANY | convert HEIC/HEIF images to PNG/JPG/PNG</title>
<style>
html {
background: #fff;
}
body {
background: #000;
color: #fff;
font-family: sans-serif;
max-width: 600px;
margin: 15px auto;
padding: 25px;
border-radius: 0 180px 0 0;
border-top: 20px solid #8bc34a;
border-left: 20px solid #8bc34a;
}
a {
color: #8bc34a;
}
h1 {
text-align: center;
}
p {
font-family: sans-serif;
font-size: 14px;
padding: 15px;
}
#images img {
height: 100px;
width: 100px;
}
li {
background: #c5e1a5;
color: #000;
padding: 5px;
}
pre {
background: #fff;
padding: 20px;
color: #000;
border: 3px solid #8bc34a;
}
</style>
</head>
<body>
<div id="readme"></div>
<hr />
<h3 id="try">Try it on your own files:</h3>
<input type="file" id="user-file" accept="image/heic" />
<img src="" id="user-img" />
<hr />
<h3>Sample HEIC files:</h3>
<div id="loading">Loading...</div>
<div id="images"></div>
<p>Alex Corvi / MIT License</p>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script src="dist/index.js"></script>
<script>
function saveFile(blob, filename) {
if (window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, filename);
} else {
const a = document.createElement("a");
document.body.appendChild(a);
const url = window.URL.createObjectURL(blob);
a.href = url;
a.download = filename;
a.click();
setTimeout(() => {
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
}, 0);
}
}

document
.getElementById("user-file")
.addEventListener("change", ev => {
const blob = ev.target.files[0];
console.log(blob);
heic2any({
blob
}).then(resultBlob => {
console.log(resultBlob);
saveFile(resultBlob, blob.name + ".png");
});
});

fetch("./readme.md")
.then(x => x.text())
.then(x => {
document.getElementById("readme").innerHTML = marked(x);
});

function loadHEIC(url) {
return fetch(url)
.then(x => x.blob())
.then(x => heic2any({ blob: x }))
.then(x => {
const url = URL.createObjectURL(x);
document.getElementById("images").innerHTML =
document.getElementById("images").innerHTML +
`<img src="${url}"/>`;
});
}

loadHEIC("./demo/1.heic")
.then(() => loadHEIC("./demo/2.heic"))
.then(() => loadHEIC("./demo/3.heic"))
.then(() => loadHEIC("./demo/4.heic"))
.then(() => loadHEIC("./demo/5.heic"))
.then(() => loadHEIC("./demo/6.heic"))
.then(() => loadHEIC("./demo/7.heic"))
.then(
() =>
(document.getElementById("loading").innerHTML =
"Finished")
)
.catch(
() =>
(document.getElementById("loading").innerHTML =
"Error occurred")
);
</script>
</body>
</html>
35 changes: 35 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "heic2any",
"version": "0.0.1",
"description": "Converting HEIC/HEIF to PNG/JPEG/GIF in the browser",
"main": "dist/index.js",
"module": "dist/index.es.js",
"files": [
"dist"
],
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc --p tsconfig.json && node ./build.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/alexcorvi/heic2any.git"
},
"keywords": [
"HEIC",
"HEIF",
"PNG",
"image",
"conversion"
],
"author": "Alex Corvi",
"license": "MIT",
"bugs": {
"url": "https://github.com/alexcorvi/heic2any/issues"
},
"homepage": "https://github.com/alexcorvi/heic2any#readme",
"dependencies": {},
"devDependencies": {
"typescript": "^3.5.1"
}
}
53 changes: 53 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# HEIC2ANY

converting [HEIC/HEIF](http://www.hackerfactor.com/blog/index.php?/archives/833-HEIC-Yeah.html) image files to JPEG/PNG/GIF in the browser. This tool is specifically for the browser environment, it _WILL NOT_ work in node environment.

[Click here for demo]()

---

- Installation: yarn

```bash
yarn add heic2any
```

- Installation: npm

```bash
npm install heic2any
```

- Installation: no module bundler

```html
<!-- just include the file in a script tag -->
<script src="./dist/index.js">
```
- Usage: Typescript & Javascript
```typescript
import heic2any from "heic2any";
// or
const heic2any = require("heic2any");
// skip the lines above if you're not using a module bundler
// and would prefer to include a <script> tag in your HTML file
// this is our heif image file
const HEICBlobFile = new Blob();
heic2any({
// required: the HEIF blob file
blob: HEICBlobFile,
// (optional) MIME type of the target file
// it can be "image/jpeg", "image/png" or "image/gif"
// defaults to "image/png"
toType: "image/jpeg",
// conversion quality
// a number ranging from 0 to 1
quality: 0.8
});
```
> This project is heavily based on the excellent [libheif](https://github.com/strukturag/libheif/) by [struktur](https://www.struktur.de/).
25 changes: 25 additions & 0 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import typescript from "rollup-plugin-typescript2";
import pkg from "./package.json";
import { readFileSync } from "fs";
export default {
input: "src/index.ts",
output: {
file: pkg.main,
format: "iife",
name: "heic2any",
banner: () =>
readFileSync("./src/libheif.js", { encoding: "utf8" }) + "\n\n",
globals: {
"./libheif": "libheif"
}
},
external: [
...Object.keys(pkg.dependencies || {}),
...Object.keys(pkg.peerDependencies || {})
],
plugins: [
typescript({
typescript: require("typescript")
})
]
};
75 changes: 75 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import "./libheif";

const supportedMIMETypes = ["image/png", "image/jpeg", "image/gif"];

function heic2any({
blob,
toType,
quality
}: {
blob: Blob;
toType?: string;
quality?: number;
}): Promise<Blob> {
// normalize quality
if (quality !== undefined) {
if (quality > 1 || quality < 0) {
quality = undefined;
}
}

// normalize MIME type
if (toType !== undefined) {
if (supportedMIMETypes.indexOf(toType) === -1) {
toType = undefined;
}
}

return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = e => {
const buffer = (e.target as any).result;
const decoder = new libheif.HeifDecoder();
const imagesArr = decoder.decode(buffer);
if (!imagesArr || !imagesArr.length) {
return reject("format not supported");
}

const primaryImage =
imagesArr.find(x => x.is_primary()) || imagesArr[0];

const w = primaryImage.get_width();
const h = primaryImage.get_height();

const canvas = document.createElement("canvas");
canvas.width = w;
canvas.height = h;
const ctx = canvas.getContext("2d");

if (!ctx) {
return reject("Error in canvas context");
}

const whiteImage = ctx.createImageData(w, h);
for (let i = 0; i < w * h; i++) {
whiteImage.data[i * 4 + 3] = 255;
}

primaryImage.display(whiteImage, display_image_data => {
ctx.putImageData(display_image_data, 0, 0);
canvas.toBlob(
resultingBlob => {
if (resultingBlob) {
resolve(resultingBlob);
}
},
toType,
quality
);
});
};
reader.readAsArrayBuffer(blob);
});
}

export default heic2any;
15 changes: 15 additions & 0 deletions src/libheif.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
declare namespace libheif {
class HeifDecoder {
decode(
buffer: ArrayBuffer
): {
get_width: () => number;
get_height: () => number;
is_primary: () => boolean;
display: (
base: ImageData,
callback: (result: ImageData) => void
) => void;
}[];
}
}
431 changes: 431 additions & 0 deletions src/libheif.js

Large diffs are not rendered by default.

Loading

0 comments on commit df15c30

Please sign in to comment.