JPEG文件数据结构以及将位图保存为JPG的代码 转2

三、实例分析
  用系统自带的画图程序画一个32×24的红色方块,另存为JPG文件,这个文件的全部数据如下:

0000: FF D8 FF E0 00 10 4A 46 49 46 00 01 01 01 00 60
0010: 00 60 00 00 FF DB 00 43 00 08 06 06 07 06 05 08
0020: 07 07 07 09 09 08 0A 0C 14 0D 0C 0B 0B 0C 19 12
0030: 13 0F 14 1D 1A 1F 1E 1D 1A 1C 1C 20 24 2E 27 20
0040: 22 2C 23 1C 1C 28 37 29 2C 30 31 34 34 34 1F 27
0050: 39 3D 38 32 3C 2E 33 34 32 FF DB 00 43 01 09 09
0060: 09 0C 0B 0C 18 0D 0D 18 32 21 1C 21 32 32 32 32
0070: 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32
0080: 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32
0090: 32 32 32 32 32 32 32 32 32 32 32 32 32 32 FF C0
00A0: 00 11 08 00 18 00 20 03 01 22 00 02 11 01 03 11
00B0: 01 FF C4 00 1F 00 00 01 05 01 01 01 01 01 01 00
00C0: 00 00 00 00 00 00 00 01 02 03 04 05 06 07 08 09
00D0: 0A 0B FF C4 00 B5 10 00 02 01 03 03 02 04 03 05
00E0: 05 04 04 00 00 01 7D 01 02 03 00 04 11 05 12 21
00F0: 31 41 06 13 51 61 07 22 71 14 32 81 91 A1 08 23
0100: 42 B1 C1 15 52 D1 F0 24 33 62 72 82 09 0A 16 17
0110: 18 19 1A 25 26 27 28 29 2A 34 35 36 37 38 39 3A
0120: 43 44 45 46 47 48 49 4A 53 54 55 56 57 58 59 5A
0130: 63 64 65 66 67 68 69 6A 73 74 75 76 77 78 79 7A
0140: 83 84 85 86 87 88 89 8A 92 93 94 95 96 97 98 99
0150: 9A A2 A3 A4 A5 A6 A7 A8 A9 AA B2 B3 B4 B5 B6 B7
0160: B8 B9 BA C2 C3 C4 C5 C6 C7 C8 C9 CA D2 D3 D4 D5
0170: D6 D7 D8 D9 DA E1 E2 E3 E4 E5 E6 E7 E8 E9 EA F1
0180: F2 F3 F4 F5 F6 F7 F8 F9 FA FF C4 00 1F 01 00 03
0190: 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 01
01A0: 02 03 04 05 06 07 08 09 0A 0B FF C4 00 B5 11 00
01B0: 02 01 02 04 04 03 04 07 05 04 04 00 01 02 77 00
01C0: 01 02 03 11 04 05 21 31 06 12 41 51 07 61 71 13
01D0: 22 32 81 08 14 42 91 A1 B1 C1 09 23 33 52 F0 15
01E0: 62 72 D1 0A 16 24 34 E1 25 F1 17 18 19 1A 26 27
01F0: 28 29 2A 35 36 37 38 39 3A 43 44 45 46 47 48 49
0200: 4A 53 54 55 56 57 58 59 5A 63 64 65 66 67 68 69
0210: 6A 73 74 75 76 77 78 79 7A 82 83 84 85 86 87 88
0220: 89 8A 92 93 94 95 96 97 98 99 9A A2 A3 A4 A5 A6
0230: A7 A8 A9 AA B2 B3 B4 B5 B6 B7 B8 B9 BA C2 C3 C4
0240: C5 C6 C7 C8 C9 CA D2 D3 D4 D5 D6 D7 D8 D9 DA E2
0250: E3 E4 E5 E6 E7 E8 E9 EA F2 F3 F4 F5 F6 F7 F8 F9
0260: FA FF DA 00 0C 03 01 00 02 11 03 11 00 3F 00 E2
0270: E8 A2 8A F9 93 F7 10 A2 8A 28 00 A2 8A 28 00 A2
0280: 8A 28 03 FF D9

