Giter VIP home page Giter VIP logo

wasm-imagemagick's Introduction

Web assembly ImageMagick Build Status

This project is not affiliated with ImageMagick , but is merely recompiling the code to be WebAssembly. I did this because I want to bring the power of ImageMagick to the browser.

Table of Contents

Demos and examples

Status

Image formats supported

Supports PNG, TIFF, JPEG, BMP, GIF, PhotoShop, GIMP, and more!

See a list of known supported formats in this demo

Features not supported

API

Reference API Documentation

Reference API Documentation

High level API and utilities

wasm-imagemagick comes with some easy to use APIs for creating image files from urls, executing multiple commands reusing output images and nicer command syntax, and utilities to handle files, html images, input elements, image comparison, metadata extraction, etc. Refer to API Reference Documentation for details.

import { buildInputFile, execute, loadImageElement } from 'wasm-imagemagick'

const { outputFiles, exitCode} = await execute({
  inputFiles: [await buildInputFile('http://some-cdn.com/foo/fn.png', 'image1.png')],
  commands: [
    'convert image1.png -rotate 70 image2.gif',
    // heads up: the next command uses 'image2.gif' which was the output of previous command:
    'convert image2.gif -scale 23% image3.jpg',
  ],
})
if(exitCode !== 0)
    await loadImageElement(outputFiles[0], document.getElementById('outputImage'))

Accessing stdout, stderr, exitCode

This other example executes identify command to extract information about an image. As you can see, we access stdout from the execution result and check for errors using exitCode and stderr:

import { buildInputFile, execute } from 'wasm-imagemagick'

const { stdout, stderr, exitCode } = await execute({
    inputFiles: [await buildInputFile('foo.gif')], 
    commands: `identify foo.gif`
})
if(exitCode === 0) 
    console.log('foo.gif identify output: ' + stdout.join('\n'))
else 
    console.error('foo.gif identify command failed: ' + stderr.join('\n'))

low-level example

As demonstration purposes, the following example doesn't use any helper provided by the library, only the low level call() function which only accept one command, in array syntax only:

import { call } from 'wasm-imagemagick'

// build an input file by fetching its content
const fetchedSourceImage = await fetch("assets/rotate.png")
const content = new Uint8Array(await fetchedSourceImage.arrayBuffer());
const image = { name: 'srcFile.png', content }

const command = ["convert", "srcFile.png", '-rotate', '90', '-resize', '200%', 'out.png']
const result = await call([image], command)

// is there any errors ?
if(result.exitCode !== 0)
    return alert('There was an error: ' + result.stderr.join('\n'))

// response can be multiple files (example split) here we know we just have one
const outputImage = result.processedFiles[0]

// render the output image into an existing <img> element
const outputImage = document.getElementById('outputImage')
outputImage.src = URL.createObjectURL(outputImage.blob)
outputImage.alt = outputImage.name

Importing the library in your project

With npm

npm install --save wasm-imagemagick

**IMPORTANT:

Don't forget to copy magick.wasm and magick.js files to the folder where your index.html is being served:

cp node_modules/wasm-imagemagick/dist/magick.wasm .
cp node_modules/wasm-imagemagick/dist/magick.js .

Then you are ready to import the library in your project like this:

import { execute} from 'wasm-imagemagick'

or like this if you are not using standard modules:

const execute = require('wasm-imagemagick').execute

Loading directly from html file

If you are not working in a npm development environment you can still load the library bundle .js file. It supports being imported as JavaScript standard module or as a UMD module.

Importing magickApi.js as a JavaScript standard module:

Basic version, just reference online https://knicknic.github.io/wasm-imagemagick/magickApi.js no files needed at all.

See samples/rotate#code.

Relevant portions called out below "..." means code is missing from example

  <script type='module'>
    //import the library to talk to imagemagick
    import * as Magick from 'https://knicknic.github.io/wasm-imagemagick/magickApi.js';

    // ...

    // Fetch the image to rotate, and call image magick
    let DoMagickCall = async function () {
      // ....

      // calling image magick with one source image, and command to rotate & resize image
      let processedFiles = await Magick.Call([{ 'name': 'srcFile.png', 'content': sourceBytes }], ["convert", "srcFile.png", "-rotate", "90", "-resize", "200%", "out.png"]);

      // ...
    };
    DoMagickCall();
  </script>

Working example source code.

Below examples need additional files coppied:

Copy magick.js, magick.wasm in the same folder as your html file.:

Importing a bundle as a JavaScript standard module:

<script type="module">
    import { execute, loadImageElement, buildInputFile } from '../../dist/bundles/wasm-imagemagick.esm-es2018.js'
    // ... same snippet as before
</script>

Working example source code

Using the UMD bundle in AMD projects (requirejs)

