Skip to content

Commit

Permalink
execute pass only command when output files not neccesary and execute…
Browse files Browse the repository at this point in the history
…AndReturnOutputFile
  • Loading branch information
cancerberoSgx committed Nov 17, 2018
1 parent 84728ba commit c79515e
Show file tree
Hide file tree
Showing 10 changed files with 272 additions and 40 deletions.
3 changes: 2 additions & 1 deletion samples/interactive-execute-context/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
"description": "html page that transform images in different formats (not understandable by the browser), transform each of them to png and show a table with all these transformations.",
"main": "dist/index.js",
"scripts": {
"all": "npm run clean && npm run build && npm run copy",
"build": "tsc && npm run bundle",
"bundle": "browserify dist/index.js -o static/bundle.js",
"copy": "cp -r ../../spec/assets/fn.png ../../spec/assets/magick.* src/static/* static",
"clean": "rm -rf dist static",
"start": "npm run clean && npm run build && npm run copy && npm run watch-all",
"start": "npm run all && npm run watch-all",
"server": "http-server static",
"watch-all": "concurrently 'npm run watch-build' 'npm run watch-server' ",
"watch-build": "onchange -v 'src/**/*' -- npm run build",
Expand Down
142 changes: 135 additions & 7 deletions samples/interactive-execute-context/src/commandExamples.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ExecuteCommand, asCommand, Command, MagickInputFile, extractInfo } from "wasm-imagemagick";
import { sampleCommandTemplates } from "imagemagick-browser";
import { ExecuteCommand, asCommand, Command, MagickInputFile, extractInfo } from 'wasm-imagemagick'
import { sampleCommandTemplates } from 'imagemagick-browser'

