发新帖

[C/VC/C++] C/C++判断某张jpg图片是否完整

零下一度 2022-12-26 735

本文转自: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;
}


最新回复 (0)
返回
零下一度
主题数
931
帖子数
0
注册排名
1