-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add trails, dual-hue, and color-palette effects
- Loading branch information
1 parent
2e89fa4
commit 56303d1
Showing
24 changed files
with
233 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,20 @@ | ||
{ | ||
"files": { | ||
"main.js": "/partymoji/static/js/main.213c5e9d.chunk.js", | ||
"main.js.map": "/partymoji/static/js/main.213c5e9d.chunk.js.map", | ||
"main.js": "/partymoji/static/js/main.dab44c5b.chunk.js", | ||
"main.js.map": "/partymoji/static/js/main.dab44c5b.chunk.js.map", | ||
"runtime-main.js": "/partymoji/static/js/runtime-main.39af959e.js", | ||
"runtime-main.js.map": "/partymoji/static/js/runtime-main.39af959e.js.map", | ||
"static/js/2.1ec7ca6a.chunk.js": "/partymoji/static/js/2.1ec7ca6a.chunk.js", | ||
"static/js/2.1ec7ca6a.chunk.js.map": "/partymoji/static/js/2.1ec7ca6a.chunk.js.map", | ||
"static/js/2.881bd7cb.chunk.js": "/partymoji/static/js/2.881bd7cb.chunk.js", | ||
"static/js/2.881bd7cb.chunk.js.map": "/partymoji/static/js/2.881bd7cb.chunk.js.map", | ||
"index.html": "/partymoji/index.html", | ||
"static/js/2.1ec7ca6a.chunk.js.LICENSE.txt": "/partymoji/static/js/2.1ec7ca6a.chunk.js.LICENSE.txt", | ||
"static/js/effect.worker.158c42ad.worker.js": "/partymoji/static/js/effect.worker.158c42ad.worker.js", | ||
"static/js/effect.worker.158c42ad.worker.js.LICENSE.txt": "/partymoji/static/js/effect.worker.158c42ad.worker.js.LICENSE.txt", | ||
"static/js/effect.worker.158c42ad.worker.js.map": "/partymoji/static/js/effect.worker.158c42ad.worker.js.map" | ||
"static/js/2.881bd7cb.chunk.js.LICENSE.txt": "/partymoji/static/js/2.881bd7cb.chunk.js.LICENSE.txt", | ||
"static/js/effect.worker.d8c48e28.worker.js": "/partymoji/static/js/effect.worker.d8c48e28.worker.js", | ||
"static/js/effect.worker.d8c48e28.worker.js.LICENSE.txt": "/partymoji/static/js/effect.worker.d8c48e28.worker.js.LICENSE.txt", | ||
"static/js/effect.worker.d8c48e28.worker.js.map": "/partymoji/static/js/effect.worker.d8c48e28.worker.js.map" | ||
}, | ||
"entrypoints": [ | ||
"static/js/runtime-main.39af959e.js", | ||
"static/js/2.1ec7ca6a.chunk.js", | ||
"static/js/main.213c5e9d.chunk.js" | ||
"static/js/2.881bd7cb.chunk.js", | ||
"static/js/main.dab44c5b.chunk.js" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/partymoji/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="description" content="App for creating animated gifs and emojis"/><link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"/><script>window.ENV="PROD"</script><script src="https://unpkg.com/@material-ui/core@latest/umd/material-ui.production.min.js"></script><link rel="manifest" href="/partymoji/manifest.json"/><title>Partymoji</title><script>!function(e,a,t,n,g,c,o){e.GoogleAnalyticsObject=g,e.ga=e.ga||function(){(e.ga.q=e.ga.q||[]).push(arguments)},e.ga.l=1*new Date,c=a.createElement(t),o=a.getElementsByTagName(t)[0],c.async=1,c.src="https://www.google-analytics.com/analytics.js",o.parentNode.insertBefore(c,o)}(window,document,"script",0,"ga"),ga("create","UA-XXXXX-Y","auto"),ga("send","pageview")</script><script async src="https://www.googletagmanager.com/gtag/js?id=G-DG40RRJF9R"></script><script>function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag("js",new Date),gtag("config","G-DG40RRJF9R")</script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div style="background-color:#effffd" id="root"/><script>!function(e){function r(r){for(var n,i,a=r[0],l=r[1],p=r[2],c=0,s=[];c<a.length;c++)i=a[c],Object.prototype.hasOwnProperty.call(o,i)&&o[i]&&s.push(o[i][0]),o[i]=0;for(n in l)Object.prototype.hasOwnProperty.call(l,n)&&(e[n]=l[n]);for(f&&f(r);s.length;)s.shift()();return u.push.apply(u,p||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,a=1;a<t.length;a++){var l=t[a];0!==o[l]&&(n=!1)}n&&(u.splice(r--,1),e=i(i.s=t[0]))}return e}var n={},o={1:0},u=[];function i(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,i),t.l=!0,t.exports}i.m=e,i.c=n,i.d=function(e,r,t){i.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,r){if(1&r&&(e=i(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(i.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)i.d(t,n,function(r){return e[r]}.bind(null,n));return t},i.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(r,"a",r),r},i.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},i.p="/partymoji/";var a=this.webpackJsonppartymoji=this.webpackJsonppartymoji||[],l=a.push.bind(a);a.push=r,a=a.slice();for(var p=0;p<a.length;p++)r(a[p]);var f=l;t()}([])</script><script src="/partymoji/static/js/2.1ec7ca6a.chunk.js"></script><script src="/partymoji/static/js/main.213c5e9d.chunk.js"></script></body><footer><div style="font-size:.7rem">Built: 09/23/24 01:38:27 PM EDT</div></footer></html> | ||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/partymoji/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="description" content="App for creating animated gifs and emojis"/><link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"/><script>window.ENV="PROD"</script><script src="https://unpkg.com/@material-ui/core@latest/umd/material-ui.production.min.js"></script><link rel="manifest" href="/partymoji/manifest.json"/><title>Partymoji</title><script>!function(e,a,t,n,g,c,o){e.GoogleAnalyticsObject=g,e.ga=e.ga||function(){(e.ga.q=e.ga.q||[]).push(arguments)},e.ga.l=1*new Date,c=a.createElement(t),o=a.getElementsByTagName(t)[0],c.async=1,c.src="https://www.google-analytics.com/analytics.js",o.parentNode.insertBefore(c,o)}(window,document,"script",0,"ga"),ga("create","UA-XXXXX-Y","auto"),ga("send","pageview")</script><script async src="https://www.googletagmanager.com/gtag/js?id=G-DG40RRJF9R"></script><script>function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag("js",new Date),gtag("config","G-DG40RRJF9R")</script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div style="background-color:#effffd" id="root"/><script>!function(e){function r(r){for(var n,i,a=r[0],l=r[1],p=r[2],c=0,s=[];c<a.length;c++)i=a[c],Object.prototype.hasOwnProperty.call(o,i)&&o[i]&&s.push(o[i][0]),o[i]=0;for(n in l)Object.prototype.hasOwnProperty.call(l,n)&&(e[n]=l[n]);for(f&&f(r);s.length;)s.shift()();return u.push.apply(u,p||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,a=1;a<t.length;a++){var l=t[a];0!==o[l]&&(n=!1)}n&&(u.splice(r--,1),e=i(i.s=t[0]))}return e}var n={},o={1:0},u=[];function i(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,i),t.l=!0,t.exports}i.m=e,i.c=n,i.d=function(e,r,t){i.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,r){if(1&r&&(e=i(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(i.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)i.d(t,n,function(r){return e[r]}.bind(null,n));return t},i.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(r,"a",r),r},i.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},i.p="/partymoji/";var a=this.webpackJsonppartymoji=this.webpackJsonppartymoji||[],l=a.push.bind(a);a.push=r,a=a.slice();for(var p=0;p<a.length;p++)r(a[p]);var f=l;t()}([])</script><script src="/partymoji/static/js/2.881bd7cb.chunk.js"></script><script src="/partymoji/static/js/main.dab44c5b.chunk.js"></script></body><footer><div style="font-size:.7rem">Built: 10/08/24 05:07:53 PM EDT</div></footer></html> |
This file was deleted.
Oops, something went wrong.
6 changes: 3 additions & 3 deletions
6
docs/static/js/2.1ec7ca6a.chunk.js → docs/static/js/2.881bd7cb.chunk.js
Large diffs are not rendered by default.
Oops, something went wrong.
File renamed without changes.
Large diffs are not rendered by default.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
File renamed without changes.
Large diffs are not rendered by default.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -145,7 +145,7 @@ export const readImage = async ( | |
return { | ||
image, | ||
dataUrl, | ||
fps: 1, | ||
fps: 20, // Default FPS | ||
}; | ||
}; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { range } from 'remeda'; | ||
import { colorUtil, imageUtil } from '~/domain/utils'; | ||
import { colorPickerParam, variableLengthParam } from '~/params'; | ||
import { buildEffect } from './utils'; | ||
|
||
const NUM_DEFAULT_COLORS = 6; | ||
const DEFAULT_COLORS = range(0, NUM_DEFAULT_COLORS).map((v) => | ||
colorUtil.setBrightness( | ||
colorUtil.fromHexColor('#98651B'), | ||
(1 - v / NUM_DEFAULT_COLORS) * 100 | ||
) | ||
); | ||
|
||
export const colorPalette = buildEffect({ | ||
name: 'Color Palette', | ||
group: 'Colors', | ||
description: 'Change all colors in the image to a set palette.', | ||
secondaryDescription: | ||
'For instance, the lightest colors in the source image will ' + | ||
'be replaced by the first color, and the darkest colors in the source image will be ' + | ||
'replaced by the last color, etc', | ||
params: [ | ||
variableLengthParam({ | ||
name: 'Palette', | ||
newParamText: 'New Color', | ||
defaultValue: DEFAULT_COLORS, | ||
createNewParam: () => | ||
colorPickerParam({ | ||
name: 'Color', | ||
defaultValue: DEFAULT_COLORS[0], | ||
}), | ||
}), | ||
] as const, | ||
fn: imageUtil.mapImage(({ coord, getSrcPixel, parameters: [palette] }) => { | ||
const src = getSrcPixel(coord); | ||
if (colorUtil.isTransparent(src)) { | ||
return src; | ||
} | ||
|
||
const gray = 255 - colorUtil.getAveragePixelValue(src); | ||
const paletteIndex = Math.floor((gray / 256) * palette.length); | ||
return palette[paletteIndex]; | ||
}), | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { colorUtil, imageUtil } from '~/domain/utils'; | ||
import { colorPickerParam } from '~/params'; | ||
import { buildEffect } from './utils'; | ||
|
||
export const dualHue = buildEffect({ | ||
name: 'Dual Hue', | ||
group: 'Colors', | ||
description: | ||
'The colors of the image will transition from one color to another', | ||
params: [ | ||
colorPickerParam({ | ||
name: 'Color 1', | ||
defaultValue: [255, 0, 0, 1], | ||
}), | ||
colorPickerParam({ | ||
name: 'Color 2', | ||
defaultValue: [0, 255, 0, 1], | ||
}), | ||
] as const, | ||
fn: imageUtil.mapImage( | ||
({ coord, getSrcPixel, parameters: [color1, color2] }) => { | ||
const src = getSrcPixel(coord); | ||
if (colorUtil.isTransparent(src)) { | ||
return src; | ||
} | ||
|
||
const amount = colorUtil.getAveragePixelValue(src) / 256; | ||
return colorUtil.linearInterpolation({ c1: color1, c2: color2, amount }); | ||
} | ||
), | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import { canvasUtil } from '~/domain/utils'; | ||
import { sliderParam } from '~/params'; | ||
import { buildEffect } from './utils'; | ||
import { FrameData } from '~/domain/types'; | ||
|
||
export const trails = buildEffect({ | ||
name: 'Trails', | ||
group: 'Misc', | ||
description: 'Adds a trail of previous animation frames', | ||
requiresAnimation: true, | ||
params: [ | ||
sliderParam({ | ||
name: 'Number of Trails', | ||
description: 'How many previous frames to draw', | ||
min: 1, | ||
max: 10, | ||
defaultValue: 3, | ||
}), | ||
sliderParam({ | ||
name: 'Trail Opacity', | ||
description: 'Controls how transparent each trail is', | ||
min: 1, | ||
max: 100, | ||
defaultValue: 50, | ||
}), | ||
sliderParam({ | ||
name: 'Trail Blur', | ||
description: 'Blurs each the trails, can make things look smoother', | ||
defaultValue: 0, | ||
min: 0, | ||
max: 100, | ||
}), | ||
] as const, | ||
fn: ({ image, parameters: [numTrails, trailOpacity, blur] }) => { | ||
const blurCoefficient = | ||
(Math.max(image.dimensions[0], image.dimensions[1]) / 10000) * blur; | ||
|
||
/* | ||
// assume numTrails = 3, numFrames = 6 | ||
frames[0] = src[4]*25% > src[5]*25% > src[0] | ||
frames[1] = src[5]*25% > src[0]*25% > src[1] | ||
frames[2] = src[0]*25% > src[1]*25% > src[2] | ||
frames[3] = src[1]*25% > src[2]*25% > src[3] | ||
frames[4] = src[2]*25% > src[3]*25% > src[4] | ||
frames[5] = src[3]*25% > src[4]*25% > src[5] | ||
... | ||
*/ | ||
const frames: FrameData[] = []; | ||
for (let i = 0; i < image.frames.length; i += 1) { | ||
const canvas = canvasUtil.createCanvas(image.dimensions); | ||
for (let n = numTrails; n > 0; n -= 1) { | ||
const idx = i - n + 1; | ||
const frameIdx = idx >= 0 ? idx : image.frames.length + idx; | ||
|
||
const frameToCopy = image.frames[frameIdx]; | ||
if (frameToCopy != null) { | ||
canvasUtil.applyFilter(canvas, { | ||
opacity: Math.floor((n / numTrails) * trailOpacity), | ||
blur: Math.floor(n * blurCoefficient), | ||
}); | ||
canvasUtil.drawImageOnCanvas({ | ||
ctx: canvas.ctx, | ||
dimensions: image.dimensions, | ||
frame: frameToCopy, | ||
}); | ||
} | ||
} | ||
canvasUtil.applyFilter(canvas, { | ||
opacity: 100, | ||
blur: 0, | ||
}); | ||
canvasUtil.drawImageOnCanvas({ | ||
ctx: canvas.ctx, | ||
dimensions: image.dimensions, | ||
frame: image.frames[i], | ||
}); | ||
frames.push(canvasUtil.canvasToFrame(canvas)); | ||
} | ||
|
||
return { | ||
dimensions: image.dimensions, | ||
frames, | ||
}; | ||
}, | ||
}); |