Skip to content

Commit

Permalink
fixed issue #34: Increased upload image size, added image compression…
Browse files Browse the repository at this point in the history
… and functionality to remove image metadata (#79)
  • Loading branch information
NdibeRaymond authored Jan 22, 2021
1 parent ee5c092 commit 396a2ca
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 32 deletions.
27 changes: 27 additions & 0 deletions zubhub_frontend/zubhub/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions zubhub_frontend/zubhub/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"@testing-library/user-event": "^12.2.2",
"aws-sdk": "^2.813.0",
"classnames": "^2.2.6",
"compressorjs": "^1.0.7",
"date-fns": "^2.16.1",
"formik": "^2.2.5",
"nanoid": "^3.1.20",
Expand All @@ -27,6 +28,7 @@
"redux-thunk": "^2.3.0",
"slick-carousel": "^1.8.1",
"web-vitals": "^0.2.4",
"workerize-loader": "^1.3.0",
"yup": "^0.29.3"
},
"scripts": {
Expand Down
39 changes: 39 additions & 0 deletions zubhub_frontend/zubhub/src/assets/js/Compress.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import Compressor from 'compressorjs';

const Compress = (images, state, handleSetState) => {
let compressed = [];

for (let index = 0; index < images.length; index += 1) {
let image = images[index];

if (image && image.type.split('/')[1] !== 'gif') {
new Compressor(image, {
quality: 0.6,
convertSize: 100000,
success: result => {
compressed.push(result);
shouldSetImages(compressed, images, state, handleSetState);
},
error: error => {
console.warn(error.message);
compressed.push(image);
shouldSetImages(compressed, images, state, handleSetState);
},
});
} else {
compressed.push(image);
shouldSetImages(compressed, images, state, handleSetState);
}
}
};

const shouldSetImages = (compressed, images, state, handleSetState) => {
if (compressed.length === images.length) {
const { image_upload } = state;
image_upload.images_to_upload = compressed;

handleSetState(image_upload);
}
};

export default Compress;
62 changes: 62 additions & 0 deletions zubhub_frontend/zubhub/src/assets/js/removeMetaDataWorker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
export const removeMetaData = imageArr => {
let newImageArr = [];

for (let index = 0; index < imageArr.length; index++) {
let fr = new FileReader();
fr.onload = process;
fr.mainFile = imageArr[index];
fr.readAsArrayBuffer(imageArr[index]);
}

function process() {
let dv = new DataView(this.result);
let offset = 0,
recess = 0;
let pieces = [];
let i = 0;
if (dv.getUint16(offset) === 0xffd8) {
offset += 2;
let app1 = dv.getUint16(offset);
offset += 2;
while (offset < dv.byteLength) {
if (app1 === 0xffe1) {
pieces[i] = { recess: recess, offset: offset - 2 };
recess = offset + dv.getUint16(offset);
i++;
} else if (app1 === 0xffda) {
break;
}
offset += dv.getUint16(offset);
app1 = dv.getUint16(offset);
offset += 2;
}

if (pieces.length > 0) {
let newPieces = [];
pieces.forEach(function (v) {
newPieces.push(this.result.slice(v.recess, v.offset));
}, this);
newPieces.push(this.result.slice(recess));
newImageArr.push(
new Blob(newPieces, { type: imageArr[newImageArr.length].type }),
);

if (newImageArr.length === imageArr.length) {
postMessage(newImageArr);
}
} else {
newImageArr.push(this.mainFile);

if (newImageArr.length === imageArr.length) {
postMessage(newImageArr);
}
}
} else {
newImageArr.push(this.mainFile);

if (newImageArr.length === imageArr.length) {
postMessage(newImageArr);
}
}
}
};
94 changes: 62 additions & 32 deletions zubhub_frontend/zubhub/src/views/create_project/CreateProject.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import {
import * as ProjectActions from '../../store/actions/projectActions';
import ErrorPage from '../error/ErrorPage';
import DO, { doConfig } from '../../assets/js/DO';
import worker from 'workerize-loader!../../assets/js/removeMetaDataWorker'; // eslint-disable-line import/no-webpack-loader-syntax
import Compress from '../../assets/js/Compress';
import { useStateUpdateCallback } from '../../assets/js/customHooks';
import CustomButton from '../../components/button/Button';
import styles from '../../assets/js/styles/views/create_project/createProjectStyles';
Expand All @@ -42,10 +44,23 @@ const useStyles = makeStyles(styles);
let image_field_touched = false;
let video_field_touched = false;

const handleImageFieldChange = (e, refs, props) => {
props.setFieldValue(e.currentTarget.name, refs.imageEl.current);
const handleImageFieldChange = (refs, props, state, handleSetState) => {
refs.imageCountEl.current.innerText = refs.imageEl.current.files.length;
refs.imageCountEl.current.style.fontSize = '0.8rem';

props.setFieldValue('project_images', refs.imageEl.current).then(errors => {
if (!errors['project_images']) {
removeMetaData(refs.imageEl.current.files, state, handleSetState);
}
});
};

const removeMetaData = (images, state, handleSetState) => {
const newWorker = worker();
newWorker.removeMetaData(images);
newWorker.addEventListener('message', e => {
Compress(e.data, state, handleSetState);
});
};

const handleImageButtonClick = (e, props, refs) => {
Expand Down Expand Up @@ -117,7 +132,7 @@ function CreateProject(props) {

useStateUpdateCallback(() => {
if (
state.image_upload.images_to_upload ===
state.image_upload.images_to_upload.length ===
state.image_upload.successful_uploads
) {
handleSetState(upload_project());
Expand Down Expand Up @@ -252,35 +267,30 @@ function CreateProject(props) {
props.setFieldTouched('project_images');
props.setFieldTouched('video');
props.setFieldTouched('materials_used');
props.validateField('title');
props.validateField('description');
props.validateField('project_images');
props.validateField('video');
props.validateField('materials_used');

if (
props.errors['title'] ||
props.errors['description'] ||
props.errors['project_images'] ||
props.errors['video'] ||
props.errors['materials_used']
) {
return;
} else if (refs.imageEl.current.files.length === 0) {
handleSetState(upload_project());
} else {
const project_images = refs.imageEl.current.files;

const { image_upload } = state;
image_upload.images_to_upload = project_images.length;
image_upload.upload_dialog = true;
image_upload.upload_percent = 0;
handleSetState({ image_upload });
image_field_touched = true;
video_field_touched = true;

for (let index = 0; index < project_images.length; index++) {
upload(project_images[index]);
props.validateForm().then(errors => {
if (Object.keys(errors).length > 0) {
return;
} else if (refs.imageEl.current.files.length === 0) {
handleSetState(upload_project());
} else {
const { image_upload } = state;
image_upload.upload_dialog = true;
image_upload.upload_percent = 0;
handleSetState({ image_upload });

for (
let index = 0;
index < image_upload.images_to_upload.length;
index++
) {
upload(image_upload.images_to_upload[index]);
}
}
}
});
}
};

Expand Down Expand Up @@ -446,7 +456,14 @@ function CreateProject(props) {
id="project_images"
name="project_images"
multiple
onChange={e => handleImageFieldChange(e, refs, props)}
onChange={e =>
handleImageFieldChange(
refs,
props,
state,
handleSetState,
)
}
onBlur={props.handleBlur}
/>
<FormHelperText error>
Expand Down Expand Up @@ -689,6 +706,19 @@ export default connect(
: true;
},
)
.test('not_an_image', 'only images are allowed', value => {
if (value) {
let not_an_image = false;
for (let index = 0; index < value.files.length; index++) {
if (value.files[index].type.split('/')[0] !== 'image') {
not_an_image = true;
}
}
return not_an_image ? false : true;
} else {
return true;
}
})
.test('too_many_images', 'too many images uploaded', value => {
if (value) {
return value.files.length > 10 ? false : true;
Expand All @@ -698,12 +728,12 @@ export default connect(
})
.test(
'image_size_too_large',
'one or more of your image is greater than 3mb',
'one or more of your image is greater than 10mb',
value => {
if (value) {
let image_size_too_large = false;
for (let index = 0; index < value.files.length; index++) {
if (value.files[index].size / 1000 > 3072) {
if (value.files[index].size / 1000 > 10240) {
image_size_too_large = true;
}
}
Expand Down

0 comments on commit 396a2ca

Please sign in to comment.