diff --git a/src/core/evaluator.js b/src/core/evaluator.js
index 80099f5dd..bf1679880 100644
--- a/src/core/evaluator.js
+++ b/src/core/evaluator.js
@@ -301,7 +301,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
 
       PDFImage.buildImage(function(imageObj) {
           var imgData = imageObj.getImageData();
-          self.handler.send('obj', [objId, self.pageIndex, 'Image', imgData]);
+          self.handler.send('obj', [objId, self.pageIndex, 'Image', imgData],
+                            null, [imgData.data.buffer]);
         }, self.handler, self.xref, resources, image, inline);
 
       operatorList.addOp(OPS.paintImageXObject, args);
@@ -1457,14 +1458,30 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
     }
   };
 
-
   return PartialEvaluator;
 })();
 
 var OperatorList = (function OperatorListClosure() {
   var CHUNK_SIZE = 100;
 
-  function OperatorList(messageHandler, pageIndex) {
+    function getTransfers(queue) {
+      var transfers = [];
+      var fnArray = queue.fnArray, argsArray = queue.argsArray;
+      for (var i = 0, ii = queue.length; i < ii; i++) {
+        switch (fnArray[i]) {
+          case OPS.paintInlineImageXObject:
+          case OPS.paintInlineImageXObjectGroup:
+          case OPS.paintImageMaskXObject:
+            var arg = argsArray[i][0]; // first param in imgData
+            transfers.push(arg.data.buffer);
+            break;
+        }
+      }
+      return transfers;
+    }
+
+
+    function OperatorList(messageHandler, pageIndex) {
     this.messageHandler = messageHandler;
     // When there isn't a message handler the fn array needs to be able to grow
     // since we can't flush the operators.
@@ -1529,6 +1546,7 @@ var OperatorList = (function OperatorListClosure() {
 
     flush: function(lastChunk) {
       PartialEvaluator.optimizeQueue(this);
+      var transfers = getTransfers(this);
       this.messageHandler.send('RenderPageChunk', {
         operatorList: {
           fnArray: this.fnArray,
@@ -1537,7 +1555,7 @@ var OperatorList = (function OperatorListClosure() {
           length: this.length
         },
         pageIndex: this.pageIndex
-      });
+      }, null, transfers);
       this.dependencies = [];
       this.fnIndex = 0;
       this.argsArray = [];
@@ -1546,6 +1564,7 @@ var OperatorList = (function OperatorListClosure() {
 
   return OperatorList;
 })();
+
 var TextState = (function TextStateClosure() {
   function TextState() {
     this.fontSize = 0;
diff --git a/src/core/worker.js b/src/core/worker.js
index 9d93fc7d7..b72d1c721 100644
--- a/src/core/worker.js
+++ b/src/core/worker.js
@@ -173,6 +173,9 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
         handler.send('test', false);
         return;
       }
+      // making sure postMessage transfers are working
+      var supportTransfers = data[0] === 255;
+      handler.postMessageTransfers = supportTransfers;
       // check if the response property is supported by xhr
       var xhr = new XMLHttpRequest();
       var responseExists = 'response' in xhr;
@@ -186,7 +189,10 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
         handler.send('test', false);
         return;
       }
-      handler.send('test', true);
+      handler.send('test', {
+        supportTypedArray: true,
+        supportTransfers: supportTransfers
+      });
     });
 
     handler.on('GetDocRequest', function wphSetupDoc(data) {
diff --git a/src/display/api.js b/src/display/api.js
index 28e0a8480..4b88ee91d 100644
--- a/src/display/api.js
+++ b/src/display/api.js
@@ -85,6 +85,12 @@ PDFJS.disableAutoFetch = PDFJS.disableAutoFetch === undefined ?
  */
 PDFJS.pdfBug = PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug;
 
+/**
+ * Enables transfer usage in postMessage for ArrayBuffers.
+ * @var {boolean}
+ */
+PDFJS.postMessageTransfers = PDFJS.postMessageTransfers === undefined ?
+                             true : PDFJS.postMessageTransfers;
 /**
  * This is the main entry point for loading a PDF and interacting with it.
  * NOTE: If a URL is used to fetch the PDF data a standard XMLHttpRequest(XHR)
@@ -544,9 +550,13 @@ var WorkerTransport = (function WorkerTransportClosure() {
         var messageHandler = new MessageHandler('main', worker);
         this.messageHandler = messageHandler;
 
-        messageHandler.on('test', function transportTest(supportTypedArray) {
+        messageHandler.on('test', function transportTest(data) {
+          var supportTypedArray = data && data.supportTypedArray;
           if (supportTypedArray) {
             this.worker = worker;
+            if (!data.supportTransfers) {
+              PDFJS.postMessageTransfers = false;
+            }
             this.setupMessageHandler(messageHandler);
             workerInitializedPromise.resolve();
           } else {
@@ -558,10 +568,16 @@ var WorkerTransport = (function WorkerTransportClosure() {
           }
         }.bind(this));
 
-        var testObj = new Uint8Array(1);
-        // Some versions of Opera throw a DATA_CLONE_ERR on
-        // serializing the typed array.
-        messageHandler.send('test', testObj);
+        var testObj = new Uint8Array([PDFJS.postMessageTransfers ? 255 : 0]);
+        // Some versions of Opera throw a DATA_CLONE_ERR on serializing the
+        // typed array. Also, checking if we can use transfers.
+        try {
+          messageHandler.send('test', testObj, null, [testObj.buffer]);
+        } catch (ex) {
+          info('Cannot use postMessage transfers');
+          testObj[0] = 0;
+          messageHandler.send('test', testObj);
+        }
         return;
       } catch (e) {
         info('The worker has been disabled.');
diff --git a/src/shared/util.js b/src/shared/util.js
index 6400c5d7a..f845c0f62 100644
--- a/src/shared/util.js
+++ b/src/shared/util.js
@@ -1104,6 +1104,7 @@ function MessageHandler(name, comObj) {
   this.name = name;
   this.comObj = comObj;
   this.callbackIndex = 1;
+  this.postMessageTransfers = true;
   var callbacks = this.callbacks = {};
   var ah = this.actionHandler = {};
 
@@ -1170,8 +1171,9 @@ MessageHandler.prototype = {
    * @param {String} actionName Action to call.
    * @param {JSON} data JSON data to send.
    * @param {function} [callback] Optional callback that will handle a reply.
+   * @param {Array} [transfers] Optional list of transfers/ArrayBuffers
    */
-  send: function messageHandlerSend(actionName, data, callback) {
+  send: function messageHandlerSend(actionName, data, callback, transfers) {
     var message = {
       action: actionName,
       data: data
@@ -1181,7 +1183,11 @@ MessageHandler.prototype = {
       this.callbacks[callbackId] = callback;
       message.callbackId = callbackId;
     }
-    this.comObj.postMessage(message);
+    if (transfers && this.postMessageTransfers) {
+      this.comObj.postMessage(message, transfers);
+    } else {
+      this.comObj.postMessage(message);
+    }
   }
 };
 
diff --git a/test/features/tests.js b/test/features/tests.js
index 934760b99..3c0b60c32 100644
--- a/test/features/tests.js
+++ b/test/features/tests.js
@@ -540,6 +540,39 @@ var tests = [
     impact: 'Important',
     area: 'Core'
   },
+  {
+    id: 'Worker-transfers',
+    name: 'Worker can use transfers for postMessage',
+    run: function () {
+      if (typeof Worker == 'undefined')
+        return { output: 'Skipped', emulated: '' };
+
+      try {
+        var worker = new Worker('worker-stub.js');
+
+        var promise = new Promise();
+        var timeout = setTimeout(function () {
+          promise.resolve({ output: 'Failed', emulated: '?' });
+        }, 5000);
+
+        worker.addEventListener('message', function (e) {
+          var data = e.data;
+          if (data.action == 'test-transfers' && data.result)
+            promise.resolve({ output: 'Success', emulated: '' });
+          else
+            promise.resolve({ output: 'Failed', emulated: 'Yes' });
+        }, false);
+        var testObj = new Uint8Array([255]);
+        worker.postMessage({action: 'test-transfers',
+          data: testObj}, [testObj.buffer]);
+        return promise;
+      } catch (e) {
+        return { output: 'Failed', emulated: 'Yes' };
+      }
+    },
+    impact: 'Normal',
+    area: 'Core'
+  },
   {
     id: 'Worker-xhr-response',
     name: 'XMLHttpRequest supports the reponse property in web workers',
diff --git a/test/features/worker-stub.js b/test/features/worker-stub.js
index c23f3d52d..6dc01f9fa 100644
--- a/test/features/worker-stub.js
+++ b/test/features/worker-stub.js
@@ -21,6 +21,9 @@ onmessage = function (e) {
   case 'test':
     postMessage({action: 'test', result: data.data instanceof Uint8Array});
     break;
+  case 'test-transfers':
+    postMessage({action: 'test-transfers', result: data.data[0] === 255});
+    break;
   case 'xhr':
     var xhr = new XMLHttpRequest();
     var responseExists = 'response' in xhr;