2013-01-08 4 views
0

먼저이 파일이 중복되면 내 질문에 답하는 제목을 찾을 수 없습니다.정확하게 float 32를 부호없는 short 또는 unsigned char로 변환하십시오.

32 비트 부동 소수점 값을 short int (16 비트) 및 unsigned char (8 비트) 값으로 변환하는 데 사용할 약간의 프로그램을 코딩하고 있습니다. 이것은 HDR 이미지 용도입니다.

static inline uint8_t u8fromfloat(float x) 
{ 
    return (int)(x * 255.0f); 
} 

내가 같은 방법으로 우리는 (pow(2,16) -1)

을 곱하여 짧은 INT를 얻을 수 있다고 생각하지만 나는 결국 :

here 에서 나는 (클램핑없이) 다음 함수를 얻을 수 주문한 디더링 및 특히 바이어 디더링에 대해 생각합니다. uint8_t로 변환하려면 4x4 행렬과 8 * 8 행렬을 부호없는 short로 사용할 수 있다고 가정합니다. I는 룩업 테이블 생각

스피드 업하는 프로세스, 이러한 방법 :

uint16_t LUT[0x10000] // 2^16 values contained 

저장 2^16 개의 짧은 부호 값 플로트에 대응한다. 이 같은 테이블은 다음 사이에 있기 때문에 암시 적 캐스트의뿐만 아니라 uint8_t에 사용될 수 서명되지 않은 짧은 < ->

INT 부호하지만이 같은 룩업 테이블은 메모리에 큰되지 않을 것? 또한 어떻게이 테이블을 채울 것입니까?!

이제 혼란 스럽 습니다만, 당신에게 가장 좋은 것은 무엇입니까? 도움 주셔서 감사합니다!

uwind 대답 이후에 EDIT : U8/U16으로 변환하기 전과 동시에 색상 공간 변환 (float)을 수행 한 다음 기본 색상 공간 변환을 수행하고 싶다고 가정 해 보겠습니다. ~ U8/U16. 이 경우에 너트를 사용하는 것이 더 효율적이지 않겠는가? 그리고 그래, 난 여전히 lut 색인에 문제가있을 것입니다 ..

.

+0

테이블 조회를 병렬화 할 수 없기 때문에 더 그렇게 LUT 방법을 쉽게 능가 할 것이다 4-8x 성능이 향상됩니다. – Jodrell

+0

예는, 나는 C/C++ – Lex

답변

1

필자가 보는 방식으로 색인을 생성하기 위해 색인을 생성하기 위해 룩업 테이블이 도움이되지 않을 것이다. float을 정수형으로 변환해야하기 때문이다. 캐치 22.

테이블에는 0x10000 * sizeof (uint16_t) 바이트 (128KB)가 필요합니다. 현대 표준에서는 그리 많지 않지만 캐시는 소중합니다. 하지만, 내가 말했듯이, 인덱스는 float을 정수로 변환해야하기 때문에 테이블에 솔루션을 많이 추가하지 않습니다.

float의 원시 비트를 인덱스로 사용하여 테이블을 정수로 다시 해석 할 수는 있지만 32 비트는 매우 커 (8GB 정도)되어야합니다.

사용자가 개요를 설명한 바로 가기 런타임 변환으로 이동하십시오.

+0

감사에 입력이 긴장을 풀고하다는 것을 정확한에 잊어 버렸습니다. 이제 나는 또한 동시에 기본 색 공간 변환을 수행하려는 지금 가정 해 봅시다, 그 U8/U16로 변환하기 전에, (부동의) 색 공간 변환을 수행하고 U8/U16로 축소합니다. 이 경우에 너트를 사용하는 것이 더 효율적이지 않겠는가? 그리고 그래, 난 여전히 색인에 문제가 생겼을거야 ... – Lex

0

그냥 곱셈과 함께있어 - 잘 작동합니다.

실질적으로 모든 최신 CPU에는이 명령어에 적합한 벡터 명령어 (SSE, AVX, ...)가 있으므로 프로그래밍을 고려해야합니다. 또는 가능한 경우 자동으로 코드를 벡터화하는 컴파일러를 사용하십시오 (Intel C, GCC). 테이블 조회가 가능한 솔루션 인 경우에도 메모리 대기 시간이 발생하지 않으므로 속도가 빨라질 수 있습니다.

-1

먼저 플로트 방법은 16 비트 INT에 적합하지 않거나 심지어는 8 비트 수 24 비트의 정밀도를 갖는다. 둘째, 플로트가 오래 오래

INT 어떤 INT에 저장하거나 할 수없는 훨씬 더 큰 범위를 가지고 그래서 귀하의 질문에 정확하게 짧거나 문자에 모든 float로 변환하는 방법은 정확하지 않습니다. 이것은 더욱 정확하게 표현 8 비트 또는 16 비트 32 비트 부동 소수점 화소 값을 변환하는 등 할 수있다. 같은 254.99999 같은

위에서 사용하는 코드에 대한

, 정확히 1.0 입력이 필요하기 때문에 255가 덜 반환 할 것입니다 값, 그렇지 않으면 값은 당신이 어떤 종류를 사용하거나 반올림한다 254로 잘린 결국 것이다

return (int)(x * 255.0f + .5f); 

또는 더 나은, 더 균형 잡힌 배포를 위해 귀하의 링크에서 제공하는 코드를 사용하여 16 비트 값에 대한 테이블이 캐시에 피팅 너무 크기 때문에 빨리되지 않을 것 LUT를 사용

static inline uint8_t u8fromfloat_trick(float x) 
{ 
    union { float f; uint32_t i; } u; 
    u.f = 32768.0f + x * (255.0f/256.0f); 
    return (uint8_t)u.i; 
} 

과의 사실은 당신의 성과를 크게 떨어 뜨릴 수 있습니다. 위의 코드는 2 개의 부동 소수점 명령어 만 필요하거나 FMA를 사용하면 1 개의 명령어만으로 충분합니다. 그리고 SIMD는 나는 이것이 C 질문입니다 가정 한

관련 문제