<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"></script>
<script src="../../dist/bundles/wasm-imagemagick.umd-es5.js"></script>
<script>
require(['wasm-imagemagick'], function (WasmImagemagick) {
    const { execute, loadImageElement, buildInputFile } = WasmImagemagick
    // ... same snippet as before

Working example source code

Using the UMD bundle without libraries

<script src="../../dist/bundles/wasm-imagemagick.umd-es5.js"></script>
<script>
    const { execute, loadImageElement, buildInputFile } = window['wasm-imagemagick']
    // ... same snippet as before

Working example source code

Build instructions

git clone --recurse-submodules https://github.com/KnicKnic/WASM-ImageMagick.git

cd WASM-ImageMagick

#ubuntu instructions
#   install node
sudo snap install --edge node --classic
#   install typescript
sudo npm install typescript -g
#   install docker
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
#   be sure to add your user to the to the docker group and relogin

# install and run build
npm install


#windows instructions
# currently broken
# If you really want a build, create a PR, 
# a build will get kicked off, click show all checks -> Details -> top right of the details page (in artifcats) 

# docker run --rm -it --workdir /code -v %CD%:/code wasm-imagemagick-build-tools bash ./build.sh

Produces magick.js, magickApi.js, & magick.wasm in the current folder.

Run tests

npm test will run all the tests.

npm run test-browser will run spec in a headless chrome browser. These tests are located at ./spec/.

npm run test-browser-server will serve the test so you can debug them with a browser.

npm run test-browser-start will run the server and start watching for file changes, recompile and restart the server for agile development.

npm test-node will run some tests with nodejs located at ./tests/rotate.

wasm-imagemagick's People

Contributors

axure avatar cancerberosgx avatar dependabot[bot] avatar f0urfingeredfish avatar knicknic avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wasm-imagemagick's Issues

Cannot use this library

Hi,

I'd like to user this code inside my react app, i've downloaded the library using npm (npm install --save wasm-imagemagick) as stated in the guide, then i've copied the file from node_modules to the public folder, as stated in the guide.

But when i start the application i get this error: Uncaught SyntaxError: Cannot use import statement outside a module
image im using snowpack, then i've tried to clone the example code you have hosted on codesandbox, but still, when installing the components and run the app, i get this error,
image

How can i solve?

How to import the module using Webpack?

How do I import the module for use with a webpack dev server? Where do I put the magick.wasm and magick.js files? I'm using preact and start the dev server with preact watch. Can I edit webpack.config.js to include the files somehow?

edit: I've tried using copy-webpack-plugin, which seems to work if I build the project, but in the development server I get errors:

Uncaught (in promise) DOMException: Failed to register a ServiceWorker for scope ('https://localhost:8080/') with script ('https://localhost:8080/sw-debug.js'): An unknown error occurred when fetching the script.
DOMException: Failed to construct 'Worker': Script at 'webpack-internal:///../node_modules/wasm-imagemagick/dist/src/magick.js' cannot be accessed from origin 'https://localhost:8080'.
Uncaught (in promise) DOMException: Failed to construct 'Worker': Script at 'webpack-internal:///../node_modules/wasm-imagemagick/dist/src/magick.js' cannot be accessed from origin 'https://localhost:8080'.

Execute fails with 'TypeError: Cannot read property 'buffer' of undefined [...]'

When executing two simple image manipulation commands in a browser environment, the ExecuteResult object will contain an error and only the result of the first command is provided.

Code:

import { buildInputFile, execute } from 'https://cdn.jsdelivr.net/npm/wasm-imagemagick/dist/bundles/magickApi.js';

let DoMagickCall = async function () {
  let result = await execute({
    inputFiles: [await buildInputFile('./locked-out.png', 'frame.png')],
    commands: [
      'convert frame.png -rotate 90 image2.png',
      'convert image2.png -rotate 45 image3.png'
    ]
  });

  console.log(result);
}

DoMagickCall();

Result:

result:
  errors: Array(2)
    0: undefined
    1: "TypeError: Cannot read property 'buffer' of undefined, exit code: 1, stderr: "
  exitCode: 1
  outputFiles: Array(1)
    0: {name: "image2.png", buffer: Uint8Array(67478)}
  results: Array(2)
    0: {outputFiles: Array(1), stdout: Array(0), stderr: Array(0), exitCode: 0, errors: Array(1)}
    1: {stderr: Array(0), stdout: Array(0), outputFiles: Array(0), exitCode: 1, errors: Array(1)}

Download test files to reproduce

WASM-ImageMagick_issue_51.zip

Any ideas why this is happening? Thanks for your help!

Demo with syntax error

The Basic playground demo has a syntax error in it.

SyntaxError
/src/Hello.tsx: Expected corresponding JSX closing tag for <p> (8:104)

   6 | 
   7 | export default ({ name }: Props) => (
>  8 |   <p>Welcome to <a href="https://github.com/KnicKnic/WASM-ImageMagick">WASM-ImageMagick</a> basic demo. </>
     |                                                                                                         ^
   9 | 
  10 | );
  11 | 

   6 | 
   7 | export default ({ name }: Props) => (
>  8 |   <p>Welcome to <a href="https://github.com/KnicKnic/WASM-ImageMagick">WASM-ImageMagick</a> basic demo. </>
     |                                                                                                        ^
   9 | 
  10 | );
  11 | 

Maximum call stack size exceeded on iOS Safari

(neat project! 👍 )

Things work great for me on desktop machines, but not on mobile (ios safari).

For example the rotate example results in the stack trace below.

It looks like magick-wasm doesn't have this issue and may work for me, so I'm going to explore that. I wouldn't have found that project without reading your issues so thanks for sharing your development in the open.

exception thrown: RangeError: Maximum call stack size exceeded.,<?>.wasm-function[194]@[wasm code]
<?>.wasm-function[2078]@[wasm code]
wasm-stub@[native code]
https://knicknic.github.io/wasm-imagemagick/magick.js:131:120835
invoke_iiiiiii@https://knicknic.github.io/wasm-imagemagick/magick.js:131:113258
<?>.wasm-function[2078]@[wasm code]
<?>.wasm-function[1525]@[wasm code]
<?>.wasm-function[2996]@[wasm code]
<?>.wasm-function[436]@[wasm code]
<?>.wasm-function[636]@[wasm code]
<?>.wasm-function[2811]@[wasm code]
<?>.wasm-function[2805]@[wasm code]
<?>.wasm-function[1962]@[wasm code]
wasm-stub@[wasm code]
bb@[native code]
https://knicknic.github.io/wasm-imagemagick/magick.js:131:119263
callMain@https://knicknic.github.io/wasm-imagemagick/magick.js:131:123423
processFiles@https://knicknic.github.io/wasm-imagemagick/magick.js:75:22
https://knicknic.github.io/wasm-imagemagick/magick.js:48:17
doRun@https://knicknic.github.io/wasm-imagemagick/magick.js:131:124045
run@https://knicknic.github.io/wasm-imagemagick/magick.js:131:124268
runCaller@https://knicknic.github.io/wasm-imagemagick/magick.js:131:123045
removeRunDependency@https://knicknic.github.io/wasm-imagemagick/magick.js:131:12921
receiveInstance@https://knicknic.github.io/wasm-imagemagick/magick.js:131:14203
receiveInstantiatedSource@https://knicknic.github.io/wasm-imagemagick/magick.js:131:14492
promiseReactionJob@[native code]

Is there any way to reduce 'magick.wasm' size?

At the moment, the 'magick.wasm' file size is 4.2Mb, which is normal for large projects where complex image or video processing is required, but not so great for small apps.

For example, I use this tool in my project only to load images (without using canvas), to resize it and get color values for each pixel, so all the other 'imagemagick' features I don't really need. And it would be wonderful if it was possible to load some individual parts of the library, instead of all at once. Is it possible to do?

Can support myck conversion?

convert: DelegateLibrarySupportNotBuiltIn 'srcFile.jpg' (LCMS) @ warning/profile.c/ProfileImage/873.

const command = ["convert", "srcFile.jpg", "-colorspace", "CMYK", "-profile", "myck.icc", "out.jpg"];

Error: Command failed: Invalid Parameter - -set

Error: Command failed: Invalid Parameter - -set

at ChildProcess.<anonymous> (E:\meschac\web work\im\node_modules\imagemagick\imagemagick.js:88:15)
at ChildProcess.emit (events.js:182:13)
at maybeClose (internal/child_process.js:961:16)
at Socket.stream.socket.on (internal/child_process.js:380:11)
at Socket.emit (events.js:182:13)
at Pipe._handle.close (net.js:599:12) timedOut: false, killed: false, code: 4, signal: null }

ExtractInfoResultImage type missing optional 'colormap' property.

Some images contain a colormap property of type string[] which contains a list of all colors present in the image. This property, when it exists, is inaccessible when using TypeScript without retyping the ExtractInfoResultImage to any.

Quick fix would be to add it as an optional property to the ExtractInfoResultImage interface in src/util/imageExtractInfoTypes.d.ts (shown here added at the bottom, is this doable?):

export interface ExtractInfoResultImage {
    name: string;
    baseName: string;
    format: string;
    formatDescription: string;
    mimeType: string;
    class: string;
    geometry: ExtractInfoResultGeometry;
    resolution: ExtractInfoResultResolution;
    printSize: ExtractInfoResultPrintSize;
    units: string;
    type: string;
    baseType: string;
    endianess: string;
    colorspace: string;
    depth: number;
    baseDepth: number;
    channelDepth: ExtractInfoResultChannelDepth;
    pixels: number;
    imageStatistics: ExtractInfoResultImageStatistics;
    channelStatistics: ExtractInfoResultChannelStatistics;
    alpha: string;
    renderingIntent: string;
    gamma: number;
    chromaticity: ExtractInfoResultChromaticity;
    matteColor: string;
    backgroundColor: string;
    borderColor: string;
    transparentColor: string;
    interlace: string;
    intensity: string;
    compose: string;
    pageGeometry: ExtractInfoResultPageGeometry;
    dispose: string;
    iterations: number;
    compression: string;
    orientation: string;
    properties: ExtractInfoResultProperties;
    profiles: ExtractInfoResultProfiles;
    tainted: boolean;
    filesize: string;
    numberPixels: string;
    pixelsPerSecond: string;
    userTime: string;
    elapsedTime: string;
    version: string;
    colormap?: string[];     <<<<<<
}

colors.xml

Hello,

By using these commands

const { outputFiles, exitCode, stderr, stdout } = await execute({
    inputFiles: [await buildInputFile(url, file.name)],
    commands: `convert ${file.name} -colors 5 -format "%c" histogram:info:`
})

I get the following error

magick.js:31 convert: UnableToOpenConfigureFile `colors.xml' @ warning/configure.c/GetConfigureOptions/699.

path options when calling commands

I'm in a file a couple directories down from the top, ie ./src/app/xxx/yyy/zzz/file.js
I have a profile I'm trying to apply to an image that's located in ./src/filters/tester.icm.

How should I go about locating tester.icm? I tried using the path ./src/filters/tester.icm, it didn't work. I tried moving tester.icm (using gulp) into dist and just trying ./tester.icm and that didn't work either.

I tried -debug All, but that just told me it couldn't find the file, it didn't tell me the full path it was looking for.

-format info: not printing to stdout

The command convert rose: -format 'sdf %f dfg' info: won't print anything to stdout. Not using -format prints: convert rose: info: or convert rose: -print 'foo' info:

It does work if printing to a file convert rose: -format 'sdf %f dfg' info:foo.txt

I think it might be related to this issue: emscripten-core/emscripten#7360

I think -format will copy bytes to stdout (not using printf or fprintf) so I guess it can be related to that.

Supposedly using emscripten setting EXIT_RUNTIME=1 could help here (https://github.com/kripken/emscripten/blob/941bbc6b9b35d3124f17d2503d7a32cc81032dac/src/settings.js#L71) - but I tried and there is no stdout at all so I'm not sure.

I'll keep investigating. This is a test that reproduces the issue:

xit('should print las chars in stdout and stderr no matter if it doesnt end with new line', async done => {
(skipped with xit()`

Easy way to configure build's features and libraries

I think there's place to configure which libraries to include in the build using environment variables so is easier to generate a smaller wasm in case features /formats are not needed.
a working build without any library weights 2mb and still is able to perform useful things and support many formats. On the other side, with all libraries (and including freetext to support text&fonts) its size is around 7mb. If more and more features/libraries are added being able to somehow configure the build without editing the script could be important.

I would like to prototype something around this so we can discuss. Note that I've never done this and probably there are tools that simplify this but initially I will just use shell if statements and variables. Initially there will be a variable to enable/disable each of the current supported libraries. Also I will try to play with IM configure flags see if more things can be disabled or enabled without adding libs.

There will be an "official" set of features enabled, and that build will be used for running tests. Later we can try to declare test dependencies to selectively run tests on each build.

Also later we can discuss if/how distribute build with different configurations or tools to easily generate/download them.

Also I will research if ALLOW_MEMORY_GROW can be disabled so users can configure also this and the memory size. after seeing the build warning so many times I want to test if such optimizations are really worth it.

Finally I will try to see if emscripten ports for zlib, libpng and others can be used as I used freetype in 'text' branch so we can remove submodules for those and simplify the script. See #32

@KnicKnic I know you want to use Native.Magick build in the future and probably this is not reusable there, but I really want to research on this and test if minimal wasm works. I really don't have much expertise in this area perhaps you know a tool or method for this (I won't learn a new language). Perhaps writing the build using JavaScript with something like shelljs and run it with node could allow us to have less errors and escalate this better? I know shell scripts but I would feel more comfortable being able to declare data in json and building / executing commands and variables with javascript string templates / TypeScript interfaces to declare and document all the settings....do you have any strong opinions? Thanks!

