2013-03-15 46 views
13

Çoğu modern CMOS kamera 12 bitlik görüntü üretebilir. En hızlı hangisi 12bit görüntü verisi dizisini 16 bit'e dönüştürür? Asıl sorun, her bir 12 bitlik sayının 4 sıfır ile doldurulmasıdır, küçük endian kabul edilebilir, SSE2/SSE3/SS4 de kabul edilebilir.12bit görüntüyü 16bit görüntüye dönüştürmenin en hızlı yolu

int* imagePtr = (int*)Image.data; 
fixed (float* imageData = img.Data) 
{ 
    float* imagePointer = imageData; 
    for (int t = 0; t < total; t++) 
     { 
     int i1 = *imagePtr; 
     imagePtr = (int*)((ushort*)imagePtr + 1); 
     int i2 = *imagePtr; 
     imagePtr = (int*)((ushort*)imagePtr + 2); 
     *imagePointer = (float)(((i1 << 4) & 0x00000FF0) | ((i1 >> 8) & 0x0000000F)); 
     imagePointer++; 
     *imagePointer = (float)((i1 >> 12) & 0x00000FFF); 
     imagePointer++; 
     *imagePointer = (float)(((i2 >> 4) & 0x00000FF0) | ((i2 >> 12) & 0x0000000F)); 
     imagePointer++; 
     *imagePointer = (float)((i2 >> 20) & 0x00000FFF); 
     imagePointer++; 
     } 
    } 
+0

Bazı kodları ekledim. Bir 12bit resmini bir float dizisine dönüştürün ancak aynı zamanda bir UInt16'ya da (sadece döküm işlemini değiştirerek) çevirebilirsiniz. – Gilad

+6

Bu eğlenceli ve ilginç bir soru. Kesinlikle kapatılmaya gerek yoktur. – erisco

+0

En Hızlı ... platforma bağlıdır. RAM, önbellek vb. .. Sadece C# diliyle SSE kullanamazsınız. Parametrelerinizi/kısıtlamalarınızı tanımlayın ve onlara bağlı kalın, lütfen. Aksi durumda, soru –

cevap

2

Ben en hızlı garanti edemez, ancak bu SSE kullanan bir yaklaşımdır:

Kod ekledi. Yineleme başına sekiz adet 12-16 bit dönüşüm yapılır ve adım başına iki dönüşüm (yaklaşık) yapılır (yani, her bir yinelemede birden çok adım atılır).

