diff --git a/src/components/LoadDrawing.jsx b/src/components/LoadDrawing.jsx index c45c6d86..d33bd91c 100644 --- a/src/components/LoadDrawing.jsx +++ b/src/components/LoadDrawing.jsx @@ -3,6 +3,7 @@ import { fromJS } from 'immutable'; import Preview from './Preview'; import Output from './Output'; import UsefulData from './UsefulData'; +import LoadImgFile from './LoadImgFile'; import { getDataFromStorage, removeProjectFromStorage, @@ -196,6 +197,12 @@ export default class LoadDrawing extends React.Component { const { frames, columns } = this.props; return ; } + case 'loadImgFile': { + const { actions, frames, columns } = this.props; + return ( + + ); + } default: { const drawings = this.giveMeDrawings(); const drawingsStored = drawings.length > 0; diff --git a/src/components/LoadImgFile.jsx b/src/components/LoadImgFile.jsx new file mode 100644 index 00000000..e0e13967 --- /dev/null +++ b/src/components/LoadImgFile.jsx @@ -0,0 +1,120 @@ +import React, { useRef, useEffect } from 'react'; +import { fromJS } from 'immutable'; +import shortid from 'shortid'; +import getTimeInterval from '../utils/intervals'; + +const LoadImgFile = props => { + const canvasRef = useRef(null); + + useEffect(() => { + const canvas = canvasRef.current; + const context = canvas.getContext('2d'); + + context.fillStyle = '#CCCCCC'; + context.fillRect(0, 0, context.canvas.width, context.canvas.height); + }, []); + + const onChange = ev => { + const file = ev.target.files[0]; + if (canvasRef && file.type.match('image.*')) { + const reader = new FileReader(); + const canvas = canvasRef.current; + const context = canvas.getContext('2d'); + const img = new Image(); + img.crossOrigin = 'anonymous'; + img.style.display = 'none'; + img.onload = function() { + context.canvas.width = img.width; + context.canvas.height = img.height; + context.drawImage(img, 0, 0); + }; + reader.readAsDataURL(file); + reader.onload = function(evt) { + if (evt.target.readyState === FileReader.DONE) { + img.src = evt.target.result; + } + }; + } + }; + + const getHeightIntervals = (imageHeight, frameCount) => { + const heightPerFrame = Math.floor(imageHeight / frameCount); + const intervals = []; + let top = 0; + let bottom = heightPerFrame; + for (let i = 0; i < frameCount; i++) { + intervals.push({ + top, + bottom, + timePercentage: getTimeInterval(i, frameCount) + }); + top += heightPerFrame; + bottom = heightPerFrame; + } + return intervals; + }; + + const generateFrames = (imageContext, frameCount = 1) => { + const { width, height } = imageContext.canvas; + const heightIntervals = getHeightIntervals(height, frameCount); + + const frameCollection = []; + + heightIntervals.forEach(heightInterval => { + const currentImage = imageContext.getImageData( + 0, + heightInterval.top, + width, + heightInterval.bottom + ).data; + frameCollection.push({ + grid: currentImage.reduce((acc, rgbaProperty, index) => { + const colorPosition = acc.length ? acc.length - 1 : 0; + let colorValue = acc.length ? acc[colorPosition] : ''; + + if (index === 0 || index % 4 === 0) { + colorValue = `rgba(${rgbaProperty},`; + acc.push(colorValue); + } else { + colorValue += `${rgbaProperty}${index % 4 === 3 ? ')' : ','}`; + acc[colorPosition] = colorValue; + } + return acc; + }, []), + interval: heightInterval.timePercentage, + key: shortid.generate() + }); + }); + + return fromJS(frameCollection); + }; + + const onClick = () => { + const { actions } = props; + const canvas = canvasRef.current; + const context = canvas.getContext('2d'); + const defaultPixelSize = 5; + const frameCount = 1; + + const frames = generateFrames(context, frameCount); + + actions.setDrawing( + frames, + [], + defaultPixelSize, + context.canvas.width, + Math.floor(context.canvas.height / frameCount) + ); + }; + + return ( + <> + + + + + ); +}; +export default LoadImgFile; diff --git a/src/components/Modal.jsx b/src/components/Modal.jsx index 7f0e4419..14966ae6 100644 --- a/src/components/Modal.jsx +++ b/src/components/Modal.jsx @@ -77,6 +77,12 @@ class Modal extends React.Component { description: 'Useful Data', labelFor: 'useful-data', id: 3 + }, + { + value: 'loadImgFile', + description: 'Load Image from File', + labelFor: 'load-img-file', + id: 4 } ]; } diff --git a/src/store/reducers/framesReducer.js b/src/store/reducers/framesReducer.js index e4ff6c9f..c7bce9b3 100644 --- a/src/store/reducers/framesReducer.js +++ b/src/store/reducers/framesReducer.js @@ -1,6 +1,7 @@ import { List, Map, fromJS } from 'immutable'; import shortid from 'shortid'; import * as types from '../actions/actionTypes'; +import getTimeInterval from '../../utils/intervals'; const createGrid = numCells => { let newGrid = List(); @@ -52,22 +53,14 @@ const create = (cellsCount, intervalPercentage) => key: shortid.generate() }); -const resetIntervals = frameList => { - const equalPercentage = 100 / frameList.size; - - return frameList.map((frame, index) => { - const percentage = - index === frameList.size - 1 - ? 100 - : Math.round((index + 1) * equalPercentage * 10) / 10; - return Map({ +const resetIntervals = frameList => + frameList.map((frame, index) => + Map({ grid: frame.get('grid'), - interval: percentage, + interval: getTimeInterval(index, frameList.size), key: frame.get('key') - }); - }); -}; - + }) + ); const getFrame = (frames, frameId) => { const frameList = frames.get('list'); const frame = frameList.get(frameId); diff --git a/src/store/reducers/paletteReducer.js b/src/store/reducers/paletteReducer.js index fe162720..59acd82f 100644 --- a/src/store/reducers/paletteReducer.js +++ b/src/store/reducers/paletteReducer.js @@ -110,8 +110,13 @@ const setCustomColor = (palette, { customColor }) => { ); }; -const setPalette = (palette, action) => - palette.set('grid', fromJS(action.paletteGridData)); +const setPalette = (palette, action) => { + const defaultPalette = action.paletteGridData.length === 0; + return palette.set( + 'grid', + fromJS(defaultPalette ? createPaletteGrid() : action.paletteGridData) + ); +}; export default function paletteReducer(palette = createPalette(), action) { switch (action.type) { diff --git a/src/utils/intervals.js b/src/utils/intervals.js new file mode 100644 index 00000000..9ea46476 --- /dev/null +++ b/src/utils/intervals.js @@ -0,0 +1,6 @@ +export default function getTimeInterval(currentFrameIndex, totalFrames) { + const equalPercentage = 100 / totalFrames; + return totalFrames === 1 + ? 100 + : Math.round((currentFrameIndex + 1) * equalPercentage * 10) / 10; +}