load magick.js from external server

Use cases:

  • So I'm able to use the library directly importing it from my html page without having to npm install or download/copy anything. i.e import * as Magick from 'http://some.cdn/magickApi.js'
  • be able to load the same magick.wasm file from different paths in the same application i.e: /foo/bar/index.html can load /foo/wasm-magick/magick.wasm

(Currently the only way to make it work is if Ii put magick.js and magick.wasm in the same folder as index.html)

Abort current operation

Is it possible to abort current Call() method call ? Use case: in the browser is common that users perform transformations using visual controls and if input images are large or if the transformation is complex then call() method call could take more than 10 seconds and sometimes even much more. In that cases would be awesome to provide users with the possibility of canceling current call. The only workaround right now is to refresh the page which is undesirable.

Thanks! any tip is most welcome. Keep it up!

Node Support

It would be nice if it was possible to run this in node, but currently it isn't possible as it uses Web Workers which are not a thing in node.

I think the node equivelent would be a fork

RuntimeError: float unrepresentable in integer range

Executing commands like the following in small but complex (shaded) images like photos will throw magick.js:74 exception thrown: RuntimeError: float unrepresentable in integer range,

["convert", "pic.jpg", "-charcoal", "5", "picOut.jpg"]

["convert", "pic.jpg", "-segment", "1x1", "+dither", "-colors", "2", "-edge", "1", "-negate", "-normalize", "picOut.jpg"]

