圖像處理、顯示中的行寬(linesize)、步長(stride)、間距(pitch)

在圖像數據傳輸和顯示的過程中有一個不常用的參數:間距。

間距的名稱:
它有很多的別名,在使用d3d顯示的時候,它叫pitch;在用ffmpeg解碼的時候,它叫linesize; 
在用ffmpeg轉換格式的時候,它叫stride。這篇文章中統一以間距來表示。

間距爲什麼出現:
這個參數看起來似乎沒什麼用,因爲它的值和圖像的寬度一樣。但是那是大多數情況下,一旦遇到它和寬度不一樣的時候,如果你不瞭解它的含義,那麼程序肯定要出問題。可是爲什麼有時候它等於寬度,有時候又不等於呢?這就和它的含義有關了。 
我們都知道現在計算機的cpu都是32位或者64位的cpu,他們一次最少讀取4、8個字節,如果少於這些,反而要做一些額外的工作,會花更長的時間。所有會有一個概念叫做內存對齊,將結構體的長度設爲4、8的倍數。 
間距也是因爲同樣的理由出現的。因爲圖像的操作通常按行操作的,如果圖像的所有數據都緊密排列,那麼會發生非常多次的讀取非對齊內存。會影響效率。而圖像的處理本就是一個分秒必爭的操作,所以爲了性能的提高就引入了間距這個概念。

間距的含義:
間距就是指圖像中的一行圖像數據所佔的存儲空間的長度,它是一個大於等於圖像寬度的內存對齊的長度。這樣每次以行爲基準讀取數據的時候就能內存對齊,雖然可能會有一點內存浪費,但是在內存充裕的今天已經無所謂了。

間距的值:
所以如果圖像的寬度如果是內存對齊長度的整數倍,那麼間距就會等於寬度,而現在的cpu通常一次讀取都是4個字節,而我們通常見到的分辨率都是4的整數倍,所以我們通常發現間距和圖像的寬度一樣(這裏通常指rgb32格式或者以通道表示的yuv420p格式的y通道)。但是如果遇到一些少見的分辨率時間距和圖像的寬度就不一樣。 
還有一種情況是顯卡,因爲顯卡是獨立工作的,所以顯卡可能和cpu的內存對齊位數是不同的,此時間距就可能和cpu上的有很大差別,例如NVIDA顯卡(它的內存對齊位數超大),通常在用d3d顯示的時候會用到間距。所以如果你的d3d顯示程序在Intel的顯卡上顯示正常,而在NVIDA顯卡上顯示不正常,先不要懷疑顯卡驅動,先看看你有沒有正確處理間距的問題(親生經歷)。

間距的處理:
那麼對於間距和寬度不同的時候要如何處理呢?在不同的情況下,處理不同,但是隻要把握一個核心—內存對齊,就能理解。

在使用d3d做圖像顯示的時候,在獲取顯示內存空間的時候通常會獲取到一個參數pitch,就是我們的間距。顯卡每次都將pitch長度的數據當做一行。我們將圖像數據複製過去得時候要一行一行復制,每次下一行數據的目的起始位置都是上一行的起始位置加上間距。如果是yv12這種通道表示的數據,u、v通道要相應的將行距除2。間距導致的空間內容可以不用置空。
在ffmpeg解碼的時候,解碼後會獲取到一個參數linesize,其實也是間距。從解碼後的數據內存中將數據拷貝出來的時候,需要一行一行拷貝,每一行數據的起始位置都是上一行的起始位置加上間距,一行的真正的圖像數據長度就是是圖像寬度(通道類型要相應除倍數)。
在用ffmpeg進行圖像格式轉換的時候,需要傳入一個參數stride,其實也是間距。只不過這次不需要複雜的處理,只需要知道傳入ffmpeg進行轉換的圖像數據使用的間距,然後傳入就行,ffmpeg會自動根據這個值進行相應的處理。
--------------------- 
作者:太上絕情 
來源:CSDN 
原文:https://blog.csdn.net/bjrxyz/article/details/52690661 
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章