|
35 | 35 | } |
36 | 36 |
|
37 | 37 |
|
38 | | - /* |
39 | | - * Takes the image and uses a canvas element to encode the media |
40 | | - * response | string | this is the raw XHR resposne data |
41 | | - * filename | string | this is the url accessed/filename, it's needed so that we can parse out the type of image for mimetyping |
42 | | - * Code base heavily on Encoding XHR image data by @mathias - http://jsperf.com/encoding-xhr-image-data/33 |
43 | | - */ |
44 | | - var base64EncodeCanvas = function( img ){ |
45 | | - try { |
46 | | - var canvas = document.createElement('canvas'); |
47 | | - canvas.width = img.width; |
48 | | - canvas.height = img.height; |
49 | | - |
50 | | - var ctx = canvas.getContext('2d'); |
51 | | - ctx.drawImage(img, 0, 0); |
52 | | - |
53 | | - var imgType = img.src.match(/\.(jpg|jpeg|png)$/i); |
54 | | - if( imgType && imgType.length ) { |
55 | | - imgType = imgType[1].toLowerCase() == 'jpg' ? 'jpeg' : imgType[1].toLowerCase(); |
56 | | - } else { |
57 | | - throw 'Invalid image type for canvas encoder: ' + img.src; |
58 | | - } |
59 | | - |
60 | | - return canvas.toDataURL('image/' + imgType); |
61 | | - } catch (e) { |
62 | | - console && console.log(e); |
63 | | - return 'error'; |
64 | | - } |
65 | | - }; |
66 | | - |
67 | | - /* |
68 | | - * Takes raw image data, and outputs a base64 encoded image data string for local storage caching |
69 | | - * response | string | this is the raw XHR resposne data |
70 | | - * filename | string | this is the url accessed/filename, it's needed so that we can parse out the type of image for mimetyping |
71 | | - * Code base heavily on Encoding XHR image data by @mathias - http://jsperf.com/encoding-xhr-image-data/33 |
72 | | - */ |
73 | | - var base64EncodeResponse = function( raw ){ |
74 | | - var base64 = '', |
75 | | - encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', |
76 | | - bytes = new Uint8Array(raw), |
77 | | - byteLength = bytes.byteLength, |
78 | | - byteRemainder = byteLength % 3, |
79 | | - mainLength = byteLength - byteRemainder, |
80 | | - a, b, c, d, chunk; |
81 | | - |
82 | | - // Main loop deals with bytes in chunks of 3 |
83 | | - for( var i = 0; i < mainLength; i = i + 3 ){ |
84 | | - // Combine the three bytes into a single integer |
85 | | - chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]; |
86 | | - // Use bitmasks to extract 6-bit segments from the triplet |
87 | | - a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18 |
88 | | - b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12 |
89 | | - c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6 |
90 | | - d = chunk & 63; // 63 = 2^6 - 1 |
91 | | - // Convert the raw binary segments to the appropriate ASCII encoding |
92 | | - base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]; |
93 | | - } |
94 | | - |
95 | | - // Deal with the remaining bytes and padding |
96 | | - if( byteRemainder === 1 ){ |
97 | | - chunk = bytes[mainLength]; |
98 | | - a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2; |
99 | | - // Set the 4 least significant bits to zero |
100 | | - b = (chunk & 3) << 4 // 3 = 2^2 - 1; |
101 | | - base64 += encodings[a] + encodings[b] + '=='; |
102 | | - } |
103 | | - else if( byteRemainder === 2 ) { |
104 | | - chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]; |
105 | | - a = (chunk & 16128) >> 8 // 16128 = (2^6 - 1) << 8; |
106 | | - b = (chunk & 1008) >> 4 // 1008 = (2^6 - 1) << 4; |
107 | | - // Set the 2 least significant bits to zero |
108 | | - c = (chunk & 15) << 2 // 15 = 2^4 - 1; |
109 | | - base64 += encodings[a] + encodings[b] + encodings[c] + '='; |
110 | | - } |
111 | | - |
112 | | - return base64; |
113 | | - }; |
114 | | - |
115 | 38 | /* |
116 | 39 | * Here is the magic, this is the function that processes through the caching of the images |
117 | 40 | */ |
118 | | - |
119 | | - // console.log( $(self) ); |
120 | 41 | return this.each(function (i, img) { |
121 | 42 | var $this = $(img), |
122 | 43 | src = $this.prop('src') || $this.data('cachedImageSrc'); |
|
158 | 79 |
|
159 | 80 | if( self.cacheImagesConfig.encodeOnCanvas && imgType !== 'gif' ){ |
160 | 81 | $this.load(function () { |
161 | | - localStorage[key] = src = base64EncodeCanvas( img ); |
| 82 | + localStorage[key] = src = $.fn.cacheImages.base64EncodeCanvas( img ); |
162 | 83 | if( src.substring(0,5) === 'data:' ){ |
163 | 84 | $this.prop('src', localStorage[key] ); |
164 | 85 | if( $this.is('.cacheImagesRemove') ){ |
|
172 | 93 | xhr.responseType = 'arraybuffer'; // Cannot use the jQuery ajax method until it support this response type |
173 | 94 | xhr.onload = function( e ){ |
174 | 95 | if (this.status == 200 && e.totalSize > 0 ){ |
175 | | - localStorage[key] = 'data:image/' + imgType + ';base64,' + base64EncodeResponse( this.response ); |
| 96 | + localStorage[key] = 'data:image/' + imgType + ';base64,' + $.fn.cacheImages.base64EncodeResponse( this.response ); |
176 | 97 | $this.prop('src', localStorage[key] ); |
177 | 98 | if( $this.is('.cacheImagesRemove') ){ |
178 | 99 | $this.remove(); |
|
208 | 129 | storagePrefix: 'cached', // Used to prefix the URL in at localStorage key |
209 | 130 | url: null // Allows you to directly set the url for an element |
210 | 131 | }; |
| 132 | + /* |
| 133 | + * Takes the image and uses a canvas element to encode the media |
| 134 | + * response | string | this is the raw XHR resposne data |
| 135 | + * filename | string | this is the url accessed/filename, it's needed so that we can parse out the type of image for mimetyping |
| 136 | + * Code base heavily on Encoding XHR image data by @mathias - http://jsperf.com/encoding-xhr-image-data/33 |
| 137 | + */ |
| 138 | + $.fn.cacheImages.base64EncodeCanvas = function( img ){ |
| 139 | + try { |
| 140 | + var canvas = document.createElement('canvas'); |
| 141 | + canvas.width = img.width; |
| 142 | + canvas.height = img.height; |
| 143 | + |
| 144 | + var ctx = canvas.getContext('2d'); |
| 145 | + ctx.drawImage(img, 0, 0); |
| 146 | + |
| 147 | + var imgType = img.src.match(/\.(jpg|jpeg|png)$/i); |
| 148 | + if( imgType && imgType.length ) { |
| 149 | + imgType = imgType[1].toLowerCase() == 'jpg' ? 'jpeg' : imgType[1].toLowerCase(); |
| 150 | + } else { |
| 151 | + throw 'Invalid image type for canvas encoder: ' + img.src; |
| 152 | + } |
| 153 | + |
| 154 | + return canvas.toDataURL('image/' + imgType); |
| 155 | + } catch (e) { |
| 156 | + console && console.log(e); |
| 157 | + return 'error'; |
| 158 | + } |
| 159 | + }; |
| 160 | + /* |
| 161 | + * Takes raw image data, and outputs a base64 encoded image data string for local storage caching |
| 162 | + * response | string | this is the raw XHR resposne data |
| 163 | + * filename | string | this is the url accessed/filename, it's needed so that we can parse out the type of image for mimetyping |
| 164 | + * Code base heavily on Encoding XHR image data by @mathias - http://jsperf.com/encoding-xhr-image-data/33 |
| 165 | + */ |
| 166 | + $.fn.cacheImages.base64EncodeResponse = function( raw ){ |
| 167 | + var base64 = '', |
| 168 | + encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', |
| 169 | + bytes = new Uint8Array(raw), |
| 170 | + byteLength = bytes.byteLength, |
| 171 | + byteRemainder = byteLength % 3, |
| 172 | + mainLength = byteLength - byteRemainder, |
| 173 | + a, b, c, d, chunk; |
| 174 | + |
| 175 | + // Main loop deals with bytes in chunks of 3 |
| 176 | + for( var i = 0; i < mainLength; i = i + 3 ){ |
| 177 | + // Combine the three bytes into a single integer |
| 178 | + chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]; |
| 179 | + // Use bitmasks to extract 6-bit segments from the triplet |
| 180 | + a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18 |
| 181 | + b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12 |
| 182 | + c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6 |
| 183 | + d = chunk & 63; // 63 = 2^6 - 1 |
| 184 | + // Convert the raw binary segments to the appropriate ASCII encoding |
| 185 | + base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]; |
| 186 | + } |
| 187 | + |
| 188 | + // Deal with the remaining bytes and padding |
| 189 | + if( byteRemainder === 1 ){ |
| 190 | + chunk = bytes[mainLength]; |
| 191 | + a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2; |
| 192 | + // Set the 4 least significant bits to zero |
| 193 | + b = (chunk & 3) << 4 // 3 = 2^2 - 1; |
| 194 | + base64 += encodings[a] + encodings[b] + '=='; |
| 195 | + } |
| 196 | + else if( byteRemainder === 2 ) { |
| 197 | + chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]; |
| 198 | + a = (chunk & 16128) >> 8 // 16128 = (2^6 - 1) << 8; |
| 199 | + b = (chunk & 1008) >> 4 // 1008 = (2^6 - 1) << 4; |
| 200 | + // Set the 2 least significant bits to zero |
| 201 | + c = (chunk & 15) << 2 // 15 = 2^4 - 1; |
| 202 | + base64 += encodings[a] + encodings[b] + encodings[c] + '='; |
| 203 | + } |
| 204 | + |
| 205 | + return base64; |
| 206 | + }; |
211 | 207 | /* |
212 | 208 | * Manually cache an image into the local storage |
213 | 209 | */ |
|
0 commit comments