Work on simple images, but fails with shaded pictures like photographs (very small ones).

Seems to be a known problem in emscripten that seems to be solved adding a compilation flag: https://kripken.github.io/emscripten-site/docs/compiling/WebAssembly.html#trap-mode . I'm investigating what's the case with this project, and I just wanted to track this problem in this issue. Thanks.

Multi-thread support

So on linux we can use some tricks to use imagemagick in parallel. But on the WASM we're limited to the command line options box.

I know it's probably a lot of work to make it work, but for large image sets, it would be nice if it utilized all my cores (definitively now that processors with large amounts of cores are getting more popular (Ryzen))

https://developers.google.com/web/updates/2018/10/wasm-threads

Fourier transform support

Trying to execute the following command:

["convert", "rotate.png", "+fft", "+ift", "out.png"]

throws the following errors:

convert: UnableToOpenConfigureFile `magic.xml' @ warning/configure.c/GetConfigureOptions/714.

magick.js:74 convert: DelegateLibrarySupportNotBuiltIn `rotate.png' (FFTW) @ warning/fourier.c/ForwardFourierTransformImage/898.

magick.js:74 convert: NoImagesDefined `out.png' @ error/convert.c/ConvertImageCommand/3288.

I guess for this to work we need to enable some library for these transformations at build time (DelegateLibrarySupportNotBuiltIn).

Examples and tutorials should reference NPM

Problem

Current sample code references my private version of hosted imagemagick wasm binaries on my github page.

  1. It is not versioned
  2. Not guaranteed up to date
  3. not guaranteed to not change over time

Solution

Use a CDN that automatically pulls from npm. This gives versioning, guaranteed upto date as well as speed.

Which CDN

Current plan is to use unpkg.com . I chose it because it was shorter a shorter url.

@cancerberoSgx Should we use a different one?

// import * as Magick from 'https://knicknic.github.io/wasm-imagemagick/magickApi.js';
import * as Magick from 'https://unpkg.com/wasm-imagemagick/dist/bundles/magickApi.js';

Notable

Well currently the samples are hosted on knicknic.github.io/imagemagick/rotate however when I updated the code to use the CDN it didn't work

It appears that ublock prevents this cross domain loading of wasm files involving github via easylist uBlockOrigin/uAssets#2309

Additional work

We should at least include in instructions an issue about this loading of wasm files. And in sample code we should detect (via window.location (are we on github.io if so say we should be loading locally rather than cross domain) and raise an alert).

text

Executing the following command:

["convert", "-size", "320x100", "xc:lightblue", "-font", "Candice", "-pointsize", "72", "-tile", "pattern:checkerboard", "-annotate", "+28+68", "asdas", "out.png"]

Throws the following error:

magick.js:74 convert: UnableToOpenConfigureFile `colors.xml' @ warning/configure.c/GetConfigureOptions/714.
magick.js:74 convert: UnableToOpenConfigureFile `type.xml' @ warning/configure.c/GetConfigureOptions/714.
magick.js:74 convert: UnableToReadFont `Candice' @ warning/annotate.c/RenderType/1009.
magick.js:74 convert: DelegateLibrarySupportNotBuiltIn 'Candice' (Freetype) @ warning/annotate.c/RenderFreetype/1847.
magick.js:74 convert: FailedToExecuteCommand `'gs' -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 '-sDEVICE=pngalpha' -dTextAlphaBits=4 -dGraphicsAlphaBits=4 '-r72x72' -g504x144  '-sOutputFile=/tmp/magick-42QA_0BEfbiCPa%d' '-f/tmp/magick-42Gf4sw7fbIDPa' '-f/tmp/magick-42AaUWWpkLaNIP'' (-1) @ error/delegate.c/ExternalDelegateCommand/462.
magick.js:74 convert: FailedToExecuteCommand `'gs' -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 '-sDEVICE=pngalpha' -dTextAlphaBits=4 -dGraphicsAlphaBits=4 '-r72x72' -g504x144  '-sOutputFile=/tmp/magick-42QA_0BEfbiCPa%d' '-f/tmp/magick-42Gf4sw7fbIDPa' '-f/tmp/magick-42AaUWWpkLaNIP' -c showpage' (-1) @ error/delegate.c/ExternalDelegateCommand/462.
magick.js:74 convert: UnableToReadFont `Candice' @ warning/annotate.c/RenderType/1009.
magick.js:74 convert: DelegateLibrarySupportNotBuiltIn 'Candice' (Freetype) @ warning/annotate.c/RenderFreetype/1847.
magick.js:74 convert: FailedToExecuteCommand `'gs' -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 '-sDEVICE=pngalpha' -dTextAlphaBits=4 -dGraphicsAlphaBits=4 '-r72x72' -g504x144  '-sOutputFile=/tmp/magick-42BZwKN-LaAgcA%d' '-f/tmp/magick-42fyXQyXLCAaPp' '-f/tmp/magick-42ryaITPaKIaPp'' (-1) @ error/delegate.c/ExternalDelegateCommand/462.
magick.js:74 convert: FailedToExecuteCommand `'gs' -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 '-sDEVICE=pngalpha' -dTextAlphaBits=4 -dGraphicsAlphaBits=4 '-r72x72' -g504x144  '-sOutputFile=/tmp/magick-42BZwKN-LaAgcA%d' '-f/tmp/magick-42fyXQyXLCAaPp' '-f/tmp/magick-42ryaITPaKIaPp' -c showpage' (-1) @ error/delegate.c/ExternalDelegateCommand/462.

Probably text is not supported by wasm-IM but just in case I wanted to track this limitation here and make sure so we can update README with this information. Thanks

Magick.Call should resolve with more information

Currently Magick.Call will resolve only providing the output files. While this could be enough when working with convert the call should provide other information such as stderr , stdout, exit code. Motivation:

  • so I can call "identify" program and read its stdout
  • So I can grab all output, warnings or error messages thrown by ImageMagick itself and provide it to the user.

Something like the following would be awesome:

const {outputFiles, stdout, stderr, exitCode} = await Magick.Call(...)

exitCode will tell if IM fails (not just an empty output file list).

Thanks

PDF read support

Hello,

I realise PDF read support is not currently supported OOTB. Do you think that we could improve wasm-im to support this too?

Do you have a rough idea what it takes to get this implemented? If it's "easy" I might even try to take this on myself.

Thanks,
Isaac

jpg support

Trying to execute the following command:

["convert", "gnu.jpg", "-rotate", "90", "-resize", "200%", "out.jpg"]

Throws the following error:

magick.js:74 convert: UnableToOpenConfigureFile `magic.xml' @ warning/configure.c/GetConfigureOptions/714.
magick.js:74 convert: UnableToOpenConfigureFile `delegates.xml' @ warning/configure.c/GetConfigureOptions/714.
magick.js:74 convert: NoDecodeDelegateForThisImageFormat `JPEG' @ error/constitute.c/ReadImage/562.
magick.js:74 convert: NoImagesDefined `out.jpg' @ error/convert.c/ConvertImageCommand/3288.

I guess IM must be compiled with some feature / library enabled for jpg support (NoDecodeDelegateForThisImageFormat)

Thanks

-ordered-dither invalid argument

Anyone had this issue with using ordered-dither in the command? The api won’t accept it and the console log says it’s an invalid argument.

convert: InvalidArgument ordered-dither : 'o2x2' @ error/threshold.c/OrderedDitherImage/1730

Webpack build

I can't have your lib working with webpack.
I've got this message in dev console :

Error: Failed to resolve async component default: SecurityError: Worker constructor: Failed to load worker script at "webpack-internal:///./node_modules/wasm-imagemagick/dist/src/magick.js"

Where does magick.js and magick.wasm should go for webpack to found them ?

add npm publish to azure pipeline

Would be awesome if you configure npm publish to azure pipelines as described here:

https://docs.microsoft.com/en-us/azure/devops/pipelines/languages/javascript?view=vsts&tabs=yaml#publish-a-module-to-a-npm-registry

https://docs.microsoft.com/en-us/azure/devops/artifacts/get-started-npm?view=vsts&tabs=new-nav%2Cwindows#step-6-publish-an-npm-package

That way if there is any increment to pagkage.json version field and tests are green it wll automatically published to npm.

Failed to load resource: the server responded with a status of 404 ()

I am trying to 'square' a file using WASM-ImageMagick however I am facing an error I can't figure out. I seems that I can't load some files and my requests to the api are causing 404s.

Here is the Javascript in the 'index.html' I am running:

  <script type='module'>

    //import the library to talk to imagemagick
    import * as Magick from 'https://knicknic.github.io/wasm-imagemagick/magickApi.js';

    // various html elements
    let rotatedImage = document.getElementById('rotatedImage');

    // Fetch the image to rotate, and call image magick
    let DoMagickCall = async function () {
      let fetchedSourceImage = await fetch("artwork.jpg");
      let arrayBuffer = await fetchedSourceImage.arrayBuffer();
      let sourceBytes = new Uint8Array(arrayBuffer);

      // calling image magick with one source image, and command to rotate & resize image
      const files = [{ 'name': 'srcFile.jpg', 'content': sourceBytes }];
      const command = [
        "convert", 
        "srcFile.jpg", 
        "-bordercolor", 
        "transparent", 
        "-border", 
        "1", 
        "-set", 
        'option:distort:viewport "%[fx:max(w,h)]x%[fx:max(w,h)]-%[fx:max((h-w)/2,0)]-%[fx:max((w-h)/2,0)]"',
        "-virtual-pixel",
        "edge",
        "-distort",
        "SRT",
        "0",
        "the_square.jpg"];
      let processedFiles = await Magick.Call(files, command);

      // response can be multiple files (example split)
      // here we know we just have one
      let firstOutputImage = processedFiles[0]
      rotatedImage.src = URL.createObjectURL(firstOutputImage['blob'])
      console.log("created image " + firstOutputImage['name'])
    };
    DoMagickCall();
  </script>

I get the following errors:

Screen Shot 2020-05-09 at 18 20 23

I would appreciate any help!

Multi-image files -or- read mods issue

I'm trying to pull out single images from a multi-image TIFF using read mods...

The command is equivalent to (from a multi-image TIFF of 10 images extract the 0th image):
convert srcFile.tif[0] dstFile.tif

Output file is undefined, errors in console are...

convert: UnableToOpenBlob 'srcFile.tif': No such file or directory @ error/blob.c/OpenBlob/3485.
convert: NoImagesDefined `dstFile.tif' @ error/convert.c/ConvertImageCommand/3300.

