@@ -21,6 +21,72 @@ var range = function(n) {
21
21
* @class ICO
22
22
*/
23
23
24
+ /**
25
+ * Generate the hexadecimal value from an arrayBuffer.
26
+ * @memberof ICO
27
+ * @param {ArrayBuffer } buffer The ArrayBuffer object contain the TypedArray of a ICO file.
28
+ * @returns {String } The hexadecimal value.
29
+ */
30
+ function buf2hex ( buffer ) { // buffer is an ArrayBuffer
31
+ return Array . prototype . map . call ( new Uint8Array ( buffer ) , x => ( '00' + x . toString ( 16 ) ) . slice ( - 2 ) ) . join ( '' ) ;
32
+ }
33
+
34
+ /**
35
+ * Creates a PNG image object using the createIcon method.
36
+ * @memberof ICO
37
+ * @param {Int } index The image index.
38
+ * @param {ArrayBuffer } buffer The ArrayBuffer object contain the TypedArray of a ICO file.
39
+ * @returns {Object } PNG icon object.
40
+ */
41
+ function createPng ( index , buffer ) {
42
+ var dv = new DataView ( buffer ) ;
43
+
44
+ var icoWidth = dv . getUint8 ( 6 + ( index * 16 ) ) || 256 ;
45
+ var icoHeight = dv . getUint8 ( 7 + ( index * 16 ) ) || 256 ;
46
+ var icoOffset = dv . getUint32 ( 18 + ( index * 16 ) , true ) ;
47
+ var icoBit = dv . getUint8 ( ( icoOffset + 16 ) + 8 , true ) ;
48
+ var endImage = ( buf2hex ( buffer . slice ( icoOffset , buffer . byteLength ) ) ) . indexOf ( "49454e44" ) ;
49
+ var imgBuffer = buffer . slice ( icoOffset , icoOffset + endImage ) ;
50
+
51
+ return createIcon ( icoBit , icoWidth , icoHeight , imgBuffer ) ;
52
+ }
53
+
54
+ /**
55
+ * Validates if the image is PNG.
56
+ * @memberof ICO
57
+ * @param {Int } index The image index.
58
+ * @param {ArrayBuffer } buffer The ArrayBuffer object contain the TypedArray of a ICO file.
59
+ * @returns {Boolean } True if the image is PNG.
60
+ */
61
+
62
+ function checkIfIsPNG ( index , buffer ) {
63
+ var icoDv = new DataView ( buffer ) ;
64
+ var startImage = icoDv . getUint32 ( 18 + ( index * 16 ) , true ) ;
65
+ var bufferSlice = buf2hex ( buffer . slice ( startImage , startImage + 4 ) )
66
+ return ( bufferSlice === "89504e47" ) ;
67
+ }
68
+
69
+
70
+ /**
71
+ * Creates an image object.
72
+ * @memberof ICO
73
+ * @param {Int } bit The image bit depth.
74
+ * @param {Int } width The image width.
75
+ * @param {Int } height The image height.
76
+ * @param {ArrayBuffer } buffer The ArrayBuffer object contain the TypedArray of a ICO file.
77
+ * @returns {Object } An icon object.
78
+ */
79
+ function createIcon ( bit , width , height , buffer ) {
80
+
81
+ return {
82
+ bit : bit ,
83
+ width : width ,
84
+ height : height ,
85
+ buffer : buffer
86
+ }
87
+
88
+ }
89
+
24
90
var factory = function ( config ) {
25
91
var previousICO = global . ICO ;
26
92
var Image = config . Image ;
@@ -38,47 +104,49 @@ var factory = function(config) {
38
104
* * `buffer` **ArrayBuffer** - Image buffer.
39
105
*/
40
106
parse : function ( buffer , mime ) {
107
+
41
108
var icoDv = new DataView ( buffer ) ;
42
109
if ( icoDv . getUint16 ( 0 , true ) !== 0 || icoDv . getUint16 ( 2 , true ) !== 1 ) {
43
110
var deferred = Q . defer ( ) ;
44
111
return deferred . reject ( new Error ( 'buffer is not ico' ) ) ;
45
112
}
46
-
47
- // make single image icon
48
- // let idCount = icoDv.getUint16(4, true);
49
- return Q . all ( range ( icoDv . getUint16 ( 4 , true ) ) . map ( function ( i ) {
50
- var ico = extractOne ( buffer , i ) ;
51
- var image = {
52
- width : ico . width ,
53
- height : ico . height
54
- } ;
55
-
56
- switch ( ico . bit ) { // eslint-disable-line default-case
57
- case 1 :
58
- image . data = imageData . from1bit ( ico ) ;
59
- break ;
60
- case 4 :
61
- image . data = imageData . from4bit ( ico ) ;
62
- break ;
63
- case 8 :
64
- image . data = imageData . from8bit ( ico ) ;
65
- break ;
66
- case 24 :
67
- image . data = imageData . from24bit ( ico ) ;
68
- break ;
69
- case 32 :
70
- image . data = imageData . from32bit ( ico ) ;
71
- break ;
72
- }
73
-
74
- return Image . encode ( image , mime ) . then ( function ( pngBuffer ) {
75
- return {
76
- bit : ico . bit ,
77
- width : ico . width ,
78
- height : ico . height ,
79
- buffer : pngBuffer
80
- } ;
81
- } ) ;
113
+
114
+ return Q . all ( range ( icoDv . getUint16 ( 4 , true ) )
115
+ . map ( function ( i ) {
116
+
117
+ if ( checkIfIsPNG ( i , buffer ) ) {
118
+ var deferred = Q . defer ( ) ;
119
+ deferred . resolve ( createPng ( i , buffer ) ) ;
120
+ return deferred . promise ;
121
+ } else {
122
+ var ico = extractOne ( buffer , i ) ;
123
+ var image = {
124
+ width : ico . width ,
125
+ height : ico . height
126
+ } ;
127
+
128
+ switch ( ico . bit ) { // eslint-disable-line default-case
129
+ case 1 :
130
+ image . data = imageData . from1bit ( ico ) ;
131
+ break ;
132
+ case 4 :
133
+ image . data = imageData . from4bit ( ico ) ;
134
+ break ;
135
+ case 8 :
136
+ image . data = imageData . from8bit ( ico ) ;
137
+ break ;
138
+ case 24 :
139
+ image . data = imageData . from24bit ( ico ) ;
140
+ break ;
141
+ case 32 :
142
+ image . data = imageData . from32bit ( ico ) ;
143
+ break ;
144
+ }
145
+
146
+ return Image . encode ( image , mime ) . then ( function ( pngBuffer ) {
147
+ return createIcon ( ico . bit , ico . width , ico . height , pngBuffer ) ;
148
+ } ) ;
149
+ }
82
150
} ) ) ;
83
151
} ,
84
152
/**
0 commit comments