export interface Example {
name: string
Expand All @@ -8,6 +8,19 @@ export interface Example {
}

export const commandExamples: Example[] = [


{
name: 'simple append',
description: `simple append+ command that joins two images`,
command: `
convert -size 100x100 xc:red \\
\( rose: -rotate -90 \) \\
+append output.png
`.trim(),
},


{
name: 'stars spiral and inwards',
description: `By Polar Distorting the image we can make the comets flying or spiraling into a point!`,
Expand All @@ -24,24 +37,139 @@ convert -size 250x100 xc: +noise Random -channel R -threshold .4% \\
\( +clone \) -compose multiply -flatten \\
-virtual-pixel Tile -background Black \\
-blur 0x.6 -motion-blur 0x15-60 -normalize \\
+distort Polar 0 +repage star_spiral.gif`.trim()
}
+distort Polar 0 +repage star_spiral.gif`.trim(),
},

{
name: 'falling stars',
description: `use "-motion-blur" to create a field of falling stars`,
command: `
convert -size 100x100 xc: +noise Random -channel R -threshold .4% \\
-negate -channel RG -separate +channel \\
\( +clone \) -compose multiply -flatten \\
-virtual-pixel tile -blur 0x.4 -motion-blur 0x20+45 -normalize \\
star_fall.gif`.trim(),
},
{
name: 'simple stars',
description: `A random noise image is used to thin itself out generate a speckle pattern. Then some effects and colors`,
command: `
convert -size 100x100 xc: +noise Random -channel R -threshold 5% \\
-negate -channel RG -separate +channel \\
-compose multiply -composite speckles.gif
convert -size 100x100 xc: +noise Random -channel R -threshold 1% \\
-negate -channel RG -separate +channel \\
\( +clone \) -compose multiply -flatten \\
-virtual-pixel tile -blur 0x.4 -contrast-stretch .8% \\
stars.gif
convert -size 100x100 xc: +noise Random -channel R -threshold 1% \\
-negate -channel RG -separate +channel \\
\( xc: +noise Random \) -compose multiply -flatten \\
-virtual-pixel tile -blur 0x.4 -contrast-stretch .8% \\
stars_colored.gif
`.trim(),
},

// commented - not working :
{
name: 'star bursts',
description: `Here we motion blur the stars in six directions (in pairs) then merge them together to create a field of 'star bursts', such as you get in a glass lens.`,
command: `
convert -size 100x100 xc: +noise Random -channel R -threshold .2% \\
-negate -channel RG -separate +channel \\
\( +clone \) -compose multiply -flatten \\
-virtual-pixel tile -blur 0x.3 \\
\( -clone 0 -motion-blur 0x10+15 -motion-blur 0x10+195 \) \\
\( -clone 0 -motion-blur 0x10+75 -motion-blur 0x10+255 \) \\
\( -clone 0 -motion-blur 0x10-45 -motion-blur 0x10+135 \) \\
-compose screen -background black -flatten -normalize \\
-compose multiply -layers composite \\
-set delay 30 -loop 0 -layers Optimize \\
star_field.gif`.trim(),
},

{
name: 'stars animation',
description: `By combining the above with a plasma glitter animation you can make set of stars that look like christmas decorations.`,
command: `
convert -size 100x100 xc: +noise Random -separate \\
null: \\
\( xc: +noise Random -separate -threshold 50% -negate \) \\
-compose CopyOpacity -layers composite \\
null: \\
plasma:red-firebrick plasma:red-firebrick plasma:red-firebrick \\
-compose Screen -layers composite \\
null: \\
\( xc: +noise Random -channel R -threshold .08% \\
-negate -channel RG -separate +channel \\
\( +clone \) -compose multiply -flatten \\
-virtual-pixel tile -blur 0x.4 \\
\( -clone 0 -motion-blur 0x15+90 -motion-blur 0x15-90 \) \\
\( -clone 0 -motion-blur 0x15+30 -motion-blur 0x15-150 \) \\
\( -clone 0 -motion-blur 0x15-30 -motion-blur 0x15+150 \) \\
-compose screen -background black -flatten -normalize \) \\
-compose multiply -layers composite \\
-set delay 30 -loop 0 -layers Optimize stars_xmas.gif
`.trim(),
},

{
name: 'radial flare',
description: `the width of the initial image before polar distorting, basically sets the number of rays that will be produced`,
command: `
convert -size 100x1 xc: +noise Random -channel G -separate +channel \\
-scale 100x100! +write flare_1a.png \\
\( -size 100x100 gradient:gray(100%) -sigmoidal-contrast 10x50% \) \\
-colorspace sRGB -compose hardlight -composite +write flare_1b.png \\
-virtual-pixel HorizontalTileEdge -distort Polar -1 \\
flare_1_final.png
`.trim(),
},


{
name: 'radial flare2',
description: `another example using multiple overlays to achieve a different looking flare. Note the technique used to generating intermediate debugging and example images showing the steps involved.`,
command: `
convert -size 100x1 xc: +noise Random -channel G -separate +channel \\
-size 100x99 xc:black -append -motion-blur 0x35-90 \\
\( -size 100x50 gradient:gray(0) \\
-evaluate cos .5 -sigmoidal-contrast 3,100% \\
-size 100x50 xc:gray(0) -append \) \\
\( -size 1x50 xc:gray(0) \\
-size 1x1 xc:gray(50%) \\
-size 1x49 xc:gray(0) \\
-append -blur 0x2 -scale 100x100! \) \\
-scene 10 +write flare_2%x.png \\
-background gray(0) -compose screen -flatten +write flare_2f.png \\
-virtual-pixel HorizontalTileEdge -distort Polar -1 \\
-colorspace sRGB flare_2_final.png
`.trim(),
},





]

let selectExampleCounter = 0

sampleCommandTemplates.forEach(template => {

const example : Example = {
const example: Example = {
name: template.name,
description: template.description,
command: async function(inputFiles: MagickInputFile[]) {
async command(inputFiles: MagickInputFile[]) {
const img = inputFiles[0]
const info = await extractInfo(img)
const context = { ...template.defaultTemplateContext, imageWidth: info[0].image.geometry.width, imageHeight: info[0].image.geometry.height }
const command = template.template(context)[0].map(s => s === '$INPUT' ? img.name : s === '$OUTPUT' ? `output${selectExampleCounter++}.png` : s)
return command
}
},
}
commandExamples.push(example)

Expand Down
65 changes: 62 additions & 3 deletions spec/executeSpec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { buildInputFile, compare, extractInfo, execute, executeOne } from '../src'
import { buildInputFile, compare, execute, executeAndReturnOutputFile, executeOne, extractInfo } from '../src'
import { showImages } from './testUtil'

export default describe('execute', () => {

Expand Down Expand Up @@ -71,9 +72,51 @@ export default describe('execute', () => {
})
const result2 = await executeOne({
inputFiles: [await buildInputFile('fn.png', 'image1.png')],
commands: ['convert image1.png -rotate 70 -scale 23% image2.gif'],
commands: ['convert image1.png -rotate 70 -scale 23% image2.png'],
})
expect(await compare(outputFiles.find(f => f.name === 'image3.jpg'), result2.outputFiles[0])).toBe(true)
const image3 = outputFiles.find(f => f.name === 'image3.jpg')
const image2 = result2.outputFiles[0]
// await showImages([image3,image2])
expect(await compare(image3, image2)).toBe(true)
done()
})

it('supports just a command when no input files are necessary', async done => {
const { outputFiles } = await execute([
'convert rose: -rotate 70 image2.gif',
'convert image2.gif -scale 23% image3.jpg',
])
const result2 = await execute('convert rose: -rotate 70 -scale 23% image2.png')
const image3 = outputFiles.find(f => f.name === 'image3.jpg')
const image2 = result2.outputFiles[0]
await showImages([image3, image2])

expect(await compare(image3, image2)).toBe(true)
done()
})

it('convert won\'t replace input files', async done => {
const input = await buildInputFile('fn.png')
const result = await execute({
inputFiles: [input],
commands: ['convert fn.png -rotate 10 fn.png'],
})
const output = result.outputFiles.find(f => f.name === 'fn.png')
expect(output).toBeUndefined()
done()
})

it('mogrify will replace input files', async done => {
const input = await buildInputFile('fn.png')
const result = await execute({
inputFiles: [input],
commands: ['mogrify -rotate 10 fn.png'],
})
const output = result.outputFiles.find(f => f.name === 'fn.png')
expect(output).toBeDefined()
const converted = await executeAndReturnOutputFile({ inputFiles: [input], commands: 'convert fn.png -rotate 10 output.png' })
// await showImages([output, converted])
expect(await compare(output, converted)).toBe(true)
done()
})

Expand Down Expand Up @@ -134,5 +177,21 @@ export default describe('execute', () => {
})
})

describe('executeAndReturnOutputFile', () => {
it('should support using just a command when input files are not necessary', async done => {
const out = await executeAndReturnOutputFile('convert rose: -rotate 55 -resize 55% out.png')
expect(out.name).toBe('out.png')

const out2 = await executeAndReturnOutputFile(`
convert rose: -rotate 55 out1.png
convert out1.png -resize 55% out2.png
`, 'out2.png')
expect(out2.name).toBe('out2.png')
expect(await compare(out, out2)).toBe(true)

done()
})
})

xit('event emitter', () => { })
})
12 changes: 12 additions & 0 deletions spec/testUtil.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import pMap from 'p-map'
import { loadImageElement, MagickFile } from '../src'