This happens no matter the image number (zero to nine).
Does WASM-ImageMagick support this?

output file name in cmdline

I tried to split a filename of abcdefghijklmn.jpg thinking this would generate abcdefghijklmn-0.jpg, abcdefghijklmn-1.jpg, ...
using command convert * -flatten -crop x20% +repage -quality 100 -scene 0 -set filename:mysize %t %[filename:mysize]-%d.jpeg

However I got file name abcdefgh0.jpg. This was unexpected for 2 reasons.

  1. I did not abcdefghijklmn, but the shortened abcdefgh
    My guess is that in the browser it does not detect that it is capable of longer than 8 character file names. I was wondering does anyone know where the detection for what character support your file system has is?
  2. I did not get '-'.
    How would I get the expected abcdefghijklmn-0.jpg, abcdefghijklmn-1.jpg, ...

Repro steps
go here and upload image named abcdefghijklmn.jpg

How to disable console.log calls?

Do you plan to toggling console.log, console.error calls at webworker?
It's a bit confusing to see a lot of logs in console without ebling to turn off this functionality.

print: text => {
stdout.push(text)
console.log(text)
},
printErr: text => {
stderr.push(text)
console.error(text);
},

changes in libjpeg fork

It's important to keep track of the changes you needed to do in IM libraries and this diff is kind of impossible to grasp:

