82

I have a project where I need to display djvu schemas in browser.

I found this old library on Github which, as far as I understood, converts djvu files to bmp and then puts them into canvas element.

As I said, library is old(last commit was 5 years ago), so I need to make some corrections. Main problem is that lib uses obsolete BlobBuilder.

Steps I made to solve this problem:

  1. Decompress this library via Chrome DevTools
  2. Initial error is at line 3774 var c = "undefined" != typeof MozBlobBuilder ? MozBlobBuilder : "undefined" != typeof WebKitBlobBuilder ? WebKitBlobBuilder : console.log("warning: cannot build blobs")
  3. I commented out this line
  4. Next, I commented out line c = new c; and some of following lines too.

So, now it looks this way(variable I is array buffer, and ololo1 and ololo2 are some kind of offset and limit)

var c = new Blob(new Uint8Array(new Uint8Array(I,ololo1,ololo2)))
              , b = b.createObjectURL(c)
              , c = document.getElementById(kb)
              , f = c.getContext("2d")
              , h = new Image
              , g = a[Ea >> 2]
              , i = a[Fa >> 2]
              , j = c.width
              , k = Math.round(i * j / g);

            h.onload = function()
            {
                var a = g / j;
                4 < a && (a = 4);
                1 > a && (a = 1);
                f.globalAlpha = 1;

                for (N = 0; N < a; N++)
                    f.drawImage(h, N, N, g - a + N, i - a + N, 0, 0, j, k),
                    f.globalAlpha *= 1 - 1 / a;
                R(h.complete, "Image /bmp.bmp could not be decoded")
            }
            ;
            h.onerror = function(errorMsg, url, lineNumber, column, errorObj) {
                console.log(errorMsg, url, lineNumber, column, errorObj);
                console.log("Image /bmp.bmp could not be decoded!")
            }           
            ;

And now I stuck at error "Image /bmp.bmp could not be decoded!"(throwed in h.onerror handler).

So, my question is: what I am doing wrong?

2
  • 1
    The original was c.append((new Uint8Array(new Uint8Array(I,ololo1,ololo2))).buffer). I don't see why the author nested his Uint8array inside an new one... You should be fine with just new Blob([new Uint8Array(I,ololo1,ololo2)]);
    – Kaiido
    Commented May 24, 2017 at 3:45
  • @Kaiido many thanks, works like a charm. Could you post it as an answer?
    – Rulisp
    Commented May 24, 2017 at 3:54

2 Answers 2

147

I don't know why the author did wrap his Uint8Array in a new one... note that I don't really know either the deprecated BlobBuilder API, but one typo I can see in your code is that you need to wrap your TypedArray in a normal Array:

new Blob([new Uint8Array(buffer, byteOffset, length)]);

The Blob() constructor takes a blobParts sequence as first parameter, and then searches for BufferSource, USVStrings and Blob elements in this sequence. So when you pass a TypedArray, it will actually iterate over all the entries of this TypedArray and treat these as USVString (and thus convert their numerical value to UTF-8 strings in the Blob). That's rarely what you want, so better always pass an Array in this constructor.

Note that if you don't need to slice the buffer, it's probably better to directly pass it instead of using an intermediary Uint8Array (but still in a normal Array):

new Blob([buffer]);
9
  • 3
    Saved my day as well (I passed in an arrayBuffer to work with binary data, but needed that wrapped as Array). However, I think Uint8Array should be passed in without the brackets as it's already an array, and therefore wasn't the OP's problem. You need the brackets around an ArrayBuffer.
    – aamarks
    Commented Apr 29, 2018 at 16:49
  • 2
    @aamarks No, if you pass an Uint8Array, you will save all its 0~255 values as utf8 strings since the Blob constructor won't access it .buffer property and that it's probably what is wanted to save the contained data as binary.
    – Kaiido
    Commented Apr 29, 2018 at 22:55
  • I see, thanks. It seems passing in the buffer the Uint8Array view is based on, or the Uint8Array, both work as long as either is in brackets.
    – aamarks
    Commented May 1, 2018 at 17:47
  • 20
    Uint8Array is a waste. You do not need it. Just new Blob([buffer]). ArrayBuffer is a byte array.
    – Domske
    Commented Aug 23, 2018 at 10:36
  • ^ it's only a view. Not certain if the starting point was the ArrayBuffer or another typed view? This could derail the blob builder in new Blob(...) Commented Jul 8, 2019 at 14:39
60
var buffer = new ArrayBuffer(32);

new Blob([buffer]);

so the Uint8Array should be

new Blob([new Uint8Array([1, 2, 3, 4]).buffer]);
0

Not the answer you're looking for? Browse other questions tagged or ask your own question.