PDF JPG

问题

如何从一个pdf文件中提取图片

思路

分析pdf文件,分析Pdf的文件流内容。pdf内的图片都是jpg格式,所以进一步分析jpg格式文件,然后把bytes数组保存到一个文件即可。

具体做法

  1. 找到”stream”
  2. 查看这个stream是否是jpg,在20个字节内寻找十六进制为0xff, 0xd8,是jpg文件的开头。
  3. 如果不是的话继续下一个stream
  4. 如果是找到”endstream”
  5. 在endstream位置前20个字节内寻找十六进制为0xff, 0xd9,是jpg文件的结尾。
  6. 把区间的bytes数组保存到文件
  7. 继续循环寻找下一个stream
  8. 文件全部找完,退出。

代码

Go 实现

// ExtractPdfImages gets JPG images via parse protocol in pdf stream.
func ExtractPdfImages(pdfname string) ([][]byte, error) {
	file, err := os.Open(pdfname)
	defer file.Close()
	content, err := ioutil.ReadAll(file)
	if err != nil { return nil, err	}
	startLoc, resultImageBytes := 0, make([][]byte, 0)
	for {
		streamStart := bytesFind(content, []byte("stream"), startLoc)
		if streamStart == -1 { break}
		jpgStart := bytesFind(content[:streamStart+20], []byte{0xff, 0xd8}, streamStart)
		if jpgStart == -1 {
			startLoc = streamStart + 20
			continue
		}
		streamEnd := bytesFind(content, []byte("endstream"), jpgStart)
		if streamEnd == -1 { return nil, Error{"pdf don't have stream end..."}}
		jpgEnd := bytesFind(content, []byte{0xff, 0xd9}, streamEnd - 20)
		if jpgEnd == -1 { return nil, Error{"pdf don't have jpg end..."}	}
		resultImageBytes = append(resultImageBytes, content[jpgStart+1: jpgEnd+1])
		if err != nil { return nil, err}
		startLoc = jpgEnd
	}
	return resultImageBytes, nil
}