export async function showImages(images: MagickFile[]): Promise<void> {
await pMap(images, async image => {
const el = document.createElement('img')
el.title = image.name
el.alt = image.name
document.body.appendChild(el)
return await loadImageElement(image, el)
}, {concurrency: 1})
}
33 changes: 14 additions & 19 deletions spec/util/htmlSpec.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,34 @@
import { buildInputFile, loadImageElement, compare, execute } from '../../src'
import { buildInputFile, loadImageElement, compare, execute, Call, executeOne } from '../../src'

export default describe('util/html', () => {

describe('loadImageElement', () => {

it('should display an input image in an html img element', async done => {
it('should display an input and output images in an html img element', async done => {
const img1 = await buildInputFile('fn.png')
const el = document.createElement('img')
document.body.appendChild(el)

let el = document.createElement('img')
// document.body.appendChild(el)
expect(el.src).toBeFalsy()
await loadImageElement(img1, el)
expect(el.src).toBeTruthy()
expect('visually check in the browser').toBe('visually check in the browser')

const img2 = await buildInputFile(el.src, 'image2.png')
// expect('visually check in the browser').toBe('visually check in the browser')

let img2 = await buildInputFile(el.src, 'image2.png')
expect(await compare(img1, img2)).toBe(true)
done()
})

xit('should display an output image in an html img element', async done => {
// const result = execute({inputFiles: [await buildInputFile('fn.png')], commands :[ 'convert fn.png -rotate 90 out.git'])
const {outputFiles} = await executeOne({inputFiles: [img1], commands: ['convert fn.png -rotate 55 out.png']})
const out = outputFiles[0]

// const el = document.createElement('img')
el = document.createElement('img')
// document.body.appendChild(el)

// expect(el.src).toBeFalsy()
// await loadImageElement(img1, el)
// expect(el.src).toBeTruthy()
expect(el.src).toBeFalsy()
await loadImageElement(out, el)
expect(el.src).toBeTruthy()
// expect('visually check in the browser').toBe('visually check in the browser')

// const img2 = await buildInputFile(el.src, 'image2.png')
img2 = await buildInputFile(el.src, 'image2.png')
expect(await compare(out, img2)).toBe(true)

// expect(await compare(img1, img2)).toBe(true)
done()
})

Expand Down
Loading

0 comments on commit c79515e

Please sign in to comment.