本文转自:https://blog.csdn.net/10km/article/details/82263274
关于jpg图片的编码格式可以在网上找资料,本文主要用一段程序实现如何识别一张jpg图片是否完整。
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <stdbool.h> #include <iostream> using namespace std; static inline uint16_t archswap16(uint16_t D) { return((D << 8) | (D >> 8)); } // gcc 预定义宏判断大小端 #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ #define arch_swap_be16(X) archswap16(X) #else #define arch_swap_be16(X) (X) #endif /** * 从文件流中读取一个大端的16位整数, * 读取成功返回true,否则返回false */ static bool read_be16(FILE *stream, /*uint16_t *value*/uint8_t *value) { if (sizeof(*value) != fread(value, sizeof(*value), 1, stream)) return false; *value = (arch_swap_be16(*value)); return true; } /* * Common JPEG markers(JPEG标记定义) * 参见 https://en.wikipedia.org/wiki/JPEG * */ #define JMK_SOI 0xFFD8 /* Start Of Image */ #define JMK_SOF0 0xFFC0 /* Start Of Frame (baseline DCT) */ #define JMK_SOF2 0xFFC2 /* Start Of Frame (progressive DCT) */ #define JMK_DHT 0xFFC4 /* Define Huffman Table(s) */ #define JMK_DQT 0xFFDB /* Define Quantization Table(s) */ #define JMK_DRI 0xFFDD /* Define Restart Interval */ #define JMK_SOS 0xFFDA /* Start Of Scan */ #define JMK_RST_mask 0xFFD0 /* mask of Restart */ #define JMK_APP_mask 0xFFE0 /* mask of Application-specific */ #define JMK_COM 0xFFFE /* Comment */ #define JMK_EOI 0xFFD9 /* End Of Image */ /** * 判断文件流是否为JPEG格式图像. * 逻辑说明:循环从文件流中读取 JPEG 标记,直到遇到SOF0,SOF2标记,就返回true,否则返回false. */ bool check_jpg(FILE* stream) { //uint16_t jpeg_marker; uint8_t jpeg_marker; if (!stream) return false; for (; read_be16(stream, &jpeg_marker) /* 读取一个JPEG标记 */;) { /* 当前标记的数据长度(不含标记本身) */ //uint16_t payload = 1; /* 设置为0或1用于指定当前JPEG 标记是否有附加数据*/ uint8_t payload = 1; /* 设置为0或1用于指定当前JPEG 标记是否有附加数据*/ switch (jpeg_marker) { case JMK_SOI: payload = 0; /* no payload,没有附加数据 */ break; case JMK_SOF0: case JMK_SOF2: return true; /* 找到SOF0,SOF2 marker,确认为JPEG 格式*/ case JMK_DHT: case JMK_DQT: case JMK_DRI: case JMK_SOS: case JMK_COM: break; case JMK_EOI: return false; /* not JPEG image*/ default: if ((0XFFF8 & jpeg_marker) == JMK_RST_mask) { payload = 0; /* RST0~7(FFD0~FFD7),no payload */ } else if ((0XFFF0 & jpeg_marker) == JMK_APP_mask) { /* APP0~APP15,do nothing */ } else return false; /* not JPEG image*/ } if (payload) { /*读取 JPEG 标记之后的附加数据长度字段,根据这个字段的值移动文件游标位置跳到下一个 JPEG 标记 */ if (!read_be16(stream, &payload)) return false; /* not JPEG image*/ fseek(stream, payload - sizeof(payload), SEEK_CUR); } } return false; /* not JPEG image*/ } int main(void) { //保存输入图像文件名和输出图像文件名 char InImgName[10]; //图像数据长度 int length; //文件指针 FILE* fp; //输入要读取的图像名 cout << "Enter Image name:"; cin >> InImgName; //以二进制方式打开图像 if ((fp = fopen(InImgName, "rb")) == NULL) { cout << "Open image failed!" << endl; exit(0); } rewind(fp); if (check_jpg(fp)) { cout << "jpg file" << endl; } else { cout << "no jpg file" << endl; } fclose(fp); system("pause"); return 0; }
|
---|