122 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
		
		
			
		
	
	
			122 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
|  | /* | ||
|  |  * format - Haxe File Formats | ||
|  |  * | ||
|  |  *  BMP File Format | ||
|  |  *  Copyright (C) 2007-2009 Robert Sköld | ||
|  |  * | ||
|  |  * Copyright (c) 2009, The Haxe Project Contributors | ||
|  |  * All rights reserved. | ||
|  |  * Redistribution and use in source and binary forms, with or without | ||
|  |  * modification, are permitted provided that the following conditions are met: | ||
|  |  * | ||
|  |  *   - Redistributions of source code must retain the above copyright | ||
|  |  *     notice, this list of conditions and the following disclaimer. | ||
|  |  *   - Redistributions in binary form must reproduce the above copyright | ||
|  |  *     notice, this list of conditions and the following disclaimer in the | ||
|  |  *     documentation and/or other materials provided with the distribution. | ||
|  |  * | ||
|  |  * THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY | ||
|  |  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
|  |  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
|  |  * DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR | ||
|  |  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
|  |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||
|  |  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||
|  |  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
|  |  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
|  |  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH | ||
|  |  * DAMAGE. | ||
|  |  */ | ||
|  | 
 | ||
|  | package iron.format.bmp; | ||
|  | 
 | ||
|  | import iron.format.bmp.Data; | ||
|  | 
 | ||
|  | 
 | ||
|  | class Reader { | ||
|  | 
 | ||
|  | 	var input : haxe.io.Input; | ||
|  | 
 | ||
|  | 	public function new( i ) { | ||
|  | 		input = i; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/**  | ||
|  | 	 * Only supports uncompressed 24bpp bitmaps (the most common format). | ||
|  | 	 *  | ||
|  | 	 * The returned bytes in `Data.pixels` will be in BGR order, and with padding (if present). | ||
|  | 	 *  | ||
|  | 	 * @see https://msdn.microsoft.com/en-us/library/windows/desktop/dd318229(v=vs.85).aspx | ||
|  | 	 * @see https://en.wikipedia.org/wiki/BMP_file_format#Bitmap_file_header | ||
|  | 	 */ | ||
|  | 	public function read() : format.bmp.Data { | ||
|  | 		// Read Header | ||
|  | 		for (b in ["B".code, "M".code]) { | ||
|  | 			if (input.readByte() != b) throw "Invalid header"; | ||
|  | 		} | ||
|  | 	 | ||
|  | 		var fileSize = input.readInt32(); | ||
|  | 		input.readInt32();							// Reserved | ||
|  | 		var offset = input.readInt32(); | ||
|  | 
 | ||
|  | 		// Read InfoHeader | ||
|  | 		var infoHeaderSize = input.readInt32();		// InfoHeader size | ||
|  | 		if (infoHeaderSize != 40) { | ||
|  | 			throw 'Info headers with size $infoHeaderSize not supported.'; | ||
|  | 		} | ||
|  | 		var width = input.readInt32();				// Image width (actual, not padded) | ||
|  | 		var height = input.readInt32();				// Image height | ||
|  | 		var numPlanes = input.readInt16();			// Number of planes | ||
|  | 		var bits = input.readInt16();				// Bits per pixel | ||
|  | 		var compression = input.readInt32();		// Compression type | ||
|  | 		var dataLength = input.readInt32();			// Image data size (includes padding!) | ||
|  | 		input.readInt32();							// Horizontal resolution | ||
|  | 		input.readInt32();							// Vertical resolution | ||
|  | 		var colorsUsed = input.readInt32();			// Colors used (0 when uncompressed) | ||
|  | 		input.readInt32();							// Important colors (0 when uncompressed) | ||
|  | 
 | ||
|  | 		// If there's no compression, the dataLength may be 0 | ||
|  | 		if ( compression == 0 && dataLength == 0 ) dataLength = fileSize - offset; | ||
|  | 
 | ||
|  | 		var bytesRead = 54; // total read above | ||
|  | 		 | ||
|  | 		var colorTable : haxe.io.Bytes = null; | ||
|  | 		if ( bits <= 8 ) { | ||
|  | 			if ( colorsUsed == 0 ) { | ||
|  | 				colorsUsed = Tools.getNumColorsForBitDepth(bits); | ||
|  | 			} | ||
|  | 			var colorTableLength = 4 * colorsUsed; | ||
|  | 			colorTable = haxe.io.Bytes.alloc( colorTableLength ); | ||
|  | 			input.readFullBytes( colorTable, 0, colorTableLength ); | ||
|  | 			bytesRead += colorTableLength; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		input.read( offset - bytesRead ); | ||
|  | 		 | ||
|  | 		var p = haxe.io.Bytes.alloc( dataLength );	 | ||
|  | 		 | ||
|  | 		// Read Raster Data | ||
|  | 		var paddedStride = Tools.computePaddedStride(width, bits); | ||
|  | 		var topToBottom = false; | ||
|  | 		if ( height < 0 ) { // if bitmap is stored top to bottom | ||
|  | 			topToBottom = true; | ||
|  | 			height = -height; | ||
|  | 		} | ||
|  |      | ||
|  | 		input.readFullBytes(p, 0, dataLength); | ||
|  | 			 | ||
|  | 		return { | ||
|  | 			header: { | ||
|  | 				width: width, | ||
|  | 				height: height, | ||
|  | 				paddedStride: paddedStride, | ||
|  | 				topToBottom: topToBottom, | ||
|  | 				bpp: bits, | ||
|  | 				dataLength: dataLength, | ||
|  | 				compression: compression | ||
|  | 			}, | ||
|  | 			pixels: p, | ||
|  | 			colorTable: colorTable | ||
|  | 		} | ||
|  | 	} | ||
|  | } |