LuaDist/libjpeg@master...KnicKnic:master

I wonder if it's just indentation or if there were changes and what are they.

Reported this issue Just to keep track of this problem. Keep it up

Magica WASM builds

@KnicKnic Just want you to know I was lately playing with my own ImageMagick WASM builds and I finally was successful. Now I have 5mb working wasm with these project's libraries plus webp, freetype, fftw (fast fourier), turbo-jpeg, openjpeg. I'm now working on integrating a couple more since now I think I'm understanding the process better.

https://github.com/cancerberoSgx/magica/tree/master/magick-wasm

But most importantly, besides a couple of exceptions, I'm using the original / latest repositories of IM and libraries without having to hack any files (like configure.ac). The exceptions were libpng (which I needed to include your changes to latest versions) and libjpeg (using your clone).

For libpng, I'm planning to PR ImageMagick/png repo with your changes using EMSCRIPTEN macros appropriately. Unfortunately, I can figure out what where your changes for libjpeg to do the same, if you more or less remember what did you needed to change there please tell me - the commits of your clone repo are kind of useless...

At last there is a script to clone my project magica, replace magick.wasm with the generated one and run magica's tests to check everything is OK.

Now I'm working on make this more configurable, both IM configuration and libraries opt-in. also change magica's tests to be smarter and check if the apability/format they use is available or not so they don¡t blindly change.

