如何找到JPG文件的帧图像开始(SOFO)段所在位置

sxqvb 2018-01-09 10:03:12
我知道帧图像开始(SOFO)的标记码是0xFFC0,我是从文件开始就开始找,但是找到了很多个,不知到那个才是SOFO所在的位置
...全文
742 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
「已注销」 2018-02-05
  • 打赏
  • 举报
回复
JPG FFD8 开始 中间每个块以 FFXX 开头,紧接着是以大端保存的 2 字节 (unsigned short) 指明该块的大小,块大小包含储存块大小的这个 2 字节在内。 FFD9 结束 不需要关心多余的文件头细节,自己随便分析分析,找到所需的块,很简单。
「已注销」 2018-02-05
  • 打赏
  • 举报
回复
#include <stdio.h>
#include <stdlib.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shellapi.h>
#include <shlwapi.h>

// 0xFFD8: SOI
// 0xFFE0: APP0
// 0xFFE1: APP1
// 0xFFE2: APP2
// 0xFFE3: APP3
// 0xFFE4: APP4
// 0xFFE5: APP5
// 0xFFE6: APP6
// 0xFFE7: APP7
// 0xFFE8: APP8
// 0xFFE9: APP9
// 0xFFDB: DQT
// 0xFFC0: SOF0
// 0xFFC4: DHT
// 0xFFDA: SOS
// 0xFFD9: EOI

int main(int argc, char *argv[])
{
	HANDLE hFile = CreateFile(TEXT("image.jpg"), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile != INVALID_HANDLE_VALUE) {
		LARGE_INTEGER lli = { 0 };
		if (GetFileSizeEx(hFile, &lli)) {
			HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
			if (hMapping != NULL) {
				BYTE *lpFileBuffer = (BYTE *)MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
				if (lpFileBuffer != NULL) {
					BYTE *lpStartBuffer = lpFileBuffer;
					BYTE *lpEndBuffer = lpFileBuffer + (size_t)lli.QuadPart;
					while (lpStartBuffer < lpEndBuffer) {
						BYTE b1 = lpStartBuffer[0];
						BYTE b2 = lpStartBuffer[1];
						BYTE b3 = lpStartBuffer[2];
						BYTE b4 = lpStartBuffer[3];
						WORD wMark = MAKEWORD(b2, b1);
						WORD wSize = MAKEWORD(b4, b3);
						size_t uOffset = lpStartBuffer - lpFileBuffer;
						lpStartBuffer += sizeof(wSize);
						if ((wMark != 0xFFD8) && (wMark != 0xFFD9)) {
							lpStartBuffer += wSize;
						}
						switch (wMark) {
						case 0xFFD8:
							printf("SOI  => from %u\n", uOffset);
							break;
						case 0xFFE0:
							printf("APP0 => from %u, size %u\n", uOffset, wSize);
							break;
						case 0xFFE1:
							printf("APP1 => from %u, size %u\n", uOffset, wSize);
							break;
						case 0xFFE2:
							printf("APP2 => from %u, size %u\n", uOffset, wSize);
							break;
						case 0xFFE3:
							printf("APP3 => from %u, size %u\n", uOffset, wSize);
							break;
						case 0xFFE4:
							printf("APP4 => from %u, size %u\n", uOffset, wSize);
							break;
						case 0xFFE5:
							printf("APP5 => from %u, size %u\n", uOffset, wSize);
							break;
						case 0xFFE6:
							printf("APP6 => from %u, size %u\n", uOffset, wSize);
							break;
						case 0xFFE7:
							printf("APP7 => from %u, size %u\n", uOffset, wSize);
							break;
						case 0xFFE8:
							printf("APP8 => from %u, size %u\n", uOffset, wSize);
							break;
						case 0xFFE9:
							printf("APP9 => from %u, size %u\n", uOffset, wSize);
							break;
						case 0xFFDB:
							printf("DQT  => from %u, size %u\n", uOffset, wSize);
							break;
						case 0xFFC0:
							printf("SOF0 => from %u, size %u\n", uOffset, wSize);
							break;
						case 0xFFC4:
							printf("DHT  => from %u, size %u\n", uOffset, wSize);
							break;
						case 0xFFDA:
							printf("SOS  => from %u, size %u\n", uOffset, wSize);
							break;
						case 0xFFD9:
							printf("EOI  => from %u\n", uOffset);
							break;
						default:
							break;
						}
					}
				}
				UnmapViewOfFile(lpFileBuffer);
			}
			CloseHandle(hMapping);
		}
		CloseHandle(hFile);
	}
	return 0;
}
「已注销」 2018-02-03
  • 打赏
  • 举报
