Esempio n. 1
0
		double parseEXIFRational(const unsigned char *buf, bool intel) {
			double numerator = 0;
			double denominator = 1;

			numerator = (double)parse32(buf, intel);
			denominator = (double)parse32(buf + 4, intel);
			if (denominator < 1e-20)
				return 0;
			return numerator / denominator;
		}
Esempio n. 2
0
		IFEntry parseIFEntry(const unsigned char *buf,
			const unsigned offs,
			const bool alignIntel,
			const unsigned base,
			const unsigned len) {
			IFEntry result;

			// 每个条目的组成
			// 2 bytes: 标记数字(数据域)
			// 2 bytes: 数据格式
			// 4 bytes: 组件数
			// 4 bytes: 数据值或数据值的偏移量
			result.tag = parse16(buf + offs, alignIntel);
			result.format = parse16(buf + offs + 2, alignIntel);
			result.length = parse32(buf + offs + 4, alignIntel);
			result.data = parse32(buf + offs + 8, alignIntel);

			// 按照指定格式进行解析
			switch (result.format) {
			case 1:
				result.val_byte = (unsigned char)*(buf + offs + 8);
				break;
			case 2:
				result.val_string = parseEXIFString(buf, result.length, result.data, base, len);
				break;
			case 3:
				result.val_16 = parse16((const unsigned char *)buf + offs + 8, alignIntel);
				break;
			case 4:
				result.val_32 = result.data;
				break;
			case 5:
				if (base + result.data + 8 <= len)
					result.val_rational = parseEXIFRational(buf + base + result.data, alignIntel);
				break;
			case 7:
			case 9:
			case 10:
				break;
			default:
				result.tag = 0xFF;
			}
			return result;
		}
