88

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)]); Commented May 24, 2017 at 3:45
  • @Kaiido many thanks, works like a charm. Could you post it as an answer? Commented May 24, 2017 at 3:54

2 Answers 2

158

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]);
Sign up to request clarification or add additional context in comments.

9 Comments

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 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.
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.
Uint8Array is a waste. You do not need it. Just new Blob([buffer]). ArrayBuffer is a byte array.
^ 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(...)
|
60
var buffer = new ArrayBuffer(32);

new Blob([buffer]);

so the Uint8Array should be

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

1 Comment

why do you reference .buffer here and not just the Uint8Array?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.