@@ -52,17 +52,12 @@ public IccProfile(byte[] data)
5252 /// by making a copy from another ICC profile.
5353 /// </summary>
5454 /// <param name="other">The other ICC profile, where the clone should be made from.</param>
55- /// <exception cref="System. ArgumentNullException"><paramref name="other"/> is null.</exception>>
55+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is null.</exception>>
5656 public IccProfile ( IccProfile other )
5757 {
5858 Guard . NotNull ( other , nameof ( other ) ) ;
5959
60- // TODO: Do we need to copy anything else?
61- if ( other . data != null )
62- {
63- this . data = new byte [ other . data . Length ] ;
64- Buffer . BlockCopy ( other . data , 0 , this . data , 0 , other . data . Length ) ;
65- }
60+ this . data = other . ToByteArray ( ) ;
6661 }
6762
6863 /// <summary>
@@ -108,7 +103,7 @@ public List<IccTagDataEntry> Entries
108103#if ! NETSTANDARD1_1
109104
110105 /// <summary>
111- /// Calculates the MD5 hash value of an ICC profile header
106+ /// Calculates the MD5 hash value of an ICC profile
112107 /// </summary>
113108 /// <param name="data">The data of which to calculate the hash value</param>
114109 /// <returns>The calculated hash</returns>
@@ -117,22 +112,38 @@ public static IccProfileId CalculateHash(byte[] data)
117112 Guard . NotNull ( data , nameof ( data ) ) ;
118113 Guard . IsTrue ( data . Length >= 128 , nameof ( data ) , "Data length must be at least 128 to be a valid profile header" ) ;
119114
120- byte [ ] header = new byte [ 128 ] ;
121- Buffer . BlockCopy ( data , 0 , header , 0 , 128 ) ;
115+ const int profileFlagPos = 44 ;
116+ const int renderingIntentPos = 64 ;
117+ const int profileIdPos = 84 ;
118+
119+ // need to copy some values because they need to be zero for the hashing
120+ byte [ ] temp = new byte [ 24 ] ;
121+ Buffer . BlockCopy ( data , profileFlagPos , temp , 0 , 4 ) ;
122+ Buffer . BlockCopy ( data , renderingIntentPos , temp , 4 , 4 ) ;
123+ Buffer . BlockCopy ( data , profileIdPos , temp , 8 , 16 ) ;
122124
123125 using ( var md5 = MD5 . Create ( ) )
124126 {
125- // Zero out some values
126- Array . Clear ( header , 44 , 4 ) ; // Profile flags
127- Array . Clear ( header , 64 , 4 ) ; // Rendering Intent
128- Array . Clear ( header , 84 , 16 ) ; // Profile ID
129-
130- // Calculate hash
131- byte [ ] hash = md5 . ComputeHash ( data ) ;
132-
133- // Read values from hash
134- var reader = new IccDataReader ( hash ) ;
135- return reader . ReadProfileId ( ) ;
127+ try
128+ {
129+ // Zero out some values
130+ Array . Clear ( data , profileFlagPos , 4 ) ;
131+ Array . Clear ( data , renderingIntentPos , 4 ) ;
132+ Array . Clear ( data , profileIdPos , 16 ) ;
133+
134+ // Calculate hash
135+ byte [ ] hash = md5 . ComputeHash ( data ) ;
136+
137+ // Read values from hash
138+ var reader = new IccDataReader ( hash ) ;
139+ return reader . ReadProfileId ( ) ;
140+ }
141+ finally
142+ {
143+ Buffer . BlockCopy ( temp , 0 , data , profileFlagPos , 4 ) ;
144+ Buffer . BlockCopy ( temp , 4 , data , renderingIntentPos , 4 ) ;
145+ Buffer . BlockCopy ( temp , 8 , data , profileIdPos , 16 ) ;
146+ }
136147 }
137148 }
138149
@@ -149,14 +160,37 @@ public void Extend(byte[] bytes)
149160 Buffer . BlockCopy ( bytes , 0 , this . data , currentLength , bytes . Length ) ;
150161 }
151162
163+ /// <summary>
164+ /// Checks for signs of a corrupt profile.
165+ /// </summary>
166+ /// <remarks>This is not an absolute proof of validity but should weed out most corrupt data.</remarks>
167+ /// <returns>True if the profile is valid; False otherwise</returns>
168+ public bool CheckIsValid ( )
169+ {
170+ return Enum . IsDefined ( typeof ( IccColorSpaceType ) , this . Header . DataColorSpace ) &&
171+ Enum . IsDefined ( typeof ( IccColorSpaceType ) , this . Header . ProfileConnectionSpace ) &&
172+ Enum . IsDefined ( typeof ( IccRenderingIntent ) , this . Header . RenderingIntent ) &&
173+ this . Header . Size >= 128 &&
174+ this . Header . Size < 50_000_000 ; // it's unlikely there is a profile bigger than 50MB
175+ }
176+
152177 /// <summary>
153178 /// Converts this instance to a byte array.
154179 /// </summary>
155180 /// <returns>The <see cref="T:byte[]"/></returns>
156181 public byte [ ] ToByteArray ( )
157182 {
158- var writer = new IccWriter ( ) ;
159- return writer . Write ( this ) ;
183+ if ( this . data != null )
184+ {
185+ byte [ ] copy = new byte [ this . data . Length ] ;
186+ Buffer . BlockCopy ( this . data , 0 , copy , 0 , copy . Length ) ;
187+ return copy ;
188+ }
189+ else
190+ {
191+ var writer = new IccWriter ( ) ;
192+ return writer . Write ( this ) ;
193+ }
160194 }
161195
162196 private void InitializeHeader ( )
0 commit comments