判斷GIF類型并使用ImageDecoder解析GIF圖

一、判斷是否為GIF圖片類型

在JavaScript中,判斷用戶上傳的文件是否為GIF文件類型時,通常可以通過檢查文件的type屬性或文件的拓展名來判斷,但是由于文件拓展名可以輕易被用戶修改,type屬性是由瀏覽器根據文件拓展名猜測得出的,因此這種判斷方式并不總是準確的。

為了更準確的判斷文件類型,需要讀取文件的頭部字節,并檢查這些字節是否符合GIF文件的規范。

要檢查文件頭部字節以確定文件是否為GIF格式,可以使用JavaScript的FileReader API來讀取文件的前幾個字節,并與GIF文件的魔數(Magic Number)進行比較。GIF文件的魔數是GIF87a或GIF89a,它們位于文件的前幾個字節中。

// 文件輸入元素
const fileInput = document.getElementById('file-input')// 監聽文件變化事件
fileInput.addEventListener('change', async fucntion(e) {// 獲取用戶選擇的文件const file = e.target.files[0]if(file) {const isGif = await checkGifFileType(file)if(isGif) {// 是gif} else {// 不是gif}}
})
/*** 檢查文件類型是否是gif* * @param {*} file * @returns */
export function checkGifFileType(file) {// 創建一個FileReader對象const reader = new FileReader();// 讀取文件的前幾個字節reader.readAsArrayBuffer(file.slice(0, 6)); // GIF的魔數只需要6個字節return new Promise((resolve, reject) => {reader.onload = function (e) {// 將ArrayBuffer轉換為Uint8Array以便讀取字節const arrayBuffer = e.target.result;const uint8Array = new Uint8Array(arrayBuffer);// GIF文件的魔數可以是'GIF87a'或'GIF89a',轉換為ASCII碼分別為[71, 73, 70, 56, 55, 97]或[71, 73, 70, 56, 57, 97]// 檢查文件的前6個字節是否匹配GIF的魔數const gif87a = [71, 73, 70, 56, 55, 97];const gif89a = [71, 73, 70, 56, 57, 97];if ((uint8Array[0] === gif87a[0] &&uint8Array[1] === gif87a[1] &&uint8Array[2] === gif87a[2] &&uint8Array[3] === gif87a[3] &&uint8Array[4] === gif87a[4] &&uint8Array[5] === gif87a[5]) ||(uint8Array[0] === gif89a[0] &&uint8Array[1] === gif89a[1] &&uint8Array[2] === gif89a[2] &&uint8Array[3] === gif89a[3] &&uint8Array[4] === gif89a[4] &&uint8Array[5] === gif89a[5])) {resolve(true); // 是GIF文件} else {resolve(false); // 不是GIF文件}};reader.onerror = function (error) {reject(error);};});
}

二、解析GIF,并在canvas上播放

GIF本質上和視頻一樣,都是一幀一幀的圖片拼合而成,所以,在canvas上播放GIF功能實現的要點,就是獲取具體某一幀的資源。

  1. 使用ImageDecoder API解析GIF每一幀的圖像資源;
  2. 將該圖像資源繪制在canvas畫布上;

注意:目前ImageDecoder僅Chrome瀏覽器支持,如果考慮兼容性,可以使用libgif.js等第三方庫去解析GIF。

1、資源獲取

使用fetch方法獲取GIF圖片資源,注意跨域問題。

fetch("xxx.gif").then((response) => {// response.body 就是圖像資源數據
});

2、使用ImageDecoder解析

imageDecoder對象就包含了一系列的屬性和方法,用來對解析好的圖像數據進行各種各樣的處理。

const imageDecoder = new ImageDecoder({ data: response.body, type: "image/gif" 
});

獲取GIF第一幀的圖形數據,則可以:

imageDecoder.decode({ frameIndex: 0
}).then((result) => {// result 對象就是解析后的結果
});

result 對象包括下面這些屬性,其中result.image?的返回值是一個?VideoFrame?對象,包含很多屬性和方法,例如,幀圖像的編碼尺寸,顯示尺寸,時間戳,時間間隔等,可以作為 ImageSource 繪制在 canvas 畫布上。

{// 解碼的圖像image: VideoFrame,// 如果為true,則表示該圖像包含最終的完整細節輸出。complete: boolean
}

result.image.timestamp:當前幀出現的時間戳,單位為微分秒,即萬分之一秒

result.image.duration:當前幀持續的時長,單位為微分秒,即萬分之一秒

const canvas = document.querySelector("canvas");
const context = canvas.getContext("2d");context.drawImage(result.image, 0, 0);

?

3、簡單封裝

