2013-08-07 3 views
1

첫째로, 이것이 중복 인 경우에 나는 사과한다; 하지만 내 Google-fu는 오늘 실패하고있는 것 같습니다.하나에 2 바이트

Photoshop 용 이미지 형식 모듈을 작성하는 중이고이 형식의 저장 옵션 중 하나에는 4 비트 알파 채널이 포함되어 있습니다. 물론 변환해야하는 데이터는 8 비트/1 바이트 알파입니다. 따라서 본질적으로 알파 2 바이트를 모두 취해 하나에 병합해야합니다. 각각 8 비트 알파 데이터와 4 비트 알파 데이터를 포함

for(int x=0,w=0;x < alphaData.size();x+=2,w++) 
{ 
    short ashort=(alphaData[x] << 8)+alphaData[x+1]; 
    alphaFinal[w]=(unsigned char)ashort; 
} 

alphaData 및 alphaFinal 있습니다 벡터 :

내 시도 (아래), 저는 믿습니다 개선의 여지가 많이있다. 2 바이트를 하나의 값으로 줄이는 것이 "해상도"를 잃는 결과를 낳을 수밖에 없지만, 더 나은 방법이 있다고 생각합니다. 추가 정보

가 여기 역을 수행하는 루프이다

alphaData는 상기와 동일한 목적으로 기능하고, imgData 부호없는 문자 벡터이다 (포토샵 8 비트로 포맷으로부터 4 비트 알파 변환) 원시 이미지 데이터를 보유합니다.

for(int b=alphaOffset,x2=0;b < (alphaOffset+dataLength); b++,x2+=2) 
{ 
    unsigned char lo = (imgData[b] & 15); 
    unsigned char hi = ((imgData[b] >> 4) & 15); 
    alphaData[x2]=lo*17; 
    alphaData[x2+1]=hi*17; 
} 
+0

+1 Google-Fu 단어 재생 전용입니다. – WhozCraig

답변

1

그것이

alphaData[x2]=lo*17; 
alphaData[x2+1]=hi*17; 

하지

alphaData[x2]=lo*16; 
alphaData[x2+1]=hi*16; 

의 당신이 있는지 있습니까 (알파 데이터 형식이 특정 변형에 이미지의 실제 RGB 데이터 이후에 압정으로 고정됩니다) 어쨌든, 게시 한 디코딩 함수로 작동하는 값을 생성하려면 작업을 되돌려 주시면됩니다. 그래서 17로 나누어과 변화 및 마스크는 다음과 같이 재정렬 취득 (17)에 의해된다 곱 : 당신은 실제로 [X] alphaFinal에 alphaData을 잃고

for(int x=0,w=0;x < alphaData.size();x+=2,w++) 
{ 
    unsigned char alpha1 = alphaData[x]/17; 
    unsigned char alpha2 = alphaData[x+1]/17; 
    Assert(alpha1 < 16 && alpha2 < 16); 
    alphaFinal[w]=(alpha2 << 4) | alpha1; 
} 
+0

처음에는 테스트 한 첫 번째 이미지가 반투명 한 것을 제외하고는 * 16 일 것이라고 생각했습니다. 되돌아 보면, 나는 15 (최고 값의 니블) * 16 = 240, 255 대신에 나타났습니다. 어쨌든 나는 명백한 것을 간과하는 습관이있는 것 같습니다. 고마워, 잘됐다! –

+0

반올림을 사용하여 부분을 수행해야한다고 생각합니다. 즉'(alphaData [x] + 8)/17'입니다. – starblue

0
short ashort=(alphaData[x] << 8)+alphaData[x+1]; 
    alphaFinal[w]=(unsigned char)ashort; 

합니다. alphaData [x]를 8 비트 왼쪽으로 이동 한 다음 8 개의 하위 비트를 지정합니다.

또한 for 루프가 안전하지 않습니다. 어떤 이유로 alphaData.size()가 홀수 일 경우 범위를 벗어납니다.

+0

그래, 알아. 나쁜 습관이지만 - 근사한 초안을 만드는 이상한 방법입니다. 그러나 첫 번째 부분에 대한 설명에 감사드립니다. 그 결과를 설명하는 데 확실히 도움이됩니다. –

0

내가 원하는 것은 8 비트 값을 4 비트 값으로 잘라내는 것입니다. 두 개의 8 비트 값을 결합하지 마십시오. 즉, 두 개의 다른 알파 값을 결합하지 말고 각 알파 값의 최하위 비트 4 개를 삭제하려고합니다.

10110110 
>> 1 
= 01011011 
>> 1 
= 00101101 
>> 1 
= 00010110 
>> 1 
= 00001011 

때문에,

: 그래서, 기본적으로, 당신은 걸릴 이진 변화에 익숙하지 않은 경우 4.

output = (input >> 4); /* truncate four bits */ 

에 의해 오른쪽 시프트이 임의의 8 비트 수를 원하는

10110110 
>> 4 
= 00001011 

대신 왼쪽 쉬프트 ...당신이 언급 한 바와 같이, 분명

00001011 
>> 4 
= 10110000 

것 이전과 같은 임의의 8 비트 숫자의 결과를 사용하여,

input = (output << 4); /* expand four bits */ 

, 정밀의 4 비트가 손실됩니다. 그러나 완전히 합성 된 작품에서 얼마나 작은 부분인지 알면 놀랄 것입니다.

0

이 코드

for(int x=0,w=0;x < alphaData.size();x+=2,w++) 
{ 
    short ashort=(alphaData[x] << 8)+alphaData[x+1]; 
    alphaFinal[w]=(unsigned char)ashort; 
} 

깨진입니다. 당신이 당신의 소스 스트림이 하나의 8 비트 값으로 당신이 할 필요가 8 비트의 저장 값에 저장 4 비트 쌍 시퀀스, 다시 저장소가 말하는 경우

#include <iostream> 

using std::cout; 
using std::endl; 

typedef unsigned char uchar; 

int main() { 
    uchar x0 = 1; // for alphaData[x] 
    uchar x1 = 2; // for alphaData[x+1] 

    short ashort = (x0 << 8) + x1; // The value 0x0102 
    uchar afinal = (uchar)ashort; // truncates to 0x02. 

    cout << std::hex 
     << "x0 = 0x" << x0 << " << 8 = 0x" << (x0 << 8) << endl 
     << "x1 = 0x" << x1 << endl 
     << "ashort = 0x" << ashort << endl 
     << "afinal = 0x" << (unsigned int)afinal << endl 
    ; 
} 

을 감안할 때, 당신은 원하는 것을 이다

for(int x=0,w=0;x < alphaData.size();x+=2,w++) 
{ 
    unsigned char aleft = alphaData[x] & 0x0f; // 4 bits. 
    unsigned char aright = alphaData[x + 1] & 0x0f; // 4 bits. 
    alphaFinal[w] = (aleft << 4) | (aright); 
} 

"< < 4 ''>> 4"로, "* 16"동등 "/ 16"에 상응한다.

관련 문제