回复
话说,不知道搜索 JPEG 的文件格式吗? https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format
百灵工作室 2018-01-11
  • 打赏
  • 举报
回复
每个jpeg文件,文件和文件都不一样,是有差异的,譬如有的有exif信息,有的没有,还有的附加了其他信息在里面,所以,你要按照tag和规范去偏移,


worldy 2018-01-11
  • 打赏
  • 举报
回复
这博文解释的很详细 http://blog.csdn.net/ryfdizuo/article/details/41250775
赵4老师 2018-01-10
  • 打赏
  • 举报
回复
参考开源软件Image Magick
#ifndef JPEGDECODE_H #define JPEGDECODE_H #include "globalextern.h" typedef unsigned char BYTE; struct ImageComponentData { double value[3]; }; class MBitReader { public: MBitReader(BYTE* data,int currentDataIndex) { Data=data; m_currentBitPosition=8; m_currentDataIndex=currentDataIndex; } BYTE* Data; int m_currentDataIndex; int m_currentBitPosition; public: int ReadNextBit() { --m_currentBitPosition; if (m_currentBitPosition<0) { m_currentBitPosition+=8; ++m_currentDataIndex; } //if (m_currentDataIndex>632) theUI->label1->setText("Error!"); return ((Data[m_currentDataIndex]>>m_currentBitPosition) & 0x01); } void GoPreviousBit() { ++m_currentBitPosition; if (m_currentBitPosition>7) { m_currentBitPosition-=8; --m_currentDataIndex; } } int GetCurrentByte() { return Data[m_currentDataIndex]; } }; class MJpegDecode { private: struct _JFIFAPPOInfo { BYTE APP0[2]; /* 02h Application Use Marker */ BYTE Length[2]; /* 04h Length of APP0 Field */ BYTE Identifier[5]; /* 06h "JFIF" (zero terminated) Id String */ BYTE Version[2]; /* 0Bh JFIF Format Revision */ BYTE Units; /* 0Dh Units used for Resolution */ BYTE Xdensity[2]; /* 0Eh Horizontal Resolution */ BYTE Ydensity[2]; /* 10h Vertical Resolution */ BYTE XThumbnail; /* 12h Thumbnail Horizontal Pixel Count */ BYTE YThumbnail; /* 13h Thumbnail Vertical Pixel Count */ } JFIFAPPOINFO; struct _JFIFDQTInfo { BYTE DQT[2]; // 14h 量化表标记 BYTE Length[2]; // 16h 量化表长度 BYTE Identifier; // 18h 量化表ID BYTE QTData[64]; // 19h 量化表数据 } JFIFDQTINFO[2]; struct _JFIFSOFOInfo { BYTE SOFO[2]; // 9Eh 开始标记 BYTE Length[2]; // A0h 开始长度 BYTE BitCount; // A2h 样本精度bit位数 BYTE Height[2]; // A5h 图像像素宽度 BYTE Width[2]; // A3h 图像像素高度 BYTE ComponentsCount; // A7h 图像组件计数 BYTE YIdentifier; // A8h 亮度Y的ID号 BYTE YHVSamplingCoefficient; // A9h 亮度Y垂直和水平采样系数 BYTE YUsedDQTIdentifier; // AAh 亮度Y使用的量化表ID号 BYTE CbIdentifier; // ABh 色度Cb的ID号 BYTE CbHVSamplingCoefficient; // ACh 色度Cb垂直和水平采样系数 BYTE CbUsedDQTIdentifier; // ADh 色度Cb使用的量化表ID号 BYTE CrIdentifier; // AEh 色度Cr的ID号 BYTE CrHVSamplingCoefficient; // AFh 色度Cr垂直和水平采样系数 BYTE CrUsedDQTIdentifier; // B0h 色度Cr使用的量化表ID号 } JFIFSOFOINFO; struct _JFIFDHTInfo { BYTE DHT[2]; // B1h 哈夫曼表定义标记 BYTE Length[2]; // B3h 哈夫曼表长度 BYTE HTIdentifier; // B5h 哈夫曼表号 BYTE NBitsSymbolsCount[16]; // B6h (符号的二进制位长度为n)的符号个数 BYTE SymbolsTable[256]; // C6h 按递增次序代码长度排列的符号表 } JFIFDHTINFO[4]; struct _JFIFSOSInfo { BYTE SOS[2]; // 261h 扫描开始标记 BYTE Length[2]; // 263h 扫描开始长度 BYTE ComponentsCount; // 265h 扫描行内组件的数量 BYTE YIdentifier; // 266h 亮度Y的ID号 BYTE YHTTableID; // 267h 亮度Y使用的哈夫曼表ID号 BYTE CbIdentifier; // 268h 色度Cb的ID号 BYTE CbHTTableID; // 269h 色度Cb使用的哈夫曼表ID号 BYTE CrIdentifier; // 26Ah 色度Cr的ID号 BYTE CrHTTableID; // 26Bh 色度Cr使用的哈夫曼表ID号 BYTE Reserved[3]; // 26Ch 3个未知保留字节 } JFIFSOSINFO; private: struct HuffmanTable { int CodeOfFirstNLengthSymbol[17]; //长度为N的第一个码字的整数值 int NLengthToSymbolsTableIndex[16]; //查表得到第一个长度为N的符号位于符号表的索引 } HUFFMANTABLE[4]; public: int ReadJFIFInfo(const BYTE* const jfifData,int jfifDataSize); void DecodeData(int mcuStartIndex,BYTE* jfifData,int jfifDataSize,ImageComponentData*& targetBitmapData); void SetHuffmanTable(); void DecodeOneDUDC(MBitReader* myBitReader,double* DU,double& lastDC,int HTID); void DecodeOneDUAC(MBitReader* myBitReader,double* DU,int HTID); void DecodeOneMCU(MBitReader* myBitReader,int mcuXn,int mcuYn,int mcuWidth,int mcuHeight,double *DU,ImageComponentData* targetImage); void InverseQuantization(double* du,BYTE* quantizationTable); void InverseZigzag(double* sourceDU,double* targetDU); void IDCT(double* sourceDU,double* targetDU); void YCbCrToRGB(ImageComponentData* sourceImage,ImageComponentData* targetImage); public: int imageHeight; int imageWidth; int alignedImageWidth; int alignedImageHeight; struct HuffmanTableID { int dc; int ac; } HTID[3]; double DC[3]; int HSamplingCoefficient[3]; int VSamplingCoefficient[3]; int DQTID[3]; }; #endif // JPEGDECODE_H
#ifndef JPEGDECODE_H #define JPEGDECODE_H #include "global.h" #include "globalextern.h" typedef unsigned char BYTE; struct ImageComponentData { double value[3]; }; class MBitReader { public: BYTE* Data; int m_currentData; int m_currentDataIndex; int m_currentBitPosition; MBitReader(BYTE* data,int currentDataIndex) { Data=data; m_currentBitPosition=8; m_currentDataIndex=currentDataIndex; m_currentData=Data[m_currentDataIndex]; } public: int ReadNextBit() { if (m_currentBitPosition-1> m_currentBitPosition) & 0x01; } }; class MJpegDecode { public: struct _JFIFAPPOInfo { BYTE APP0[2]; /* 02h Application Use Marker */ BYTE Length[2]; /* 04h Length of APP0 Field */ BYTE Identifier[5]; /* 06h "JFIF" (zero terminated) Id String */ BYTE Version[2]; /* 0Bh JFIF Format Revision */ BYTE Units; /* 0Dh Units used for Resolution */ BYTE Xdensity[2]; /* 0Eh Horizontal Resolution */ BYTE Ydensity[2]; /* 10h Vertical Resolution */ BYTE XThumbnail; /* 12h Thumbnail Horizontal Pixel Count */ BYTE YThumbnail; /* 13h Thumbnail Vertical Pixel Count */ } JFIFAPPOINFO; struct _JFIFDQTInfo { BYTE DQT[2]; // 14h 量化表标记 BYTE Length[2]; // 16h 量化表长度 BYTE Identifier; // 18h 量化表ID BYTE QTData[64]; // 19h 量化表数据 } JFIFDQTINFO[2]; struct _JFIFSOFOInfo { BYTE SOFO[2]; // 9Eh 开始标记 BYTE Length[2]; // A0h 开始长度 BYTE BitCount; // A2h 样本精度bit位数 BYTE Height[2]; // A5h 图像像素宽度 BYTE Width[2]; // A3h 图像像素高度 BYTE ComponentsCount; // A7h 图像组件计数 BYTE YIdentifier; // A8h 亮度Y的ID号 BYTE YHVSamplingCoefficient; // A9h 亮度Y垂直和水平采样系数 BYTE YUsedDQTIdentifier; // AAh 亮度Y使用的量化表ID号 BYTE CbIdentifier; // ABh 色度Cb的ID号 BYTE CbHVSamplingCoefficient; // ACh 色度Cb垂直和水平采样系数 BYTE CbUsedDQTIdentifier; // ADh 色度Cb使用的量化表ID号 BYTE CrIdentifier; // AEh 色度Cr的ID号 BYTE CrHVSamplingCoefficient; // AFh 色度Cr垂直和水平采样系数 BYTE CrUsedDQTIdentifier; // B0h 色度Cr使用的量化表ID号 } JFIFSOFOINFO; struct _JFIFDRIInfo { BYTE DRI[2]; BYTE Length[2]; BYTE NMCUReset[2]; //每n个MCU块就有一个 RSTn 标记. } JFIFDRIINFO; struct _JFIFDHTInfo { BYTE DHT[2]; // B1h 哈夫曼表定义标记 BYTE Length[2]; // B3h 哈夫曼表长度 BYTE HTIdentifier; // B5h 哈夫曼表号 BYTE NBitsSymbolsCount[16]; // B6h (符号的二进制位长度为n)的符号个数 BYTE SymbolsTable[256]; // C6h 按递增次序代码长度排列的符号表 } JFIFDHTINFO[2][2]; struct _JFIFSOSInfo { BYTE SOS[2]; // 261h 扫描开始标记 BYTE Length[2]; // 263h 扫描开始长度 BYTE ComponentsCount; // 265h 扫描行内组件的数量 BYTE YIdentifier; // 266h 亮度Y的ID号 BYTE YHTTableID; // 267h 亮度Y使用的哈夫曼表ID号 BYTE CbIdentifier; // 268h 色度Cb的ID号 BYTE CbHTTableID; // 269h 色度Cb使用的哈夫曼表ID号 BYTE CrIdentifier; // 26Ah 色度Cr的ID号 BYTE CrHTTableID; // 26Bh 色度Cr使用的哈夫曼表ID号 BYTE Reserved[3]; // 26Ch 3个未知保留字节 } JFIFSOSINFO; private: struct HuffmanTable { int CodeOfFirstNLengthSymbol[17]; //长度为N的第一个码字的整数值 int NLengthToSymbolsTableIndex[16]; //查表得到第一个长度为N的符号位于符号表的索引 } HUFFMANTABLE[2][2]; public: int ReadJFIFInfo(const BYTE* const jfifData,int jfifDataSize); void DecodeData(int mcuStartIndex,BYTE* jfifData,int jfifDataSize,ImageComponentData*& targetBitmapData); void SetHuffmanTable(); void DecodeOneDUDC(MBitReader* myBitReader,double* DU,double& lastDC,int index1,int index2); void DecodeOneDUAC(MBitReader* myBitReader,double* DU,int index1,int index2); void DecodeOneMCU(MBitReader* myBitReader,int mcuXn,int mcuYn,int mcuWidth,int mcuHeight,double *DU,ImageComponentData* targetImage); void InverseQuantization(double* du,BYTE* quantizationTable); void InverseZigzag(double* sourceDU,double* targetDU); void IDCT(double* sourceDU,double* targetDU); void YCbCrToRGB(ImageComponentData* sourceImage,ImageComponentData* targetImage); public: int imageHeight; int imageWidth; int alignedImageWidth; int alignedImageHeight; HuffmanTable* HT; double DC[3]; int HSamplingCoefficient[3]; int VSamplingCoefficient[3]; int DQTID[3]; int nMCUReset; }; #endif // JPEGDECODE_H

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