export function giftDecoder(url) {return new Promise((resolve, reject) => {fetch(url).then(async (response) => {// response.body 就是圖像資源數據const imageDecoder = new ImageDecoder({ data: response.body, type: "image/gif" });let _d = await imageDecoder.decode({ frameIndex: 0 })console.log(imageDecoder, _d)const track = imageDecoder.tracks.selectedTrack;console.log(track)let arr = []let totalTime = 0for(let i = 0; i < track.frameCount; i++) {let result = await imageDecoder.decode({ frameIndex: i})if(result) {// result 對象就是解析后的結果// 1000000// timestamp:當前幀出現的時間戳,單位為微分秒// duration:當前幀持續的時長,單位為微分秒arr.push(result)if(i == track.frameCount - 1) {totalTime = result.image.timestamp + result.image.duration}} else {reject()break}}console.error('gif數組', arr)resolve({totalTime,list: arr})});})
}
// gif圖特殊處理
const gifData = await giftDecoder(gifUrl)console.error('gif圖特殊處理', gifData)

參考文檔

https://developer.mozilla.org/en-US/docs/Web/API/VideoFrame

https://developer.mozilla.org/en-US/docs/Web/API/ImageDecoder

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/18898.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/18898.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/18898.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

douyin-vue:使用Vue3、Pinia和Vite5打造高度還原的抖音仿制項目

一&#xff1a;引言 在前端技術日新月異的今天&#xff0c;Vue.js作為一款流行的前端框架&#xff0c;不斷吸引著開發者的目光。最近&#xff0c;GitHub上出現了一個備受矚目的項目——douyin-vue&#xff0c;這是一個基于Vue3、Pinia和Vite5的移動端短視頻項目&#xff0c;旨…

[解決]windows mysql8.0.x誤刪除root,解決辦法

1. 停止mysql服務 2. 以管理員身份打開命令窗口&#xff0c;進入到mysql安裝位置的bin目錄下 3. 輸入 mysqld --console --skip-grant-tables --shared-memory 注意&#xff1a;a. 很多解決辦法是輸入mysqld --skip-grant-tables&#xff0c;這在mysql8.0之后的版本已經不在…

ASPICE標準:汽車軟件與嵌入式系統開發的黃金準則-亞遠景

在高度信息化的現代社會&#xff0c;汽車行業的發展已遠超過傳統的機械和動力系統&#xff0c;汽車電子和軟件系統的重要性日益凸顯。為了確保汽車軟件的質量和可靠性&#xff0c;汽車行業需要一套統一且高效的開發標準。ASPICE&#xff08;Automotive SPICE&#xff09;標準應…

通過ESP32芯片模組實現產品智能化升級,啟明云端樂鑫代理商

隨著科技的不斷進步&#xff0c;物聯網&#xff08;IoT&#xff09;已經滲透到我們生活的方方面面&#xff0c;成為現代生活不可或缺的一部分。在這場智能化革命中&#xff0c;樂鑫科技以其創新的ESP32芯片模組&#xff0c;為智能家居和智能設備的發展注入了新的活力。作為樂鑫…

msi安裝mysql8 啟動失敗,提示只有在任務處于完成狀態(RanToCompletion、Faulted 或 Canceled)時才能釋放它。

解決方案: 1.打開服務,找到安裝的mysql 2. 右擊&#xff0c;打開屬性&#xff0c;進入【登錄】選項卡&#xff0c;選擇本地系統賬戶。 3. 點擊確定-->應用 4.服務中選擇開始服務 5.服務啟動成功后,在安裝步驟中繼續點擊執行

Post Microsoft Build and AI Day 上海開發者日

點擊藍字 關注我們 編輯&#xff1a;Alan Wang 排版&#xff1a;Rani Sun 這個六一怎么過&#xff1f;來微軟 Reactor&#xff0c;一起過兒童節吧&#xff01; 6月1日&#xff0c;Microsoft Azure & Microsoft Reactor 面向大小朋友特別推出六一特輯&#xff0c;「Post Mic…

開源進銷存系統

推薦一款開源的進銷存系統 項目地址&#xff1a;進銷存系統 倉庫管理系統 SAAS進銷存 進銷存ERP: 進銷存系統 倉庫管理系統 SAAS進銷存 進銷存ERPhttps://gitee.com/flyemu/jxc.git 主要功能模塊 銷售 采購 庫存 資料 設置 支持saas多租戶&#xff0c;100%開源可二開 …

前端項目上線要準備哪些問題?

上線前 一般開發過程中&#xff0c;會準備好幾條線路&#xff0c;一個是測試環境&#xff0c;一個是正式環境&#xff1b;如果是公司比較大&#xff0c;在此外還會增加一個環境-預上線。 預上線&#xff0c;就是所有的設備&#xff0c;環境&#xff0c;條件和正式線的環境都是一…

iPhone用戶推薦使用的藏漢翻譯小助手:藏漢翻譯通小程序,支持藏文OCR識別文字提取,衛藏語、安多語、康巴語學習背單詞!

網上沖浪時&#xff0c;遇到不會的漢語詞匯&#xff0c;可以復制到藏漢翻譯通小程序中進行翻譯。如果不會拼音&#xff0c;可以使用圖片識別功能掃一掃文字&#xff0c;即可OCR識別提取文字。 此外&#xff0c;藏漢翻譯通小程序現在還支持背單詞和會話速成課程&#xff0c;支持…

C# BurnServiceContractClient 使用方法

目錄 1. 添加服務引用 2. 使用客戶端進行操作 3. 配置文件&#xff08;App.config&#xff09; 4. 異步調用 總結 要在C#中使用BurnServiceContractClient&#xff0c;首先需要了解該客戶端的使用場景和目標服務契約。假設BurnServiceContractClient是一個WCF&#xff08;W…

混元助手 mysql建表語句轉換oracle

提示語 mysql建表語句轉換成oracle&#xff0c;并且有common SQL語句的生成&#xff1a; create ....

Pytorch-Reduction Ops

文章目錄 前言1.torch.argmax()2.torch.argmin()3.torch.amax()4.torch.amin()5.torch.all()6.torch.any()7.torch.max()8.torch.dist()9.torch.logsumexp()10.torch.mean()11.torch.norm()12.torch.nansum()13.torch.prod()14.torch.cumsum()15.torch.cumprod() 前言 1.torch.…

node環境問題(無法加載文件D:\Software\Node.js\node_global\vue.ps1,因為在此系統上禁止運行腳本。)

問題&#xff1a;npm安裝lerna顯示安裝成功&#xff0c;但是lerna -v的時候報錯 解決步驟&#xff1a; 1、輸入&#xff1a;Get-ExecutionPolicy 2、輸入&#xff1a;Set-ExecutionPolicy -Scope CurrentUser&#xff08;有選項的選Y&#xff09; 3、輸入&#xff1a;RemoteSi…

【記錄】打印|無需排版,生成證件照打印PDF,打印在任意尺寸的紙上(簡單無損!)

以前我打印證件照的時候&#xff0c;我總是在網上找在線證件照轉換或者別的什么。但是我今天突然就琢磨了一下&#xff0c;用 PDF 打印應該也可以直接打印出來&#xff0c;然后就琢磨出來了&#xff0c;這么一條路大家可以參考一下。我覺得比在線轉換成一張 a4 紙要方便的多&am…

Python爬蟲要掌握哪些東西

學習Python爬蟲,你需要掌握以下幾個關鍵方面的知識: 文章目錄 Python基礎:首先,確保你對Python語言有良好的理解,包括基本語法、數據結構(如列表、字典、集合等)、函數、類和對象、模塊和包的使用等。# 有一個數字列表,要創建新的列表,元素是原列表中每個元素的平方 …

深入探索MySQL SELECT查詢:從基礎到高級,解鎖數據寶藏的密鑰

系列文章目錄 更新ing... MySQL操作全攻略&#xff1a;庫、表、數據、事務全面指南深入探索MySQL SELECT查詢&#xff1a;從基礎到高級&#xff0c;解鎖數據寶藏的密鑰MySQL SELECT查詢實戰&#xff1a;練習題精選&#xff0c;提升你的數據庫查詢技能PyMySQL&#xff1a;連接P…

解決 x-content-sha256 no match 錯誤,對 S3CrtAsyncHttpClient 修改

一、CRT修改核心邏輯: 找到 software.amazon.awssdk.services.s3.internal.crt 包下 S3CrtAsyncHttpClient 按照邏輯需要對 GET請求進行適配 signingConfig.setSignedBodyValue(AwsSigningConfig.AwsSignedBodyValue.EMPTY_SHA256); if("GET".equals(asyncRequ…

orin部署tensorrt、cuda、cudnn、pytorch、onnx

絕大部分參考https://blog.csdn.net/qq_41336087/article/details/129661850 非orin可以參考https://blog.csdn.net/JineD/article/details/131201121 報錯顯卡驅動安裝535沒法安裝、原始是和l4t-cuda的部分文件沖突 Options marked [*] produce a lot of output - pipe it t…

數據結構(一)順序表

目錄 一、概念&#xff08;一&#xff09;數據結構的三元素1. 邏輯結構&#xff08;1&#xff09;線性結構&#xff08;2&#xff09;非線性結構 2. 存儲結構&#xff08;1&#xff09;順序存儲&#xff08;2&#xff09;鏈式存儲&#xff08;3&#xff09;索引存儲 3. 運算 &a…

Linux下Git的基本使用

認識Git 先基于Windows下的git操作&#xff0c;熟悉了git的基本概念和使用&#xff0c;直接參考這幾篇文章&#xff1a; Git概述、安裝與本地倉庫的基本操作-CSDN博客 Git本地倉庫與遠程倉庫的交互-CSDN博客 GtiHub遠程倉庫之間的交互-CSDN博客 Git倉庫的分支操作-CSDN博客 倉庫…