Esempio n. 3
0
File: file.cpp Progetto: dcauz/opus
bool readIdent( const char * file )
{
	FILE * fh = fopen( file, "r" );

	unsigned char e_ident[EI_NIDENT];

	if( EI_NIDENT != fread( e_ident, 1, EI_NIDENT, fh ))
	{
		fclose(fh);
		fprintf( stderr, "Failed to read magic number of file %s\n", file );
		return 1;
	}

	if( e_ident[EI_MAG0] != ELFMAG0 || e_ident[EI_MAG1] != ELFMAG1 ||
		e_ident[EI_MAG2] != ELFMAG2 || e_ident[EI_MAG3] != ELFMAG3)
	{
		fprintf( stderr, "Invalid ELF Magic number bytes\n" );
		return 2;
	}

	if( e_ident[EI_VERSION] != EV_CURRENT )
	{
		fprintf( stderr, "Invalid ELF version number %d\n", e_ident[EI_VERSION] );
		return 3;
	}

	bool is64 = false;
	bool is32 = false;

	switch(e_ident[EI_CLASS])
	{
	case ELFCLASSNONE:	printf( "class=NONE\n" ); break;
	case ELFCLASS32:	printf( "class=32\n" );   is32=true; break;
	case ELFCLASS64:	printf( "class=64\n" );   is64=true; break;

	default:			printf( "class=%d\n", e_ident[EI_CLASS] );
	}

	bool isBig = false;
	bool isLittle = false;

	switch( e_ident[EI_DATA])
	{
	case ELFDATANONE:	printf( "data=NONE\n" );	break;
	case ELFDATA2LSB:	printf( "data=2's complement, little endian\n" ); isLittle = true; break;
	case ELFDATA2MSB:	printf( "data=2's complement, big endian \n" );   isBig = true; break;
	default:			printf( "class=%d\n", e_ident[EI_DATA] );
	}

	switch(e_ident[EI_OSABI])
	{
	case ELFOSABI_SYSV:			printf( "ABI=SYSV\n" ); 		break;
	case ELFOSABI_HPUX:			printf( "ABI=HPUX\n" ); 		break;
	case ELFOSABI_NETBSD:		printf( "ABI=NETBSD\n" ); 		break;
	case ELFOSABI_GNU:			printf( "ABI=GNU\n" ); 			break;
	case ELFOSABI_SOLARIS:		printf( "ABI=SOLARIS\n" ); 		break;
	case ELFOSABI_AIX:			printf( "ABI=AIX\n" ); 			break;
	case ELFOSABI_IRIX:			printf( "ABI=IRIX\n" ); 		break;
	case ELFOSABI_FREEBSD:		printf( "ABI=FREEBSD\n" );		break;
	case ELFOSABI_TRU64:		printf( "ABI=TRU64\n" ); 		break;
	case ELFOSABI_MODESTO:		printf( "ABI=MODESTO\n" ); 		break;
	case ELFOSABI_OPENBSD:		printf( "ABI=OPENBSD\n" ); 		break;
	case ELFOSABI_ARM_AEABI:	printf( "ABI=ARM_AEABI\n" ); 	break;
	case ELFOSABI_ARM:			printf( "ABI=ARM\n" ); 			break;
	case ELFOSABI_STANDALONE:	printf( "ABI=STANDALONE\n" ); 	break;
	default:					printf( "ABI=%d\n", e_ident[EI_OSABI] );
	}

	if(!is32 && !is64 )
	{
		fprintf( stderr, "ELF architecture must be either 32 or 64\n" );
		return 4;
	}

	if(!isBig && !isLittle )
	{
		fprintf( stderr, "ELF architecture must be either big or little endian\n" );
		return 5;
	}

	bool rc;
	if(is64)
		rc = parse64(fh);
	else
		rc = parse32(fh);

	fclose(fh);

	return rc;
}
Esempio n. 4
0
int ParseEXIF(unsigned char *buf, unsigned len, EXIFInfo &result) {
    bool alignIntel = true;     // byte alignment 
    unsigned offs   = 0;        // current offset into buffer
    if(len == 0)
        return PARSE_EXIF_ERROR_NO_EXIF;
    
    // Prepare return structure
    memset(&result, 0, sizeof(result));
    
    // Scan for EXIF header and do a sanity check
    for(offs = 0; offs < len-1; offs++) 
        if(buf[offs] == 0xFF && buf[offs+1] == 0xE1) 
            break;
    if(offs == len-1)
        return PARSE_EXIF_ERROR_NO_EXIF;
    offs += 4;
    if(buf[offs] != 0x45 || buf[offs+1] != 0x78 || buf[offs+2] != 0x69) 
        return PARSE_EXIF_ERROR_NO_EXIF;
    
    // Get byte alignment (Motorola or Intel)
    offs += 6;
    if(buf[offs] == 0x49 && buf[offs+1] == 0x49) 
        alignIntel = true;
    else {
        if(buf[offs] == 0x4d && buf[offs+1] == 0x4d)
            alignIntel = false;
        else 
            return PARSE_EXIF_ERROR_UNKNOWN_BYTEALIGN;
    }
    result.byteAlign = alignIntel;
    
    // Get offset into first IFD
    offs += 4;
    unsigned x = parse32(buf+offs, alignIntel);
    if(offs + x >= len) {
        return PARSE_EXIF_ERROR_CORRUPT;
    } 
    
    // Jump to the first IFD, scan tags there.
    offs += x-4;
    int nentries = parse16(buf+offs, alignIntel);
    offs += 2;
    unsigned ifdOffset = offs-10;
    unsigned exifSubIFD = 0;
    unsigned gpsIFD = 0;
    for(int j = 0; j < nentries; j++)  {
        unsigned short tag = parse16(buf+offs, alignIntel);
        unsigned ncomp = parse32(buf+offs+4, alignIntel);
        unsigned coffs = parse32(buf+offs+8, alignIntel);
        
        switch(tag) {
            case 0x8769:
                // EXIF subIFD offset
                exifSubIFD = ifdOffset + coffs;
                break;
                
            case 0x10F:
            case 0x110:
            case 0x10E:
                break;
                
            case 0x132:
                // EXIF/TIFF date/time of image
                copyEXIFString(&result.dateTimeModified, ncomp, ifdOffset, coffs, buf);
                break;
                
            case 0x8825:
                gpsIFD = ifdOffset + coffs;
                break;
        }
        offs += 12;
    }
    if(!exifSubIFD)
        return 0;
    
    // At the EXIF SubIFD, read the rest of the EXIF tags
    offs = exifSubIFD;
    nentries = parse16(buf+offs, alignIntel);
    offs += 2;
    for(int j = 0; j < nentries; j++)  {
        unsigned short tag = parse16(buf+offs, alignIntel);
        unsigned ncomp = parse32(buf+offs+4, alignIntel);
        unsigned coffs = parse32(buf+offs+8, alignIntel);
        
        switch(tag) {
            case 0x9003:
                // original image date/time string
                copyEXIFString(&result.dateTimeOriginal, ncomp, ifdOffset, coffs, buf);
                break;
                
            case 0x920a:
            case 0x829D:        
            case 0x829A:
               break;
        }
        offs += 12;
    }
    
    return 0;
}
Esempio n. 5
0
		//对EXIF段进行解析 'buf'必须开始于EXIF TIFF,为字节"Exif\0\0" ;'len'为buffer的长度
		int EXIFInfo::parseFromEXIFSegment(const unsigned char *buf, unsigned len) {
			bool alignIntel = true;     // 字节对齐方式 (定义在 EXIF 头信息中)
			unsigned offs = 0;        // 缓冲区中当前偏移量
			if (!buf || len < 6)
				return PARSE_EXIF_ERROR_NO_EXIF;

			if (!std::equal(buf, buf + 6, "Exif\0\0"))
				return PARSE_EXIF_ERROR_NO_EXIF;
			offs += 6;

			// 现在解析 TIFF 头. 前两个字节为"II"或者"MM"表示Intel或者 Motorola字节对齐方式
			// 安全性检查,接下来的两个字节必须是0x2a. 最后4个字节是第一个IFD的偏移量 
			// 将会被添加到全局偏移计数器中
			// 这块的最小大小8个字节:
			//  2 bytes: 'II' or 'MM'
			//  2 bytes: 0x002a
			//  4 bytes: 第一个IDF的偏移量
			// -----------------------------
			//  8 bytes
			if (offs + 8 > len)
				return PARSE_EXIF_ERROR_CORRUPT;
			unsigned tiff_header_start = offs;
			if (buf[offs] == 'I' && buf[offs + 1] == 'I')
				alignIntel = true;
			else {
				if (buf[offs] == 'M' && buf[offs + 1] == 'M')
					alignIntel = false;
				else
					return PARSE_EXIF_ERROR_UNKNOWN_BYTEALIGN;
			}
			this->m_byte_align = alignIntel;
			offs += 2;
			if (0x2a != parse16(buf + offs, alignIntel))
				return PARSE_EXIF_ERROR_CORRUPT;
			offs += 2;
			unsigned first_ifd_offset = parse32(buf + offs, alignIntel);
			offs += first_ifd_offset - 4;
			if (offs >= len)
				return PARSE_EXIF_ERROR_CORRUPT;

			// 先解析第一个图像文件目录 (IFD0,主图像).
			// 一个IFD包含多个12字节的目录条目
			// IFD段的前2个字节包含目录条数
			// 最后4个字节包含一个偏移量对下一个IFD
			// 这表明IFD段必须包含6 + 12 * num个字节数
			if (offs + 2 > len)
				return PARSE_EXIF_ERROR_CORRUPT;
			int num_entries = parse16(buf + offs, alignIntel);
			if (offs + 6 + 12 * num_entries > len)
				return PARSE_EXIF_ERROR_CORRUPT;
			offs += 2;
			unsigned exif_sub_ifd_offset = len;
			unsigned gps_sub_ifd_offset = len;
			while (--num_entries >= 0) {
				IFEntry result = parseIFEntry(buf, offs, alignIntel, tiff_header_start, len);
				offs += 12;
				switch (result.tag) {
				case 0x102:
					// 取样数
					if (result.format == 3)
						this->m_bits_per_sample = result.val_16;
					break;

				case 0x10E:
					// 图像描述
					if (result.format == 2)
						this->m_image_description = result.val_string;
					break;

				case 0x10F:
					// 相机制造商
					if (result.format == 2)
						this->m_make = result.val_string;
					break;

				case 0x110:
					// 相机型号
					if (result.format == 2)
						this->m_model = result.val_string;
					break;

				case 0x112:
					// 图片方向
					if (result.format == 3)
						this->m_orientation = result.val_16;
					break;

				case 0x131:
					// 使用软件
					if (result.format == 2)
						this->m_software = result.val_string;
					break;

				case 0x132:
					// EXIF/TIFF 文件修改的日期与时间
					if (result.format == 2)
						this->m_datetime = result.val_string;
					break;

				case 0x8298:
					// 文件的版权信息
					if (result.format == 2)
						this->m_copyright = result.val_string;
					break;

				case 0x8825:
					// GPS IFS 偏移量
					gps_sub_ifd_offset = tiff_header_start + result.data;
					break;

				case 0x8769:
					// EXIF SubIFD 偏移量
					exif_sub_ifd_offset = tiff_header_start + result.data;
					break;
				}
			}

			// 如果存在,则跳转到EXIF SubIFD,解析其所有信息。
			// 这边要注意的是EXIF SubIFD可能不存在
			// EXIF SubIFD包含了很多有用的信息
			if (exif_sub_ifd_offset + 4 <= len) {
				offs = exif_sub_ifd_offset;
				int num_entries = parse16(buf + offs, alignIntel);
				if (offs + 6 + 12 * num_entries > len)
					return PARSE_EXIF_ERROR_CORRUPT;
				offs += 2;
				while (--num_entries >= 0) {
					IFEntry result = parseIFEntry(buf, offs, alignIntel, tiff_header_start, len);
					switch (result.tag) {
					case 0x829a:
						// 曝光时间,单位秒
						if (result.format == 5)
							this->m_exposure_time = result.val_rational;
						break;

					case 0x829d:
						// 相机光圈数
						if (result.format == 5)
							this->m_f_number = result.val_rational;
						break;

					case 0x8827:
						// ISO 感光度
						if (result.format == 3)
							this->m_iso_speed_ratings = result.val_16;
						break;

					case 0x9003:
						//原始文件的日期和时间
						if (result.format == 2)
							this->m_datetime_original = result.val_string;
						break;

					case 0x9004:
						// 数字化的日期和时间
						if (result.format == 2)
							this->m_datetime_digitized = result.val_string;
						break;

					case 0x9201:
						// 快门速度(曝光时间的倒数)
						if (result.format == 5)
							this->m_shutter_speed_value = result.val_rational;
						break;

					case 0x9204:
						// 曝光补偿值
						if (result.format == 5)
							this->m_exposure_bias_value = result.val_rational;
						break;

					case 0x9206:
						// 对焦点的距离
						if (result.format == 5)
							this->m_subject_distance = result.val_rational;
						break;

					case 0x9209:
						// 是否使用闪光
						if (result.format == 3)
							this->m_flash = result.data ? 1 : 0;
						break;

					case 0x920a:
						// 焦距
						if (result.format == 5)
							this->m_focal_length = result.val_rational;
						break;

					case 0x9207:
						// 测光模式
						if (result.format == 3)
							this->m_metering_mode = result.val_16;
						break;

					case 0x9291:
						// 图像被拍摄的低于秒级的时间
						if (result.format == 2)
							this->m_sub_sec_time_original = result.val_string;
						break;

					case 0xa002:
						// EXIF 图像宽度
						if (result.format == 4)
							this->m_image_width = result.val_32;
						else
							if (result.format == 3)
								this->m_image_width = result.val_16;
							else
								this->m_image_width = result.data;
						break;

					case 0xa003:
						// EXIF 图像高度
						if (result.format == 4)
							this->m_image_height = result.val_32;
						else
							if (result.format == 3)
								this->m_image_height = result.val_16;
							else
								this->m_image_height = result.data;
						break;

					case 0xa405:
						// 35mm等效焦距
						if (result.format == 3)
							this->m_focal_length_in_35mm = result.val_16;
						break;
					}
					offs += 12;
				}
			}

			// 如果GPS存在则跳转到 GPS SubIFD 进行解析
			if (gps_sub_ifd_offset + 4 <= len) {
				offs = gps_sub_ifd_offset;
				int num_entries = parse16(buf + offs, alignIntel);
				if (offs + 6 + 12 * num_entries > len)
					return PARSE_EXIF_ERROR_CORRUPT;
				offs += 2;
				while (--num_entries >= 0) {
					unsigned short tag = parse16(buf + offs, alignIntel);
					unsigned short format = parse16(buf + offs + 2, alignIntel);
					unsigned length = parse32(buf + offs + 4, alignIntel);
					unsigned data = parse32(buf + offs + 8, alignIntel);
					switch (tag) {
					case 1:
						// GPS 南 或者 北
						this->GeoLocation.LatComponents.direction = *(buf + offs + 8);
						if ('S' == this->GeoLocation.LatComponents.direction)
							this->GeoLocation.latitude = -this->GeoLocation.latitude;
						break;

					case 2:
						// GPS 纬度信息
						if (format == 5 && length == 3) {
							this->GeoLocation.LatComponents.degrees =
								parseEXIFRational(buf + data + tiff_header_start, alignIntel);
							this->GeoLocation.LatComponents.minutes =
								parseEXIFRational(buf + data + tiff_header_start + 8, alignIntel);
							this->GeoLocation.LatComponents.seconds =
								parseEXIFRational(buf + data + tiff_header_start + 16, alignIntel);
							this->GeoLocation.latitude =
								this->GeoLocation.LatComponents.degrees +
								this->GeoLocation.LatComponents.minutes / 60 +
								this->GeoLocation.LatComponents.seconds / 3600;
							if ('S' == this->GeoLocation.LatComponents.direction)
								this->GeoLocation.latitude = -this->GeoLocation.latitude;
						}
						break;

					case 3:
						// GPS 东或西
						this->GeoLocation.LonComponents.direction = *(buf + offs + 8);
						if ('W' == this->GeoLocation.LonComponents.direction)
							this->GeoLocation.longitude = -this->GeoLocation.longitude;
						break;

					case 4:
						// GPS 经度信息
						if (format == 5 && length == 3) {
							this->GeoLocation.LonComponents.degrees =
								parseEXIFRational(buf + data + tiff_header_start, alignIntel);
							this->GeoLocation.LonComponents.minutes =
								parseEXIFRational(buf + data + tiff_header_start + 8, alignIntel);
							this->GeoLocation.LonComponents.seconds =
								parseEXIFRational(buf + data + tiff_header_start + 16, alignIntel);
							this->GeoLocation.longitude =
								this->GeoLocation.LonComponents.degrees +
								this->GeoLocation.LonComponents.minutes / 60 +
								this->GeoLocation.LonComponents.seconds / 3600;
							if ('W' == this->GeoLocation.LonComponents.direction)
								this->GeoLocation.longitude = -this->GeoLocation.longitude;
						}
						break;

					case 5:
						// 相对于海平面的高度
						this->GeoLocation.altitude_ref = *(buf + offs + 8);
						if (1 == this->GeoLocation.altitude_ref)
							this->GeoLocation.altitude = -this->GeoLocation.altitude;
						break;

					case 6:
						// 与海平面的相对位置
						if (format == 5) {
							this->GeoLocation.altitude =
								parseEXIFRational(buf + data + tiff_header_start, alignIntel);
							if (1 == this->GeoLocation.altitude_ref)
								this->GeoLocation.altitude = -this->GeoLocation.altitude;
						}
						break;
					}
					offs += 12;
				}
			}

			return PARSE_EXIF_SUCCESS;
		}