source

부호 있는 문자에서 부호 없는 문자로 변환하고 다시 돌아오시겠습니까?

factcode 2022. 8. 21. 14:05
반응형

부호 있는 문자에서 부호 없는 문자로 변환하고 다시 돌아오시겠습니까?

저는 JNI에서 일하고 있으며 jbyte의 배열을 가지고 있습니다.jbyte는 -128~127의 부호 있는 문자로 표현됩니다.jbytes는 이미지 픽셀을 나타냅니다.화상 처리의 경우, 통상, 픽셀 컴퍼넌트의 범위는 0 ~255입니다.따라서 jbyte 값을 0 ~ 255 범위(부호 없는 문자와 동일한 범위)로 변환하고 값을 계산한 후 결과를 다시 jbyte로 저장합니다.

어떻게 하면 안전하게 변환할 수 있을까요?

픽셀 값이 30씩 증가하지만 255로 고정되는 이 코드를 작동시킬 수 있었습니다만, 안전한지, 휴대 가능한지는 모르겠습니다.

 #define CLAMP255(v) (v > 255 ? 255 : (v < 0 ? 0 : v))

 jbyte pixel = ...
 pixel = CLAMP_255((unsigned char)pixel + 30);

C와 C++ 모두에서 이 방법을 알고 싶습니다.

캐스트한 이유 중 이며, 에는 C++가 포함되어 있습니다.static_cast ★★★★★★★★★★★★★★★★★」reinterpret_cast

부호 없는 변수에서 부호 없는 변수로의 변환은 부호 없는 변수 + 1의 최대값으로 부호 없는 변수의 값을 포함하도록 지시하는 것을 의미할 수 있습니다., 부호 이면 ", "char " -128" 입니다.CHAR_MAX+1 "128" "-1" 입니다.CHAR_MAX+1255번입니다.스태틱 캐스트 시스템에서 되고 있는 있는 에 관계없이, 일부 없는 하는 것을 할 수 , 「」이 경우, 「」( 「」)입니다.0b10000000 128, 128, 255로 해야 합니다.0b11111111resterfret_cast는 resterfret_cast를 resterfret_cast로

이이 -128로 에 -128이.0b10000000은 -1로 됩니다.0b11111111그리고 그 사이에 있는 모든 사람들에게도 마찬가지입니다.그러나 다른 컴퓨터(일반적으로 오래된 아키텍처)에서는 부호 및 규모, 보 등 다른 부호 표현을 사용할 수 있습니다.0b10000000-128이므로 bit value가 .리프레트 캐스트 128자 덧붙여서, addition addition addition addition addition addition addition addition addition addition addition addition addition addition addition.0b11111111는 -1이 이 bit value가 bit value가 -1인 됩니다(이 값은 static_cast.bit value가 됩니다).보어의 경우 부호 없는 값 128은 -0의 값으로 인해 -127에서 127의 범위이기 때문에 실제로는 부호 있는 문자로 나타낼 수 없습니다.

대부분의 컴퓨터가 2의 보완을 사용하고 있기 때문에 코드 실행이 가능한 거의 모든 장소에서 문제 전체를 해결할 수 있습니다.매우 오래된 아키텍처에서는 2개의 보완 이외의 것을 가진 시스템을 볼 수 있을 것입니다.60년대의 타임라인이라고 생각됩니다.

구문은 다음과 같이 요약됩니다.

signed char x = -100;
unsigned char y;

y = (unsigned char)x;                    // C static
y = *(unsigned char*)(&x);               // C reinterpret
y = static_cast<unsigned char>(x);       // C++ static
y = reinterpret_cast<unsigned char&>(x); // C++ reinterpret

어레이를 사용하여 C++를 적절하게 사용하려면:

jbyte memory_buffer[nr_pixels];
unsigned char* pixels = reinterpret_cast<unsigned char*>(memory_buffer);

또는 C 방식:

unsigned char* pixels = (unsigned char*)memory_buffer;

네, 이것은 안전합니다.

c 언어에서는 정수 승격이라는 기능을 사용하여 계산을 수행하기 전에 값의 비트 수를 늘립니다.따라서 CLAMP255 매크로는 정수(아마 32비트) 정밀도로 작동합니다.결과는 jbyte에 할당되어 정수 정밀도가 jbyte에 맞는 8비트로 감소합니다.

CLAMP255는 v < 0에 대해 0을 반환하고 v > = 0에 대해 255를 반환한다는 것을 알고 계십니까?
는 IMHO, CLAMP255로.

#define CLAMP255(v) (v > 255 ? 255 : (v < 0 ? 0 : v))

차이점:v가 255보다 크고 0보다 작으면 255 대신 v를 반환합니다.

입력 데이터를 해석하는 방법에는 두 가지가 있습니다. -128은 가장 낮은 값이고 127은 가장 높은 값(즉, 진정한 서명된 데이터) 또는 0은 가장 낮은 값이고 127은 중간 값이며 다음 "높은" 숫자는 -128이며 -1은 "가장 높은" 값(즉, 가장 유의한 비트가 두 개의 컴포트에서 이미 신호 비트로 잘못 해석되었습니다).리스먼트 표기법

후자를 의미한다고 가정할 때, 공식적으로 올바른 방법은

signed char in = ...
unsigned char out = (in < 0)?(in + 256):in;

적어도 GCC는 수술 불가로 인식합니다.

제가 당신의 질문을 이해했는지 100% 확신할 수 없으니, 제가 틀렸다면 말해주세요.

제가 맞췄다면 기술적으로는 부호화된 문자이지만 실제로는 0에서 255 사이의 픽셀 값을 읽고 있습니다.그리고 프로세스에서 값을 손상시키지 않고 어떻게 처리해야 하는지 궁금할 것입니다.

Then, you should do the following:

  • convert jbytes to unsigned char before doing anything else, this will definetly restore the pixel values you are trying to manipulate

  • use a larger signed integer type, such as int while doing intermediate calculations, this to make sure that over- and underflows can be detected and dealt with (in particular, not casting to a signed type could force to compiler to promote every type to an unsigned type in which case you wouldn't be able to detect underflows later on)

  • when assigning back to a jbyte, you'll want to clamp your value to the 0-255 range, convert to unsigned char and then convert again to signed char: I'm not certain the first conversion is strictly necessary, but you just can't be wrong if you do both

For example:

inline int fromJByte(jbyte pixel) {
    // cast to unsigned char re-interprets values as 0-255
    // cast to int will make intermediate calculations safer
    return static_cast<int>(static_cast<unsigned char>(pixel));
}

inline jbyte fromInt(int pixel) {
    if(pixel < 0)
        pixel = 0;

    if(pixel > 255)
        pixel = 255;

    return static_cast<jbyte>(static_cast<unsigned char>(pixel));
}

jbyte in = ...
int intermediate = fromJByte(in) + 30;
jbyte out = fromInt(intermediate);

ReferenceURL : https://stackoverflow.com/questions/5040920/converting-from-signed-char-to-unsigned-char-and-back-again

반응형