Bu yaklaşım, xmm kaydındaki 16 bitlik sınırlar etrafındaki 12 bit tamsayıları aşıyor. Aşağıda bunun nasıl yapıldığını gösterir.

  • Bir x mm kayıt kullanılıyor (xmm0 varsayalım). Kayıt durumu bir harf satırı ile temsil edilir.
  • Her harf 12 bit tamsayıdan 4 bit gösterir (yani, dizideki ilk 12 bitlik kelimenin tamamı AAA'dur).
  • Her boşluk 16 bitlik bir sınırı temsil eder.
  • >> 2, bir baytın mantıksal olarak doğru kaydırılmasını belirtir.
  • Havuç (^) simgesi, her bir adımda, ilgili 12 bit tamsayıların 16bit sınırını geçtiğini vurgulamak için kullanılır.

: Her adımda

load 
AAAB BBCC CDDD EEEF FFGG GHHH JJJK KKLL 
^^^ 

>>2 
00AA ABBB CCCD DDEE EFFF GGGH HHJJ JKKK 
     ^^^ ^^^  

>>2 
0000 AAAB BBCC CDDD EEEF FFGG GHHH JJJK 
       ^^^ ^^^  

>>2 
0000 00AA ABBB CCCD DDEE EFFF GGGH HHJJ 
          ^^^ ^^^  

>>2 
0000 0000 AAAB BBCC CDDD EEEF FFGG GHHH 
            ^^^ 

, Hizalandığımız 12bit tamsayılar ayıklamak ve XMM1 defterine bunları saklayabilir. Sonunda, bizim xmm1 aşağıdaki gibi görünecek. Soru işaretleri, önemsemediğimiz değerleri belirtmektedir.

AAA? ?BBB CCC? ?DDD EEE? ?FFF GGG? ?HHH 

yüksek hizalanmış tamsayılar (A, C, E, G) XMM2 içine ve daha sonra, XMM2 ile, 4 bitlik bir sağ mantıksal kelime kayma gerçekleştirmek ekstrakte edin. Bu, yüksek hizalanmış tam sayıları düşük hizada dönüştürür. Bu ayarlanmış tam sayıları xmm1'e geri karıştırın. XMM1 durumu şimdi:
?AAA ?BBB ?CCC ?DDD ?EEE ?FFF ?GGG ?HHH 

Sonunda tamsayılar dışarı maskeleyebilir (yani dönüştürmek 'ın 0 en etmek?) 0FFFh her kelimenin üstünde.

0AAA 0BBB 0CCC 0DDD 0EEE 0FFF 0GGG 0HHH 

Artık xmm1, birbirini izleyen sekiz dönüştürülmüş tam sayı içeriyor.

Aşağıdaki NASM programı bu algoritmayı göstermektedir.

global main 

segment .data 
sample dw 1234, 5678, 9ABCh, 1234, 5678, 9ABCh, 1234, 5678 
low12 times 8 dw 0FFFh 

segment .text 
main: 

    movdqa xmm0, [sample] 

    pblendw xmm1, xmm0, 10000000b 
    psrldq xmm0, 1 
    pblendw xmm1, xmm0, 01100000b 
    psrldq xmm0, 1 
    pblendw xmm1, xmm0, 00011000b 
    psrldq xmm0, 1 
    pblendw xmm1, xmm0, 00000110b 
    psrldq xmm0, 1 
    pblendw xmm1, xmm0, 00000001b 

    pblendw xmm2, xmm1, 10101010b 
    psrlw xmm2, 4 

    pblendw xmm1, xmm2, 10101010b 

    pand xmm1, [low12]  ; low12 could be stored in another xmm register 
1

SSSE3 yönergesi PSHUFB; A = [a0, a1, a2, a3 ... a7], B = [b0, b1, b2, .. b7] verilen = 0; BX'in üst biti 1 ise, sonuç baytının sıfır olması dışında Böylece

,

 A = [aa ab bb cc cd dd ee ef] == input vector 

C=PSHUFB(A, [0 1 1 2 3 4 4 5]) = [aa ab ab bb cc cd cd dd] 
C=PSRLW (C, [4 0 4 0])   = [0a aa ab bb 0c cc cd dd] // (>> 4) 
C=PSLLW (C, 4)     = [aa a0 bb b0 cc c0 dd d0] // << by immediate 

ise tam bir çözelti, 3 ya da 6 mmx/xmm kayıtları okumak olacaktır ve çıkış 4/8 mmx/xmm her turda kaydeder. Ortadaki iki çıkışın, bazı ekstra kopyalama ve yazmaçların birleştirilmesini gerektiren iki giriş parçasından birleştirilmesi gerekir.

+0

Montaj programlama ve SSE talimatları için yeni. PSHUFB oldukça güçlü bir talimattır. 'C = C.16 >> [4 0 4 0] 'için hangi komutu kullanıyorsunuz? Sonuç verildiğinde bile ne anlama geldiğinden emin değilim. – erisco

+0

Bu, PSRLW veya değişken bit bitleriyle "paketlenmiş kaydırma sağ mantıksal kelime" kayması olurdu. Vektör [4 0 4 0] diğer işleneni gösterir. Ayrıca, örnekleri sadece kavramı göstermek için mmx kayıtları için verilmiştir. Neon dünyasından .16 önekini ödünç aldım. –

İlgili konular