Index: /main/trunk/model-interfaces-dev/atea/ocr/src/components/EditPage.vue
===================================================================
--- /main/trunk/model-interfaces-dev/atea/ocr/src/components/EditPage.vue	(revision 35745)
+++ /main/trunk/model-interfaces-dev/atea/ocr/src/components/EditPage.vue	(revision 35746)
@@ -23,10 +23,14 @@
             </table>
 
-            <img ref="image" :src="imageUrl" class="image" :style="{ filter: filterString }" />
+            <img ref="image" :src="src" class="image" :style="{ filter: filterString }" />
         </div>
     </div>
 
     <div class="control-panel">
-        <button class="btn-fab" @click="$emit('closeRequested')">
+        <button class="btn-fab" @click="$emit('closeAndDiscard')">
+            <span class="material-icons mdi-l">cancel</span>
+        </button>
+
+        <button class="btn-fab" @click="closeAndSave">
             <span class="material-icons mdi-l">save</span>
         </button>
@@ -151,9 +155,10 @@
     },
     props: {
-        image: File
-    },
+        imageBuffer: ArrayBuffer,
+        src: String
+    },
+    emits: [ "closeAndDiscard", "closeAndSave" ],
     data() {
         return {
-            imageUrl: URL.createObjectURL(this.image),
             invert: false,
             rotation: 0,
@@ -183,6 +188,6 @@
     },
     methods: {
-        async getImageBlobAsync() {
-            const buffer = Buffer.from(this.image.arrayBuffer());
+        async closeAndSave() {
+            const buffer = Buffer.from(this.imageBuffer);
             const that = this;
 
@@ -193,12 +198,12 @@
                     }
 
-                    // if (that.rotation !== 0) {
-                    //     image.rotate(that.rotation);
-                    // }
+                    if (that.rotation !== 0) {
+                        image.rotate(-that.rotation);
+                    }
 
                     return await image.getBufferAsync(Jimp.MIME_PNG);
                 });
 
-            return new Blob([ modifiedBuffer ], { type: Jimp.MIME_PNG });
+            this.$emit("closeAndSave", modifiedBuffer, Jimp.MIME_PNG);
         },
 
Index: /main/trunk/model-interfaces-dev/atea/ocr/src/components/MainPage.vue
===================================================================
--- /main/trunk/model-interfaces-dev/atea/ocr/src/components/MainPage.vue	(revision 35745)
+++ /main/trunk/model-interfaces-dev/atea/ocr/src/components/MainPage.vue	(revision 35746)
@@ -1,8 +1,9 @@
 <template>
 <div class="main-page-root">
-    <edit-page v-if="showEditor" class="image-editor" :image="image" @closeRequested="onEditorCloseRequested" />
-
-    <div class="paper root-container" :class="{ 'root-container-image-state': image !== null }">
-        <div v-if="image === null" class="upload-area" @click="uploadFile">
+    <edit-page v-if="showEditor" class="image-editor" :src="imageUrl" :imageBuffer="imageBuffer"
+        @closeAndDiscard="onEditorCloseRequested" @closeAndSave="onEditorSave" />
+
+    <div class="paper root-container" :class="{ 'root-container-image-state': imageUrl !== null }">
+        <div v-if="imageUrl === null" class="upload-area" @click="uploadFile">
             <span class="heading1">{{ translations.get("Title") }}</span>
             <span class="material-icons mdi-xl">upload_file</span>
@@ -10,5 +11,5 @@
         </div>
 
-        <div v-if="image !== null" class="image-area">
+        <div v-if="imageUrl !== null" class="image-area">
             <div class="controls">
                 <button class="btn-primary" @click="doOcr" :disabled="ocrInProgress">
@@ -17,5 +18,5 @@
                 </button>
 
-                <button class="btn-primary" @click="showEditor = true">
+                <button class="btn-primary" @click="showEditor = true" :disabled="ocrInProgress">
                     <span class="material-icons">edit</span>
                     <span>Edit Image</span>
@@ -60,5 +61,6 @@
 .root-container-image-state {
     width: calc(100% - 3em);
-    height: calc(100% - 3em);
+    height: calc(100vh - 3em);
+    max-height: calc(100vh - 3em);
 }
 
@@ -128,4 +130,8 @@
     grid-column-start: span 2;
 }
+
+.text-container {
+    overflow: scroll;
+}
 </style>
 
@@ -145,6 +151,7 @@
     data() {
         return {
-            /** @type {File} */
-            image: null,
+            imageType: null,
+            /** @type {ArrayBuffer} */
+            imageBuffer: null,
             imageUrl: null,
             ocrInProgress: false,
@@ -158,4 +165,19 @@
         })
     },
+    watch: {
+        imageBuffer(newValue) {
+            if (this.imageUrl !== null) {
+                URL.revokeObjectURL(this.imageUrl);
+            }
+
+            if (newValue === null) {
+                return;
+            }
+
+            const arrayView = new Uint8Array(newValue);
+            const blob = new Blob([ arrayView ]);
+            this.imageUrl = URL.createObjectURL(blob);
+        }
+    },
     methods: {
         uploadFile() {
@@ -169,16 +191,19 @@
             }
 
-            this.image = files[0];
-            this.imageUrl = URL.createObjectURL(this.image);
-        },
+            this.imageBuffer = await files[0].arrayBuffer();
+            this.imageType = files[0].type;
+        },
+
         async doOcr() {
             try {
                 this.ocrInProgress = true;
 
-                const imageBlob = await this.$refs.imageEditor.getImageBlobAsync();
+                const arrayView = new Uint8Array(this.imageBuffer);
+                const imageBlob = new Blob([ arrayView ], { type: this.imageType });
 
                 const result = await ocrService.run([
                     {
                         image: imageBlob,
+                        fileName: "file.png",
                         options: new OcrOptions(false)
                     }
@@ -196,9 +221,21 @@
             }
         },
+
         onEditorCloseRequested() {
             this.showEditor = false;
         },
+        /**
+         * Called when the editor is saved in order to update the stored image buffer.
+         * @param {Buffer} newBuffer The updated image buffer.
+         * @param {String} newType The updated MIME type of the image buffer.
+         */
+        onEditorSave(newBuffer, newType) {
+            this.imageBuffer = newBuffer.buffer;
+            this.imageType = newType;
+
+            this.onEditorCloseRequested();
+        },
+
         reset() {
-            this.image = null;
             URL.revokeObjectURL(this.imageUrl);
             this.imageUrl = null;
Index: /main/trunk/model-interfaces-dev/atea/ocr/src/js/OcrService.js
===================================================================
--- /main/trunk/model-interfaces-dev/atea/ocr/src/js/OcrService.js	(revision 35745)
+++ /main/trunk/model-interfaces-dev/atea/ocr/src/js/OcrService.js	(revision 35746)
@@ -59,5 +59,5 @@
     /**
      * Makes an OCR request.
-     * @param {{image: File, options: OcrOptions}[]} images The image set to perform OCR on.
+     * @param {{image: Blob, fileName: String, options: OcrOptions}[]} images The image set to perform OCR on.
      * @returns {Promise<{key: String, fileName: String, text: String}[]>} A JSON list of the recognised text.
      */
@@ -74,8 +74,8 @@
             {
                 const element = images[i];
-                const name = i + element.image.name;
+                const name = i + element.fileName;
 
                 options[name] = element.options;
-                formData.append(name, element.image, element.image.name);
+                formData.append(name, element.image, element.fileName);
             }
 
