本文轉自:https://blog.csdn.net/10km/article/details/82263274
關於jpg圖片的編碼格式可以在網上找資料,本文主要用一段程序實現如何識別一張jpg圖片是否完整。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <stdint.h> 4 #include <stdbool.h> 5 #include <iostream> 6 7 using namespace std; 8 9 10 static inline uint16_t archswap16(uint16_t D) { 11 return((D << 8) | (D >> 8)); 12 } 13 // gcc 預定義宏判斷大小端 14 #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ 15 #define arch_swap_be16(X) archswap16(X) 16 #else 17 #define arch_swap_be16(X) (X) 18 #endif 19 20 /** 21 * 從文件流中讀取一個大端的16位整數, 22 * 讀取成功返回true,否則返回false 23 */ 24 static bool read_be16(FILE *stream, /*uint16_t *value*/uint8_t *value) 25 { 26 if (sizeof(*value) != fread(value, sizeof(*value), 1, stream)) 27 return false; 28 *value = (arch_swap_be16(*value)); 29 return true; 30 } 31 32 /* 33 * Common JPEG markers(JPEG標記定義) 34 * 參見 https://en.wikipedia.org/wiki/JPEG 35 * */ 36 #define JMK_SOI 0xFFD8 /* Start Of Image */ 37 #define JMK_SOF0 0xFFC0 /* Start Of Frame (baseline DCT) */ 38 #define JMK_SOF2 0xFFC2 /* Start Of Frame (progressive DCT) */ 39 #define JMK_DHT 0xFFC4 /* Define Huffman Table(s) */ 40 #define JMK_DQT 0xFFDB /* Define Quantization Table(s) */ 41 #define JMK_DRI 0xFFDD /* Define Restart Interval */ 42 #define JMK_SOS 0xFFDA /* Start Of Scan */ 43 #define JMK_RST_mask 0xFFD0 /* mask of Restart */ 44 #define JMK_APP_mask 0xFFE0 /* mask of Application-specific */ 45 #define JMK_COM 0xFFFE /* Comment */ 46 #define JMK_EOI 0xFFD9 /* End Of Image */ 47 48 /** 49 * 判斷文件流是否為JPEG格式圖像. 50 * 邏輯說明:循環從文件流中讀取 JPEG 標記,直到遇到SOF0,SOF2標記,就返回true,否則返回false. 51 */ 52 bool check_jpg(FILE* stream) 53 { 54 //uint16_t jpeg_marker; 55 uint8_t jpeg_marker; 56 if (!stream) 57 return false; 58 for (; read_be16(stream, &jpeg_marker) /* 讀取一個JPEG標記 */;) 59 { 60 /* 當前標記的數據長度(不含標記本身) */ 61 //uint16_t payload = 1; /* 設置為0或1用於指定當前JPEG 標記是否有附加數據*/ 62 uint8_t payload = 1; /* 設置為0或1用於指定當前JPEG 標記是否有附加數據*/ 63 switch (jpeg_marker) 64 { 65 case JMK_SOI: 66 payload = 0; /* no payload,沒有附加數據 */ 67 break; 68 case JMK_SOF0: 69 case JMK_SOF2: 70 return true; /* 找到SOF0,SOF2 marker,確認為JPEG 格式*/ 71 case JMK_DHT: 72 case JMK_DQT: 73 case JMK_DRI: 74 case JMK_SOS: 75 case JMK_COM: 76 break; 77 case JMK_EOI: 78 return false; /* not JPEG image*/ 79 default: 80 if ((0XFFF8 & jpeg_marker) == JMK_RST_mask) { 81 payload = 0; /* RST0~7(FFD0~FFD7),no payload */ 82 } 83 else if ((0XFFF0 & jpeg_marker) == JMK_APP_mask) { 84 /* APP0~APP15,do nothing */ 85 } 86 else 87 return false; /* not JPEG image*/ 88 } 89 if (payload) { 90 /*讀取 JPEG 標記之后的附加數據長度字段,根據這個字段的值移動文件游標位置跳到下一個 JPEG 標記 */ 91 if (!read_be16(stream, &payload)) 92 return false; /* not JPEG image*/ 93 fseek(stream, payload - sizeof(payload), SEEK_CUR); 94 } 95 } 96 return false; /* not JPEG image*/ 97 } 98 99 int main(void) 100 { 101 //保存輸入圖像文件名和輸出圖像文件名 102 char InImgName[10]; 103 //圖像數據長度 104 int length; 105 //文件指針 106 FILE* fp; 107 //輸入要讀取的圖像名 108 cout << "Enter Image name:"; 109 cin >> InImgName; 110 //以二進制方式打開圖像 111 if ((fp = fopen(InImgName, "rb")) == NULL) 112 { 113 cout << "Open image failed!" << endl; 114 exit(0); 115 } 116 rewind(fp); 117 if (check_jpg(fp)) { 118 cout << "jpg file" << endl; 119 } 120 else { 121 cout << "no jpg file" << endl; 122 } 123 124 fclose(fp); 125 126 system("pause"); 127 128 return 0; 129 }