@@ -1053,18 +1053,11 @@ private void ReadInfoHeader()
10531053 this . stream . Read ( buffer , 0 , BmpInfoHeader . HeaderSizeSize ) ;
10541054
10551055 int headerSize = BinaryPrimitives . ReadInt32LittleEndian ( buffer ) ;
1056- if ( headerSize < BmpInfoHeader . CoreSize )
1056+ if ( headerSize < BmpInfoHeader . CoreSize || headerSize > BmpInfoHeader . MaxHeaderSize )
10571057 {
10581058 BmpThrowHelper . ThrowNotSupportedException ( $ "ImageSharp does not support this BMP file. HeaderSize is '{ headerSize } '.") ;
10591059 }
10601060
1061- int skipAmount = 0 ;
1062- if ( headerSize > BmpInfoHeader . MaxHeaderSize )
1063- {
1064- skipAmount = headerSize - BmpInfoHeader . MaxHeaderSize ;
1065- headerSize = BmpInfoHeader . MaxHeaderSize ;
1066- }
1067-
10681061 // Read the rest of the header.
10691062 this . stream . Read ( buffer , BmpInfoHeader . HeaderSizeSize , headerSize - BmpInfoHeader . HeaderSizeSize ) ;
10701063
@@ -1169,15 +1162,13 @@ private void ReadInfoHeader()
11691162 {
11701163 this . bmpMetadata . BitsPerPixel = ( BmpBitsPerPixel ) bitsPerPixel ;
11711164 }
1172-
1173- // Skip the remaining header because we can't read those parts.
1174- this . stream . Skip ( skipAmount ) ;
11751165 }
11761166
11771167 /// <summary>
11781168 /// Reads the <see cref="BmpFileHeader"/> from the stream.
11791169 /// </summary>
1180- private void ReadFileHeader ( )
1170+ /// <returns>The color map size in bytes, if it could be determined by the file header. Otherwise -1.</returns>
1171+ private int ReadFileHeader ( )
11811172 {
11821173#if NETCOREAPP2_1
11831174 Span < byte > buffer = stackalloc byte [ BmpFileHeader . Size ] ;
@@ -1186,12 +1177,36 @@ private void ReadFileHeader()
11861177#endif
11871178 this . stream . Read ( buffer , 0 , BmpFileHeader . Size ) ;
11881179
1189- this . fileHeader = BmpFileHeader . Parse ( buffer ) ;
1190-
1191- if ( this . fileHeader . Type != BmpConstants . TypeMarkers . Bitmap )
1180+ short fileTypeMarker = BinaryPrimitives . ReadInt16LittleEndian ( buffer ) ;
1181+ switch ( fileTypeMarker )
11921182 {
1193- BmpThrowHelper . ThrowNotSupportedException ( $ "ImageSharp does not support this BMP file. File header bitmap type marker '{ this . fileHeader . Type } '.") ;
1183+ case BmpConstants . TypeMarkers . Bitmap :
1184+ this . fileHeader = BmpFileHeader . Parse ( buffer ) ;
1185+ break ;
1186+ case BmpConstants . TypeMarkers . BitmapArray :
1187+ // The Array file header is followed by the bitmap file header of the first image.
1188+ var arrayHeader = BmpArrayFileHeader . Parse ( buffer ) ;
1189+ this . stream . Read ( buffer , 0 , BmpFileHeader . Size ) ;
1190+ this . fileHeader = BmpFileHeader . Parse ( buffer ) ;
1191+ if ( this . fileHeader . Type != BmpConstants . TypeMarkers . Bitmap )
1192+ {
1193+ BmpThrowHelper . ThrowNotSupportedException ( $ "Unsupported bitmap file inside a BitmapArray file. File header bitmap type marker '{ this . fileHeader . Type } '.") ;
1194+ }
1195+
1196+ if ( arrayHeader . OffsetToNext != 0 )
1197+ {
1198+ int colorMapSizeBytes = arrayHeader . OffsetToNext - arrayHeader . Size ;
1199+ return colorMapSizeBytes ;
1200+ }
1201+
1202+ break ;
1203+
1204+ default :
1205+ BmpThrowHelper . ThrowNotSupportedException ( $ "ImageSharp does not support this BMP file. File header bitmap type marker '{ fileTypeMarker } '.") ;
1206+ break ;
11941207 }
1208+
1209+ return - 1 ;
11951210 }
11961211
11971212 /// <summary>
@@ -1203,7 +1218,7 @@ private int ReadImageHeaders(Stream stream, out bool inverted, out byte[] palett
12031218 {
12041219 this . stream = stream ;
12051220
1206- this . ReadFileHeader ( ) ;
1221+ int colorMapSizeBytes = this . ReadFileHeader ( ) ;
12071222 this . ReadInfoHeader ( ) ;
12081223
12091224 // see http://www.drdobbs.com/architecture-and-design/the-bmp-file-format-part-1/184409517
@@ -1218,7 +1233,6 @@ private int ReadImageHeaders(Stream stream, out bool inverted, out byte[] palett
12181233 this . infoHeader . Height = - this . infoHeader . Height ;
12191234 }
12201235
1221- int colorMapSize = - 1 ;
12221236 int bytesPerColorMapEntry = 4 ;
12231237
12241238 if ( this . infoHeader . ClrUsed == 0 )
@@ -1227,35 +1241,38 @@ private int ReadImageHeaders(Stream stream, out bool inverted, out byte[] palett
12271241 || this . infoHeader . BitsPerPixel == 4
12281242 || this . infoHeader . BitsPerPixel == 8 )
12291243 {
1230- int colorMapSizeBytes = this . fileHeader . Offset - BmpFileHeader . Size - this . infoHeader . HeaderSize ;
1244+ if ( colorMapSizeBytes == - 1 )
1245+ {
1246+ colorMapSizeBytes = this . fileHeader . Offset - BmpFileHeader . Size - this . infoHeader . HeaderSize ;
1247+ }
1248+
12311249 int colorCountForBitDepth = ImageMaths . GetColorCountForBitDepth ( this . infoHeader . BitsPerPixel ) ;
12321250 bytesPerColorMapEntry = colorMapSizeBytes / colorCountForBitDepth ;
12331251
12341252 // Edge case for less-than-full-sized palette: bytesPerColorMapEntry should be at least 3.
12351253 bytesPerColorMapEntry = Math . Max ( bytesPerColorMapEntry , 3 ) ;
1236- colorMapSize = colorMapSizeBytes ;
12371254 }
12381255 }
12391256 else
12401257 {
1241- colorMapSize = this . infoHeader . ClrUsed * bytesPerColorMapEntry ;
1258+ colorMapSizeBytes = this . infoHeader . ClrUsed * bytesPerColorMapEntry ;
12421259 }
12431260
12441261 palette = null ;
12451262
1246- if ( colorMapSize > 0 )
1263+ if ( colorMapSizeBytes > 0 )
12471264 {
12481265 // Usually the color palette is 1024 byte (256 colors * 4), but the documentation does not mention a size limit.
12491266 // Make sure, that we will not read pass the bitmap offset (starting position of image data).
1250- if ( ( this . stream . Position + colorMapSize ) > this . fileHeader . Offset )
1267+ if ( ( this . stream . Position + colorMapSizeBytes ) > this . fileHeader . Offset )
12511268 {
12521269 BmpThrowHelper . ThrowImageFormatException (
1253- $ "Reading the color map would read beyond the bitmap offset. Either the color map size of '{ colorMapSize } ' is invalid or the bitmap offset.") ;
1270+ $ "Reading the color map would read beyond the bitmap offset. Either the color map size of '{ colorMapSizeBytes } ' is invalid or the bitmap offset.") ;
12541271 }
12551272
1256- palette = new byte [ colorMapSize ] ;
1273+ palette = new byte [ colorMapSizeBytes ] ;
12571274
1258- this . stream . Read ( palette , 0 , colorMapSize ) ;
1275+ this . stream . Read ( palette , 0 , colorMapSizeBytes ) ;
12591276 }
12601277
12611278 this . infoHeader . VerifyDimensions ( ) ;
0 commit comments