from Byte manipulation and Endian conversion in MATLAB by Gautam Vallabha
A demonstration of MATLAB's built-in facilities for unpacking integers into individual bytes (and vi

Numeric and byte order (endian) conversions in MATLAB

Numeric and byte order (endian) conversions in MATLAB

Contents

Creating an integer variable

Say I want to create a variable of type uint16, with value 100.

Method 1

val1 = uint16(100);

Method 2

val2 = cast(100, 'uint16');

Method 3

val3 = zeros(1,1,'uint16');
val3(1) = 100;

whos val1 val2 val3
  Name      Size            Bytes  Class     Attributes

  val1      1x1                 2  uint16              
  val2      1x1                 2  uint16              
  val3      1x1                 2  uint16              

Incorrect method

The following won't work, since val4 will be reinitialized to have the type of the number '100', i.e., it will be a double.

val4 = zeros(1,1,'uint16');
val4 = 100;

whos val4
  Name      Size            Bytes  Class     Attributes

  val4      1x1                 8  double              

Destructive casting - I

If I have a variable of type uint16 and would like to convert it to a uint8, I can use the CAST or UINT8 commands.

First create a variable of type uint16

aval = uint16(10000);

Conversion to int16 is safe, since 10000 is within the valid range for an int16.

bval = int16(aval)
bval =
  10000

Convert to uint8 is not safe since the 10000 doesn't fit in the new type. Hence, the value gets clipped.

cval = uint8(aval)
cval =
  255

It is not possible to recover the original aval from the uint8 variable cval

new_aval = uint16(cval);
aval,new_aval
aval =
  10000
new_aval =
    255

Destructive casting - II

