Skip to content

Commit

Permalink
Add EXIF transform feature
Browse files Browse the repository at this point in the history
Add EXIF transform feature to clipper-upload component
  • Loading branch information
timtnleeProject committed Feb 21, 2019
1 parent b006ff6 commit 6e616a2
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 11 deletions.
5 changes: 5 additions & 0 deletions package-lock.json

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

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"exif-js": "^2.3.0",
"rxjs": "^6.3.2",
"vue-rx": "^6.0.1"
},
Expand Down Expand Up @@ -53,7 +54,7 @@
],
"rules": {
"indent": [
"warn",
"error",
2
]
},
Expand Down
7 changes: 2 additions & 5 deletions src/components/clipper-basic.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
<div class="extend inner" :style="exInnerStyle">
<div class="drag-inset"></div>
</div>
<div v-if="corner" v-for="index in 4" :key="'corner'+index" class="corner" :class="`corner${index}`">
<div v-if="corner">
<div v-for="index in 4" :key="'corner'+index" class="corner" :class="`corner${index}`"></div>
</div>
<div v-if="grid" class="grid">
<div v-for="index in 4" :key="'gridItem'+index" class="grid-item"></div>
Expand Down Expand Up @@ -379,10 +380,6 @@ $cover_color: rgba(0, 0, 0, 0.4);
$border-color: #1baae8;
$grid-width: 1px; //dive 2
// .clipper-basic {
// // width: 100%;
// // height: 100%;
// }
.clip-area {
position: relative;
width: 100%;
Expand Down
96 changes: 91 additions & 5 deletions src/components/clipper-upload.vue
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
<template>
<div @click="triggerInput">
<slot></slot>
<img class="stem" :src="DomString" style="display:none">
<input type="file" class="upload" :accept="accept" @input="upload($event)" @click="clear($event)" style="display:none">
</div>
</template>

<script>
import exif from "exif-js";
export default {
mounted(){
this.uploadEl = this.$el.querySelector('.upload')
},
props: {
accept: {
type: String,
default: 'image/*'
default: '*'
},
exif: {
type: Boolean,
default: true
},
value: {
type: String,
Expand All @@ -33,12 +40,91 @@ export default {
methods: {
upload: function(e){
if(e.target.files.length!==1) return;
const file = e.target.files[0];
if (this.check && !file.type.startsWith('image/')) return;
this.file = e.target.files[0];
if (this.check && !this.file.type.startsWith('image/')) return;
if(this.DomString)
window.URL.revokeObjectURL(this.DomString)
this.DomString = window.URL.createObjectURL(file)
this.$emit('input', this.DomString)
this.DomString = window.URL.createObjectURL(this.file)
this.checkEXIF().then(()=>{
this.$emit('input', this.DomString)
})
},
checkEXIF: function(){
return new Promise((res,rej)=>{
if (!this.exif) return rej()
res()
})
.then(()=>this.getEXIF())
.then(orientation=>this.getImageRect()
.then(({width,height})=>{
return Promise.resolve({
width,
height,
orientation
})
})
.catch(()=>Promise.reject()))
.then(this.tranformCanvas)
.catch(()=>Promise.resolve()) //just use catch to escape chains
},
getEXIF: function(){
return new Promise((res,rej)=>{
exif.getData(this.file,function(){
const orientation = this.exifdata.Orientation
if (orientation === undefined || orientation === 1) rej()
res(orientation)
})
})
},
getImageRect: function() {
return new Promise((res,rej)=>{
const img = this.$el.querySelector('.stem')
if (img.complete) return res({
width: img.naturalWidth,
height: img.naturalHeight
})
img.onload = function(){
res({
width: this.naturalWidth,
height: this.naturalHeight
})
}
img.onerror = function(err) {
rej()
}
})
},
tranformCanvas: function({width,height,orientation}) {
/**This piece of code is referenced to
* https://stackoverflow.com/questions/20600800/js-client-side-exif-orientation-rotate-and-mirror-jpeg-images */
const canvas = document.createElement('canvas')
const ctx = canvas.getContext("2d");
// set proper canvas dimensions before transform & export
if (4 < orientation && orientation < 9) {
canvas.width = height;
canvas.height = width;
} else {
canvas.width = width;
canvas.height = height;
}
// transform context before drawing image
switch (orientation) {
case 2: ctx.transform(-1, 0, 0, 1, width, 0); break;
case 3: ctx.transform(-1, 0, 0, -1, width, height); break;
case 4: ctx.transform(1, 0, 0, -1, 0, height); break;
case 5: ctx.transform(0, 1, 1, 0, 0, 0); break;
case 6: ctx.transform(0, 1, -1, 0, height, 0); break;
case 7: ctx.transform(0, -1, -1, 0, height, width); break;
case 8: ctx.transform(0, -1, 1, 0, 0, width); break;
default: break;
}
ctx.drawImage(this.$el.querySelector('.stem'),0,0)
this.DomString = canvas.toDataURL(this.file.type)
},
clear: function(e){
e.target.value = null;
Expand Down

1 comment on commit 6e616a2

@timtnleeProject
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refer to #2

Please sign in to comment.