일부 스케일링 기능을 사용하여 16 비트 unsigned short
데이터를 8 비트 unsigned char
으로 변환하려고합니다. 현재 저는 float로 변환하고 크기를 줄인 다음 8 비트로 채 웁니다. 더 효율적인 방법이 있습니까?스케일링을 효율적으로 사용하여 16 비트 부호없는 short를 8 비트 unsigned char로 변환하는 방법은 무엇입니까?
int _tmain(int argc, _TCHAR* argv[])
{
float Scale=255.0/65535.0;
USHORT sArr[8]={512,1024,2048,4096,8192,16384,32768,65535};
BYTE bArr[8],bArrSSE[8];
//Desired Conventional Method
for (int i = 0; i < 8; i++)
{
bArr[i]=(BYTE)(sArr[i]*Scale);
}
__m128 vf_scale = _mm_set1_ps(Scale),
vf_Round = _mm_set1_ps(0.5),
vf_zero = _mm_setzero_ps();
__m128i vi_zero = _mm_setzero_si128();
__m128i vi_src = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&sArr[0]));
__m128 vf_Src_Lo=_mm_cvtepi32_ps(_mm_unpacklo_epi16(vi_src, _mm_set1_epi16(0)));
__m128 vf_Src_Hi=_mm_cvtepi32_ps(_mm_unpackhi_epi16(vi_src, _mm_set1_epi16(0)));
__m128 vf_Mul_Lo=_mm_sub_ps(_mm_mul_ps(vf_Src_Lo,vf_scale),vf_Round);
__m128 vf_Mul_Hi=_mm_sub_ps(_mm_mul_ps(vf_Src_Hi,vf_scale),vf_Round);
__m128i v_dst_i = _mm_packus_epi16(_mm_packs_epi32(_mm_cvtps_epi32(vf_Mul_Lo), _mm_cvtps_epi32(vf_Mul_Hi)), vi_zero);
_mm_storel_epi64((__m128i *)(&bArrSSE[0]), v_dst_i);
for (int i = 0; i < 8; i++)
{
printf("ushort[%d]= %d * %f = %.3f ,\tuChar[%d]= %d,\t SSE uChar[%d]= %d \n",i,sArr[i],Scale,(float)(sArr[i]*Scale),i,bArr[i],i,bArrSSE[i]);
}
return 0;
}
스케일링 계수는 다른 값으로 설정해야 할 수도 있습니다. 255.0/512.0
, 255.0/1024.0
또는 255.0/2048.0
이므로 어떤 솔루션도 255.0/65535.0
으로 하드 코딩하면 안됩니다. 코드의 비율이 고정되어있는 경우
디버그보기의 부호가 무시됩니다. 아무 것도 영향을주지 않습니다. 값은 정확합니다. 마음 속의 비트를 재 해석하거나 인쇄하십시오. – harold
나는 당신이 대답을 삭제 한 것을 본다 - 정말로 이것을 할 필요는 없다 - 다소 비효율적이긴하지만 개선 할 다른 대답을위한 좋은 출발점이된다. 삭제 취소를 고려하십시오.(나는 아마도'_mm_mulhi_epu16'을 사용하여 직접 답변을 작성 하겠지만 오늘은 꽤 바쁩니다. 어쩌면 주말에 함께 할 것입니다.) –