The behavior of CAST and functions like UINT16 or INT8 can be frustrating if I have a signed integer that I want to treat as an unsigned number, or vice versa (i.e., I want to convert to/from the two's-complement representation of the number).

aval = int16(-200);
bval = uint16(aval);
whos aval bval, bval
  Name      Size            Bytes  Class     Attributes

  aval      1x1                 2  int16               
  bval      1x1                 2  uint16              

bval =
      0

bval is 0 since the allowable range for a uint16 is [0,65535], and the value of -100 gets clipped to 0. Hence, it is not possible to recover the original number, even though aval and bval have the same size (two bytes):

new_aval = int16(bval);
aval, new_aval
aval =
   -200
new_aval =
      0

Non-destructive casting

The way to do non-destructive casting is with the TYPECAST command.

aval = int16(-200);
bval = typecast(aval, 'uint16');
whos aval bval, bval
  Name      Size            Bytes  Class     Attributes

  aval      1x1                 2  int16               
  bval      1x1                 2  uint16              

bval =
  65336

Now convert back from uint16 to int16

new_aval = typecast(bval, 'int16');
aval, new_aval
aval =
   -200
new_aval =
   -200

Converting an integer to a sequence of bytes

Say I want to convert a mulitbyte number to a sequence of bytes (e.g., I want to save the data in a custom binary format, or want to send it over a communications channel that only takes a sequence of bytes).

Make a 4-byte signed integer

aval = int32(-314159);
whos aval, aval
  Name      Size            Bytes  Class    Attributes

  aval      1x1                 4  int32              

aval =
     -314159

Convert the 4-byte integer to a sequence of four unsigned bytes

bval = typecast(aval, 'uint8');
whos bval, bval
  Name      Size            Bytes  Class    Attributes

  bval      1x4                 4  uint8              

bval =
  209   52  251  255

Now convert from the sequence of bytes back to a multibyte value

new_aval = typecast(bval, 'int32');
aval, new_aval
aval =
     -314159
new_aval =
     -314159

Converting a floating-point value to a sequence of bytes

Create an 8-byte floating point value (i.e., of type double)

aval = 3.14159; % equivalent to double(3.14159)
whos aval, aval
  Name      Size            Bytes  Class     Attributes

  aval      1x1                 8  double              

aval =
    3.1416

This becomes a sequence of 8 unsigned bytes

bval = typecast(aval, 'uint8');
whos bval, bval
  Name      Size            Bytes  Class    Attributes

  bval      1x8                 8  uint8              

bval =
  110  134   27  240  249   33    9   64

Now convert back:

new_aval = typecast(bval, 'double');
aval, new_aval
aval =
    3.1416
new_aval =
    3.1416

Converting a sequence of bytes to an integer

Sometimes I have a sequence of bytes that I want to convert to a multibyte integer. This example shows how to go from an array of four bytes to a uint32.

Define a byte array of length 4

byteArray = zeros(1,4,'uint8');
byteArray(1) = 2;
byteArray(2) = 1;
whos byteArray, byteArray
  Name           Size            Bytes  Class    Attributes

  byteArray      1x4                 4  uint8              

byteArray =
    2    1    0    0

Another way of specifying byteArray

byteArray = uint8([2 1 0 0]);

Now convert to a uint32 (the bytes will be interpreted in Little-endian order on my system).

integerValue = typecast(byteArray, 'uint32');
whos integerValue, integerValue
  Name              Size            Bytes  Class     Attributes

  integerValue      1x1                 4  uint32              

integerValue =
         258

Checking the Endianness of the system

The COMPUTER command returns the current endian-ness (the value of endian is 'L' if the system is Little-endian, and 'B' if it is Big-endian).

[computerType, maxSize, endian] = computer;
isLittleEndian = (endian == 'L')
isLittleEndian =
     1

Another way of testing the endianness

testNumber = uint32(1);
byteSeq = typecast(testNumber, 'uint8');
isLittleEndian = (byteSeq(1) == 1)
isLittleEndian =
     1

Little-endian and Big-endian conversions

The TYPECAST operator makes it easy to do byte-order conversions, such as from Little-endian to Big-endian. For example, I may need to save to a binary file that needs to be read on big-endian system, or may need to send data over a communications channel that assumes big-endian representation.

Create a little-endian number (I know it is little-endian since my computer is a Little-endian system; see the section on checking endianness).

leNumber = uint32(258);

Get the bytes in the 32-bit little-endian number (note that the leftmost byte is the least-significant one).

byteSeq = typecast(leNumber, 'uint8')
byteSeq =
    2    1    0    0

See each byte as a binary number (each row is one byte)

dec2bin(byteSeq,8)
ans =
00000010
00000001
00000000
00000000

There are two ways to convert the little-endian value to a big-endian value

Method 1: Use the SWAPBYTES command

beNumber = swapbytes(leNumber)
newByteSeq = typecast(beNumber, 'uint8')
beNumber =
    33619968
newByteSeq =
    0    0    1    2

Method 2: Do the conversion myself

newByteSeq = byteSeq(end:-1:1)
beNumber = typecast(newByteSeq, 'uint32')
newByteSeq =
    0    0    1    2
beNumber =
    33619968

Help on functions

help class
 CLASS  Create object or return object class.
    C = CLASS(OBJ) returns the class of the object OBJ.
    Possibilities are:
      double          -- Double precision floating point number array
                         (this is the traditional MATLAB matrix or array)
      single          -- Single precision floating point number array
      logical         -- Logical array
      char            -- Character array
      cell            -- Cell array
      struct          -- Structure array
      function_handle -- Function Handle
      int8            -- 8-bit signed integer array
      uint8           -- 8-bit unsigned integer array
      int16           -- 16-bit signed integer array
      uint16          -- 16-bit unsigned integer array
      int32           -- 32-bit signed integer array
      uint32          -- 32-bit unsigned integer array
      int64           -- 64-bit signed integer array
      uint64          -- 64-bit unsigned integer array
      <class_name>    -- Custom object class
      <java_class>    -- Java class name for java objects
 
    All other uses of CLASS must be invoked within a constructor method,
    in a file named <class_name>.m in a directory named @<class_name>.
    Further, 'class_name' must be the second argument to CLASS.
 
    O = CLASS(S,'class_name') creates an object of class 'class_name'
    from the structure S.
 
    O = CLASS(S,'class_name',PARENT1,PARENT2,...) also inherits the
    methods and fields of the parent objects PARENT1, PARENT2, ...
 
    O = CLASS(struct([]),'class_name',PARENT1,PARENT2,...), specifying
    an empty structure S, creates an object that inherits from one or
    more parent classes, but which does not have any additional fields
    not inherited from the parents.
 
    See also ISA, SUPERIORTO, INFERIORTO, STRUCT.

    Overloaded methods:
       scribehandle/class
       serial/class
       digitalio/class
       analogoutput/class
       analoginput/class
       visa/class
       udp/class
       tcpip/class
       icgroup/class
       icdevice/class
       gpib/class

    doc class
      
help cast
 CAST  Cast a variable to a different data type or class.
    B = CAST(A,NEWCLASS) casts A to class NEWCLASS. A must be convertible to
    class NEWCLASS. NEWCLASS must be the name of one of the builtin data types.
 
    Example:
       a = int8(5);
       b = cast(a,'uint8');
 
    See also CLASS.

    Overloaded methods:
       ccspointer/cast
       ccsnumeric/cast
       ccsenum/cast
       ccsbitfield/cast
       darray/cast

    doc cast
      
help typecast
 TYPECAST Convert datatypes without changing underlying data.
    Y = TYPECAST(X, DATATYPE) convert X to DATATYPE.  If DATATYPE has
    fewer bits than the class of X, Y will have more elements than X.  If
    DATATYPE has more bits than the class of X, Y will have fewer
    elements than X.  X must be a scalar or vector.  DATATYPE must be one
    of 'UINT8', 'INT8', 'UINT16', 'INT16', 'UINT32', 'INT32', 'UINT64',
    'INT64', 'SINGLE', or 'DOUBLE'.
  
    Note: An error is issued if X contains fewer values than are needed
    to make an output value.
  
    Example:
  
       X = uint32([1 255 256]);
       Y = typecast(X, 'uint8');
  
    On little-endian architectures Y will be
  
       [1   0   0   0   255 0   0   0   0   1   0   0]
  
   See also CLASS, CAST, SWAPBYTES.

    Overloaded methods:
       darray/typecast

    doc typecast
      
help swapbytes
 SWAPBYTES Swap byte ordering, changing endianness.
     Y = SWAPBYTES(X) reverses the byte ordering of the matrix X,
     converting little-endian values to big-endian (and vice versa).
 
     Example:
 
        X = uint16([0 1 128 65535]);
        Y = swapbytes(X);
 
     Y will have the following uint16 values:
 
        [0    256  32768  65535]
 
     Examining the output in hex notation shows the byte swapping:
 
        format hex
        X, Y
        format
     
     See also TYPECAST.

    Overloaded methods:
       darray/swapbytes

    doc swapbytes
      

Contact us