Well, I would like this project (WASM-ImageMagick) to use some of this - but my scripts are currently too different to this's so I want to discuss with you first what are your thoughts.

Also I would like to contribute some of this also to Magick.Native too.

Thanks

Seems to break on max ram usage

I seem to get issues when the memory on my chromebook reaches max usage during a convert:

Output in console:

Cannot enlarge memory arrays. Either (1) compile with  -s TOTAL_MEMORY=X  with X higher than the current value 2133196800, (2) compile with  -s ALLOW_MEMORY_GROWTH=1  which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with  -s ABORTING_MALLOC=0 
printErr @ magick.js:32
abort @ magick.js:106
abortOnCannotGrowMemory @ magick.js:106
wasm-function[601]
wasm-function[258]
wasm-function[1162]
wasm-function[792]
wasm-function[277]
wasm-function[1043]
wasm-function[1044]
wasm-function[432]
wasm-function[199]
wasm-function[2068]
(anonymous) @ magick.js:106
invoke_iiiii @ magick.js:106
wasm-function[1511]
wasm-function[2983]
wasm-function[283]
wasm-function[549]
wasm-function[2797]
wasm-function[2791]
wasm-function[1692]
(anonymous) @ magick.js:106
callMain @ magick.js:106
processFiles @ magick.js:69
onmessage @ magick.js:103
magick.js:32 exception thrown: abort("Cannot enlarge memory arrays. Either (1) compile with  -s TOTAL_MEMORY=X  with X higher than the current value 2133196800, (2) compile with  -s ALLOW_MEMORY_GROWTH=1  which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with  -s ABORTING_MALLOC=0 "). Build with -s ASSERTIONS=1 for more info.
printErr @ magick.js:32
callMain @ magick.js:106
processFiles @ magick.js:69
onmessage @ magick.js:103

The app itself starts using 2GB or more memory when converting in my case 46 png's that are about 3-4 MB on average

