最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用golang實現(xiàn)PDF圖片提取

 更新時間:2025年11月23日 11:20:38   作者:九江Mgx  
這篇文章主要為大家詳細介紹了如何使用golang實現(xiàn)PDF圖片提取功能,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下

““PDF 里的圖,難道只能看不能拿?””

—— 別急,今天教你用 Go 寫個"“圖片提取器”",把 PDF 里的圖統(tǒng)統(tǒng)打包帶走!

你有沒有遇到過這種情況:

  • 看到一份超贊的 PDF 報告,里面的圖表清晰又專業(yè),想保存下來做參考?
  • 老師發(fā)的課件里有張神圖,但右鍵不能保存,復制還糊成馬賽克?
  • 想批量提取 PDF 中的所有插圖,卻只能一張張截圖?

別慌!今天我們就用 Go 語言 + pdfcpu 庫,手搓一個超實用的 PDF 圖片提取工具,一鍵把 PDF 里的所有圖片“扒”出來,整齊碼好,命名清晰,絕不手軟!

它是怎么工作的

簡單來說,這個工具干了三件事:

  • 讀 PDF:用 pdfcpu 庫解析 PDF 文件結(jié)構(gòu)。
  • 找圖片:遍歷每一頁,找出所有嵌入的圖像對象(不管是 JPG、PNG 還是其他格式)。
  • 存圖片:把每張圖按 名稱-頁碼-對象ID.格式 的規(guī)則命名,存到你指定的文件夾里。

小知識:PDF 里的圖片其實是“嵌入對象”,每個都有唯一 ID 和所屬頁碼。我們就是靠這些信息精準定位每張圖!

用起來有多爽

假設(shè)你有個文件叫 report.pdf,只需一行命令:

extractimages report.pdf

它就會自動創(chuàng)建一個叫 report.pdf.images 的文件夾,里面是這樣的:

chart-5-42.jpg
diagram-12-108.png
image-3-17.jpg
...

想換個目錄?加個 -o 就行:

extractimages -o my_pics report.pdf

連幫助都貼心準備好了:

extractimages --help

技術(shù)小彩蛋

用 unsafe “偷看”私有字段:pdfcpu.Image 的內(nèi)部字段是私有的,但我們用 unsafe.Pointer 強行轉(zhuǎn)成自定義結(jié)構(gòu)體 MyImage,就能拿到圖片名、頁碼、對象

ID等關(guān)鍵信息?。▌e怕,這在 Go 里是合法“黑科技”)

自動防重名:如果文件名沖突,自動加上時間戳,絕不覆蓋!

智能默認輸出目錄:不指定 -o?沒問題,自動用 PDF文件名.images 當文件夾!

快來試試吧

只要你會裝 Go,三步搞定:

安裝依賴:

go mod init extractimages
go get github.com/pdfcpu/pdfcpu

把下面的代碼保存為 main.go

編譯運行:

go build -o extractimages main.go
./extractimages your_file.pdf

從此,PDF 再也不是圖片的"監(jiān) 獄"——而是你的"圖庫倉庫"!

