How to convert /map uint16 to int16 maintaining the dynamic range so that [0] and [2^16-1] in uint16 beomes [-2^15] and [2^15-1] without going through double

43 views (last 30 days)
I would like to convert my uint16 values to int16 values amd maintain the dynamic range. All my attempts with typecast and cast still map value 0 (uint16) to 0 (int16). I would like it to map 0 (uint16) directly to -2^15 (int16). I need to convert a rather large dataset so I would like to circumvent doing to double or single if I can.
The data comes from fread and if I can do the mapping there directly then that would be even better. This is what I use now to read the data:
Data = fread(fid,[m n],'uint16=>uint16')';
Ive tried asking for 'uint16=>int16', but that also cuts the data
  1 Comment
Micke Malmström
Micke Malmström on 2 Feb 2024
Edited: Micke Malmström on 2 Feb 2024
% Example uint16 data
uint16Data = uint16([0, 2^16-1]);
% Map uint16 to int16
int16Data = int16(uint16Data - 2^15); % here is where the problem lies and I cant figure out how to circumvent going through double or single...
% Display the results
disp(['Original uint16 data: ', num2str(uint16Data)]);
Original uint16 data: 0 65535
disp(['Mapped int16 data: ', num2str(int16Data)]); % my desired result here is Mapped int16 data: -32768 32767
Mapped int16 data: 0 32767

Sign in to comment.

Accepted Answer

Stephen23
Stephen23 on 2 Feb 2024
Edited: Stephen23 on 2 Feb 2024
inp = uint16([-Inf,pi,Inf])
inp = 1×3
0 3 65535
Method one: use INT32 for the intermediate values:
off = int32(intmin('int16'));
out = int16(int32(inp)+off)
out = 1×3
-32768 -32765 32767
Method two: convert from two's complement to offset binary, which you can then simply TYPECAST into INT16:
out = typecast(bitset(inp,16,1-bitget(inp,16)),'int16')
out = 1×3
-32768 -32765 32767

More Answers (1)

Bruno Luong
Bruno Luong on 3 Feb 2024
Edited: Bruno Luong on 3 Feb 2024
If you have C compiler this simple mex file will do the job:
/**************************************************************************
* Matlab Mex file castint16.C
Convert uint16 to int16 by adding 2^15 in 2-complement binary coding
Example:
a = uint16([0 2^16-1])
b = castint16(a)
will return
1×2 int16 row vector
-32768 32767
Compile:
mex -R2018a castint16.c
*************************************************************************/
#include "mex.h"
#include "matrix.h"
#define A prhs[0]
#define B plhs[0]
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]) {
size_t i, n;
mxUint16 *a, *b;
if (nrhs!=1)
mexErrMsgTxt("castint16 missing input argument");
/* n = numel(A) */
n = mxGetNumberOfElements(A);
if (mxGetClassID(A) == mxUINT16_CLASS) {
a = mxGetUint16s (A);
B = mxCreateNumericMatrix(mxGetM(A), mxGetN(A), mxINT16_CLASS, mxREAL);
b = mxGetInt16s(B);
for (i = 0; i < n; i++)
b[i] = a[i] + 0x8000;
} else
mexErrMsgTxt("castint16 suports only UINT16 input");
}

Categories

Find more on Numeric Types in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!