Use Transferable objects to pass data between worker and page

It seens that webworkers support transference of data betwee the worker and the page with a zero-copy operation, which results in a vast performance improvement when sending large data sets. We should use that to pass input and output files from and to the web-worker:

Add Support for JPEG2000 format (.jp2)

Hi,
I am trying to run:
const command = ["convert", "srcFile.jp2", "out.png"];

I got the following error:
magick.js:32 convert: NoDecodeDelegateForThisImageFormat `JP2' @ error/constitute.c/ReadImage/556.

Is it possible to convert jp2 image to png or jpeg?

No Output File Is created

I am trying to use WASM-ImageMagick but no output seems to be created by my command.

This is the javascript file where I call 'wasm-imagemagick':

import image from "./image.png"
import { buildInputFile, execute, loadImageElement } from 'wasm-imagemagick'

(async () => {
  const { stdout, stderr, exitCode } = await execute({
    inputFiles: [await buildInputFile(image, 'image1.png')],
    commands: 'convert image1.png -rotate 70 image2.png'
  })
  if(exitCode === 0)
      console.log('foo.gif identify output: ' + stdout.join('\n'))
  else
      console.error('foo.gif identify command failed: ' + stderr.join('\n'));

  const maged_img = document.createElement("img")
  maged_img.src = stdout.outputFiles[0]
  console.log(maged_img)
  document.body.appendChild(maged_img)

})();

I get the following error in the browser Javascript console:

app.bundle.js:1 Uncaught (in promise) TypeError: Cannot read property '0' of undefined
    at app.bundle.js:1
    at g (polyfill.bundle.js:1)
    at Generator._invoke (polyfill.bundle.js:1)
    at Generator.forEach.t.<computed> [as next] (polyfill.bundle.js:1)
    at i (app.bundle.js:1)
    at s (app.bundle.js:1)

It seems no output file is being produced by my command as stdout.outputFiles[0] is raising this error.

This is the only error I get. The wasm-imagemagick command seems not to be producing any other error.

I am working with webpack.

I would be thankful for any help!

[Not an Issue] memory / file.destroy()

When interactively transforming several images without reloading the page I'm seeing (obviously) that RAM consumed by chrome increases until at some point the call to WASM will fail (TODO: print the exception).

exception thrown: abort("Cannot enlarge memory arrays. Either (1) compile with  -s TOTAL_MEMORY=X  with X higher than the current value 2136801280, (2) compile with  -s ALLOW_MEMORY_GROWTH=1  which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with  -s ABORTING_MALLOC=0 "). Build with -s ASSERTIONS=1 for more info.

You can simulate it if you have low free memory (chrome with many tabs open) and open this one: https://cancerberosgx.github.io/autumn-leaves/photo-morph/#%7B%22selectedImageUrls%22%3A%5B%22https%3A%2F%2Fimages.unsplash.com%2Fphoto-1460400355256-e87506dcec4f%3Fixlib%3Drb-0.3.5%26s%3Db4a72fe29f709d81050016ca2a75f053%26auto%3Dformat%26fit%3Dcrop%26w%3D1350%26q%3D80%22%2C%22https%3A%2F%2Fimages.unsplash.com%2Fphoto-1439127989242-c3749a012eac%3Fixlib%3Drb-0.3.5%26s%3D7fc8fea1879fe330634a89948a6e5d06%26auto%3Dformat%26fit%3Dcrop%26w%3D1350%26q%3D80%22%2C%22https%3A%2F%2Fimages.unsplash.com%2Fphoto-1467825487722-2a7c4cd62e75%3Fixlib%3Drb-0.3.5%26s%3D2403f6e3a8a69f23e2a842720b87ffbe%26auto%3Dformat%26fit%3Dcrop%26w%3D1350%26q%3D80%22%2C%22https%3A%2F%2Fimages.unsplash.com%2Fphoto-1460088033389-a14158fa866d%3Fixlib%3Drb-0.3.5%26s%3D841ae3028c1ef31c36454c40a18b92b9%26auto%3Dformat%26fit%3Dcrop%26w%3D1353%26q%3D80%22%5D%2C%22selectedMorph%22%3A%22Tile4Morph%22%2C%22selectedMorphValue%22%3A%7B%22frames%22%3A6%2C%22loop%22%3A0%2C%22speed%22%3A4%2C%22delayShort%22%3A10%2C%22delayLong%22%3A50%2C%22imageWidth%22%3A0%2C%22imageHeight%22%3A0%7D%7D

Basically that one will load 4 big images and then try to execute a command with several intermediate images. It's failing.

I wander if we should provide a method to dispose/destroy the input and output files ? I'm almost sure the memory consumption is at the .html level not at the webworker's because there we are removing files but I think we should at some point analyse this problem

That's why I'm creating this issue and also I wanted to know your opinion

Thanks!

`let` declaration breaks worker

The onmessage function provided in the worker file magick.js from 'distis declared withlet. Therefore onmessageis not a property ofself`, making the script fail to work as expected.

The example given in README.md works, because inside their magick.js, onmessage is introduced without any keyword.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.