分析:
0000-0001:FF D8(文件头)
0002-0013:APP0段,其中:
  0002-0003:FF E0(段标记)
  0004-0005:00 10(段长度=16字节)
  0006-000A:4A 46 49 46 00(“JFIF”的ASCII码)
  000B-000C:01 01(主次版本号=1.01)
  000D     :01(密度单位为 点数/英寸)
  000E-0011:00 60 00 60(水平和垂直的密度均为每英寸96像素)
  0012-0013:00 00(没有缩略图)
0014-0058:DQT段,其中:
  0014-0015:FF DB(段标记)
  0016-0017:00 43(段长度=67字节)
  0018     :00(QT号=0,QT精度=8bit)
  0019-0058:QT
0059-009D:DQT段,其中:
  0059-005A:FF DB(段标记)
  005B-005C:00 43(段长度=67字节)
  005D     :01(QT号=1,QT精度=8bit)
  005E-009D:QT
009E-00B0:SOF0段,其中:
  009E-009F:FF C0(段标记)
  00A0-00A1:00 11(段长度=17字节)
  00A2     :08(样本精度=8bit)
  00A3-00A6:00 18 00 20(图像高=24,图像宽=32)
  00A7     :03(组件数量=3,YCbCr彩色图)
  00A8     :01(ID号=1,这是亮度Y组件)
  00A9     :22(化为二进制=00100010,表明垂直和水平采样系数均=2)
  00AA     :00(使用QT号=0的量化表)
  00AB     :02(ID号=2,这是色度Cb组件)
  00AC     :11(化为二进制=00010001,表明垂直和水平采样系数均=1)
  00AD     :01(使用QT号=1的量化表)
  00AE     :03(ID号=3,这是色度Cr组件)
  00AF     :11(化为二进制=00010001,表明垂直和水平采样系数均=1)
  00B0     :01(使用QT号=1的量化表)
00B1-00D1:DHT段,其中:
  00B1-00B2:FF C4(段标记)
  00B3-00B4:00 1F(段长度=31字节)
  00B5     :00(HT号=0,DC表)
  00B6-00C5:这16个数字之和=12,说明下面的HT值表的长度=12字节)
  00C6-00D1:HT值表
00D2-0188:DHT段,这是HT号=0的AC表,参照上面分析
0189-01A9:DHT段,这是HT号=1的DC表,参照上面分析
01AA-0260:DHT段,这是HT号=1的AC表,参照上面分析
0261-026E:SOS段,其中:
  0261-0262:FF DA(段标记)
  0263-0264:00 0C(段长度=12字节)
  0265     :03(组件数量=3)
  0266-0267:01 00(组件ID=1,Y组件,使用HT表号=0的AC表)
  0268-0269:02 11(组件ID=2,Cb组件,使用HT表号=1的DC表)
  026A-026B:03 11(组件ID=3,Cr组件,使用HT表号=1的DC表)
  026C-026E:00 3F 00(几乎每个JPG文件中这3个字节的值都相同,但用途不明)
026F-0282:图像压缩数据
0283-0284:FF D9(文件尾)

 

作者:一江秋水      发表时间:2010-1-30 10:00:00

 3楼  


四、将位图保存为JPG的函数代码:

Option Explicit

Private Declare Function CLSIDFromString Lib "ole32" (ByVal str As Long, id As GUID) As Long
Private Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" (lpvDest As Any, lpvSource As Any, ByVal cbCopy As Long)
Private Declare Function GdipCreateBitmapFromHBITMAP Lib "gdiplus" (ByVal hbm As Long, ByVal hpal As Long, Bitmap As Long) As Long
Private Declare Function GdiplusStartup Lib "gdiplus.dll" (ByRef token As Long, ByRef inputX As GdiplusStartupInput, ByVal Output As Long) As Long
Private Declare Function GdipSaveImageToFile Lib "gdiplus" (ByVal Image As Long, ByVal Filename As Long, clsidEncoder As GUID, encoderParams As Any) As Long
Private Declare Function GdipDisposeImage Lib "gdiplus" (ByVal Image As Long) As Long
Private Declare Function GdiplusShutdown Lib "gdiplus.dll" (ByVal token As Long) As Long