完整代碼(直接復制就能用?。?/h2>
package main

import (
	"flag"               // 用于處理命令行參數(shù)
	"fmt"               // 用于格式化輸出
	"io"                // 提供基礎(chǔ)的I/O接口
	"log"               // 提供日志功能
	"os"                // 提供操作系統(tǒng)功能接口
	"path/filepath"     // 用于處理文件路徑
	"strings"           // 提供字符串處理函數(shù)
	"time"              // 用于計時和時間戳
	"unsafe"            // 用于不安全的內(nèi)存操作

	"github.com/pdfcpu/pdfcpu/pkg/api"      // pdfcpu庫的API接口
	"github.com/pdfcpu/pdfcpu/pkg/pdfcpu"   // pdfcpu庫的核心功能
)

// MyImage 是對pdfcpu.Image的封裝,用于訪問圖片的詳細信息
type MyImage struct {
	io.Reader  // 嵌入的Reader接口,用于讀取圖片數(shù)據(jù)
	Name     string // 圖片名稱
	FileType string // 文件類型(如jpg、png等)
	PageNr   int    // 圖片所在的PDF頁碼
	ObjNr    int    // 圖片在PDF中的對象編號
}

// 全局變量,用于統(tǒng)計提取的圖片數(shù)量
var extractedImagesCount int

// main 程序入口函數(shù)
func main() {
	// 設(shè)置日志格式
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
	log.Println("PDF圖片提取工具啟動")

	// 解析命令行參數(shù)
	var help bool
	var outputDir string
	flag.BoolVar(&help, "h", false, "顯示幫助信息")
	flag.BoolVar(&help, "help", false, "顯示幫助信息")
	flag.StringVar(&outputDir, "o", "", "指定輸出圖片的目錄")
	flag.StringVar(&outputDir, "output", "", "指定輸出圖片的目錄")
	flag.Parse()

	// 獲取剩余的非選項參數(shù)(即PDF文件路徑)
	args := flag.Args()
	if help || len(args) < 1 {
		showHelp()
		return
	}

	// 獲取PDF文件的絕對路徑
	pdfFilename, err := filepath.Abs(args[0])
	if err != nil {
		log.Fatalf("獲取文件絕對路徑失敗: %v", err)
	}

	// 檢查文件是否存在
	if _, err := os.Stat(pdfFilename); os.IsNotExist(err) {
		log.Fatalf("PDF文件不存在: %s", pdfFilename)
	}

	// 檢查文件擴展名是否為pdf
	if !strings.HasSuffix(strings.ToLower(pdfFilename), ".pdf") {
		log.Printf("警告: 文件擴展名不是.pdf,可能不是有效的PDF文件: %s\n", pdfFilename)
	}

	// 確定輸出目錄
	if outputDir == "" {
		// 如果未指定輸出目錄,使用默認目錄(PDF文件名.images)
		pdfName := strings.TrimSuffix(filepath.Base(pdfFilename), ".pdf")
		outputDir = pdfName + ".images"
	}
	
	// 獲取輸出目錄的絕對路徑
	outputDir, err = filepath.Abs(outputDir)
	if err != nil {
		log.Fatalf("獲取輸出目錄絕對路徑失敗: %v", err)
	}

	// 創(chuàng)建輸出目錄(如果不存在)
	if err := os.MkdirAll(outputDir, 0755); err != nil {
		log.Fatalf("創(chuàng)建輸出目錄失敗: %v", err)
	}

	log.Printf("開始處理PDF文件: %s", pdfFilename)
	log.Printf("圖片將保存到目錄: %s", outputDir)
	startTime := time.Now()

	// 打開 PDF 文件
	pdfFile, err := os.Open(pdfFilename)
	if err != nil {
		log.Fatalf("打開PDF文件失敗: %v", err)
	}
	// 確保程序結(jié)束時關(guān)閉文件
	defer pdfFile.Close()

	// 解析 PDF,將提取的圖片寫入指定目錄
	// 使用saveImageToDir函數(shù)作為回調(diào)函數(shù)處理每個提取到的圖片
	if err := api.ExtractImages(pdfFile, nil, saveImageToDir(outputDir), nil); err != nil {
		log.Fatalf("提取圖片過程中出錯: %v", err)
	}

	elapsedTime := time.Since(startTime)
	log.Printf("圖片提取完成,共提取 %d 張圖片,耗時: %v", extractedImagesCount, elapsedTime)
	log.Printf("所有圖片已保存到目錄: %s", outputDir)
}

// showHelp 顯示幫助信息
func showHelp() {
	fmt.Println("PDF圖片提取工具 - 從PDF文件中提取所有圖片并保存到指定目錄")
	fmt.Println("\n用法:")
	fmt.Println("  extractimages [選項] <PDF文件路徑>")
	fmt.Println("\n選項:")
	fmt.Println("  -h, --help              顯示此幫助信息")
	fmt.Println("  -o, --output <目錄路徑>  指定輸出圖片的目錄(默認: PDF文件名.images)")
	fmt.Println("\n示例:")
	fmt.Println("  extractimages document.pdf")
	fmt.Println("  extractimages -o images_folder document.pdf")
	fmt.Println("\n說明:")
	fmt.Println("  1. 程序會從指定的PDF文件中提取所有圖片")
	fmt.Println("  2. 提取的圖片將保存到指定目錄或默認目錄中")
	fmt.Println("  3. 圖片文件名格式: 圖片名稱-頁碼-對象編號.文件類型")
	fmt.Println("  4. 如果指定的目錄不存在,將自動創(chuàng)建")
}

// saveImageToDir 創(chuàng)建一個回調(diào)函數(shù),用于將提取的圖片保存到指定目錄
// 參數(shù) outputDir 是保存圖片的目標目錄路徑
// 返回值是一個函數(shù),該函數(shù)將在pdfcpu庫提取到圖片時被調(diào)用
func saveImageToDir(outputDir string) func(pdfcpu.Image, bool, int) error {
	return func(img pdfcpu.Image, singleImgPerPage bool, maxPageDigits int) error {
		// 使用unsafe包將pdfcpu.Image類型強制轉(zhuǎn)換為MyImage類型,以便訪問私有字段
		myImg := (*MyImage)(unsafe.Pointer(&img))
		
		// 處理空文件名的情況
		name := myImg.Name
		if name == "" {
			name = "image"
		}
		
		// 處理未知文件類型的情況
		fileType := myImg.FileType
		if fileType == "" {
			fileType = "jpg" // 默認使用jpg格式
		}
		
		// 生成圖片文件名,格式為:圖片名稱-頁碼-對象編號.文件類型
		filename := fmt.Sprintf("%s-%d-%d.%s", name, myImg.PageNr, myImg.ObjNr, fileType)
		
		// 生成完整的文件路徑
		filePath := filepath.Join(outputDir, filename)
		
		// 檢查文件是否已存在,如果存在則添加時間戳
		if _, err := os.Stat(filePath); err == nil {
			timestamp := time.Now().Format("20060102_150405")
			filename = fmt.Sprintf("%s-%d-%d_%s.%s", name, myImg.PageNr, myImg.ObjNr, timestamp, fileType)
			filePath = filepath.Join(outputDir, filename)
			log.Printf("圖片文件已存在,將使用新文件名: %s", filename)
		}
		
		// 創(chuàng)建目標文件
		outFile, err := os.Create(filePath)
		if err != nil {
			log.Printf("創(chuàng)建圖片文件失敗: %v", err)
			return err
		}
		
		// 確保文件關(guān)閉
		defer outFile.Close()
		
		// 將圖片數(shù)據(jù)寫入文件
		n, err := io.Copy(outFile, img.Reader)
		if err != nil {
			log.Printf("寫入圖片數(shù)據(jù)失敗: %v", err)
			return err
		}
		
		// 增加統(tǒng)計計數(shù)
		extractedImagesCount++
		
		// 輸出成功處理的圖片文件名和大小
		log.Printf("成功提取圖片 #%d: %s (大小: %d 字節(jié))", extractedImagesCount, filename, n)
		return nil
	}
}

從此 PDF 里的圖,都是你的!

快去試試吧,說不定下一個被你提取到的,就是價值千金的設(shè)計圖呢~

到此這篇關(guān)于使用golang實現(xiàn)PDF圖片提取的文章就介紹到這了,更多相關(guān)go提取PDF圖片內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • goland服務(wù)熱重啟的配置文件

    goland服務(wù)熱重啟的配置文件

    這篇文章主要介紹了goland服務(wù)熱重啟的配置文件,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • Go高級特性探究之HTTP錯誤處理詳解

    Go高級特性探究之HTTP錯誤處理詳解

    在Web應(yīng)用程序中,HTTP錯誤處理是非常重要的,它關(guān)系到Web應(yīng)用程序的穩(wěn)定性和可靠性,本文介紹如何在Go項目中處理HTTP錯誤,并提供相應(yīng)的解決方案和實踐經(jīng)驗,希望對Go語言Web應(yīng)用程序的開發(fā)者有所幫助
    2023-06-06
  • Golang實現(xiàn)KV存儲引擎實例探究

    Golang實現(xiàn)KV存儲引擎實例探究

    這篇文章主要為大家介紹了Golang實現(xiàn)KV存儲引擎實例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2024-01-01
  • 淺析Go語言中的Range關(guān)鍵字

    淺析Go語言中的Range關(guān)鍵字

    Range是go語言中很獨特的一個關(guān)鍵詞,也相當好用。下面就跟著小編來再聊聊這個Range關(guān)鍵字,有需要的朋友們可以參考借鑒。
    2016-09-09
  • golang結(jié)構(gòu)體與json格式串實例代碼

    golang結(jié)構(gòu)體與json格式串實例代碼

    本文通過實例代碼給大家介紹了golang結(jié)構(gòu)體與json格式串的相關(guān)知識,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-10-10
  • Go語言中普通函數(shù)與方法的區(qū)別分析

    Go語言中普通函數(shù)與方法的區(qū)別分析

    這篇文章主要介紹了Go語言中普通函數(shù)與方法的區(qū)別,以實例形式對比分析了普通函數(shù)與方法使用時的區(qū)別與相關(guān)技巧,需要的朋友可以參考下
    2015-02-02
  • Go中Gzip與json搭配實現(xiàn)數(shù)據(jù)壓縮demo

    Go中Gzip與json搭配實現(xiàn)數(shù)據(jù)壓縮demo

    這篇文章主要為大家介紹了Go中Gzip與json搭配使用壓縮數(shù)據(jù)的實現(xiàn)demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-05-05
  • 淺談JWT在GO中的使用方法及原理

    淺談JWT在GO中的使用方法及原理

    JWT是一種基于?JSON?的開放標準,用于在網(wǎng)絡(luò)應(yīng)用間傳遞聲明,JWT被設(shè)計為可安全地將用戶身份驗證和授權(quán)數(shù)據(jù)作為?JSON?對象在各個應(yīng)用程序之間傳遞,本文將詳細給大家介紹JWT原理及在Go中的用法,需要的朋友可以參考下
    2023-05-05
  • golang 如何用反射reflect操作結(jié)構(gòu)體

    golang 如何用反射reflect操作結(jié)構(gòu)體

    這篇文章主要介紹了golang 用反射reflect操作結(jié)構(gòu)體的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • Go 循環(huán)結(jié)構(gòu)for循環(huán)使用教程全面講解

    Go 循環(huán)結(jié)構(gòu)for循環(huán)使用教程全面講解

    這篇文章主要為大家介紹了Go 循環(huán)結(jié)構(gòu)for循環(huán)使用全面講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10

最新評論

宽甸| 龙口市| 红原县| 余干县| 莫力| 巍山| 本溪| 九江县| 年辖:市辖区| 连江县| 安泽县| 乐业县| 公安县| 黄大仙区| 万全县| 开阳县| 张家港市| 思茅市| 镶黄旗| 安仁县| 金塔县| 黔南| 苍梧县| 开阳县| 景宁| 喜德县| 旬邑县| 股票| 黄石市| 静乐县| 丰县| 大竹县| 翼城县| 板桥市| 甘德县| 城步| 花垣县| 上高县| 商丘市| 伊宁县| 肇庆市|