Private Type GUID
  Data1  As Long
  Data2  As Integer
  Data3  As Integer
  Data4(0 To 7) As Byte
End Type
Private Type GdiplusStartupInput
  GdiplusVersion As Long
  DebugEventCallback As Long
  SuppressBackgroundThread As Long
  SuppressExternalCodecs As Long
End Type
Private Type EncoderParameter
  GUID As GUID
  NumberOfvalues  As Long
  type As Long
  Value As Long
End Type
Private Type EncoderParameters
  Count As Long
  Parameter As EncoderParameter
End Type

'输入参数:必需的:1.对象;2.要保存的全路径文件名;可选的:3.jpg品质因素
Private Function SaveJpg(ByVal pict As StdPicture, ByVal Filename As String, Optional ByVal JPG_Quality As Byte = 80) As Boolean
On Error GoTo 100
Dim lGDIP As Long
Dim lBitmap As Long
Dim aEncParams() As Byte
Dim udtData As GdiplusStartupInput

udtData.GdiplusVersion = 1 'GDI+初始化
If GdiplusStartup(lGDIP, udtData, 0) = 0 Then
  If GdipCreateBitmapFromHBITMAP(pict.Handle, 0, lBitmap) = 0 Then '从句柄创建 GDI+ 图像
    Dim tJpgEncoder As GUID
    Dim tParams As EncoderParameters
    CLSIDFromString StrPtr("{557CF401-1A04-11D3-9A73-0000F81EF32E}"), tJpgEncoder '初始化解码器的GUID标识
    tParams.Count = 1      '设置解码器参数
    With tParams.Parameter '设置品质因数
      CLSIDFromString StrPtr("{1D5BE4B5-FA4A-452D-9CDD-5DB35105E7EB}"), .GUID '获取JPG_Quality参数的GUID标识
      .NumberOfvalues = 1
      .type = 4
      .Value = VarPtr(JPG_Quality)
    End With
    ReDim aEncParams(1 To Len(tParams))
    Call CopyMemory(aEncParams(1), tParams, Len(tParams))
    GdipSaveImageToFile lBitmap, StrPtr(Filename), tJpgEncoder, aEncParams(1) '保存图像
    GdipDisposeImage lBitmap '销毁GDI+图像
    GdiplusShutdown lGDIP
    Erase aEncParams
    SavePic = True
  End If
End If
Exit Function
100
End Function

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要将unsigned char数组里的数据保存jpg文件,可以使用libjpeg库。下面是一个简单的C代码示例: ``` #include <stdio.h> #include <jpeglib.h> void write_jpeg_file(unsigned char *data, int width, int height, char *filename) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; FILE *outfile = fopen(filename, "wb"); if (!outfile) { fprintf(stderr, "Can't open %s\n", filename); return; } cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo, outfile); cinfo.image_width = width; cinfo.image_height = height; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_start_compress(&cinfo, TRUE); JSAMPROW row_pointer[1]; while (cinfo.next_scanline < cinfo.image_height) { row_pointer[0] = & data[cinfo.next_scanline * width * 3]; jpeg_write_scanlines(&cinfo, row_pointer, 1); } jpeg_finish_compress(&cinfo); fclose(outfile); jpeg_destroy_compress(&cinfo); } int main() { // 假设数据保存在data数组中,宽度为width,高度为height unsigned char data[width * height * 3]; // 将数据保存jpg文件 write_jpeg_file(data, width, height, "output.jpg"); return 0; } ``` 在这个示例中,我们定义了一个write_jpeg_file函数,用于将数据保存jpg文件。函数接受四个参数:数据指针data,宽度width,高度height和文件名filename。在函数中,我们首先打开文件并初始化jpeg压缩器。然后,设置像的宽度、高度、像素数据格式等参数。接着,我们逐行将像素数据写入文件中,最后关闭文件和压缩器。在main函数中,我们调用write_jpeg_file函数将数据保存jpg文件

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值