how to convert HEX to Double (and keep precision)

I need to read in values from a serial port, which arrive in HEX encoded.

For instance, 75.8f = 0x42 0x97 0x99 0x9A When I receive “42 97 99 9A” I need to decode it to “75.800003”. Most of what I can find in Xojo language ref is useful for single values < 255, but not for Floats (Doubles).

The follow C code works, but I’m not sure how to recreate this in Xojo. Thanks for any pointers! (pun intended)

float value;
unsigned char* ptr = &value;
ptr[3] = 0x42;
ptr[2] = 0x97;
ptr[1] = 0x99;
ptr[0] = 0x9A;
printf(“%f
”, value);

Stuff it byte by byte into a Memoryblock then grab the double single value from that (skipped over that this is only 4 bytes of data not 8)

dim mb as new memoryblock(4)

mb.byte(3) = &h42
mb.byte(2) = &h97
mb.byte(1) = &h99
mb.byte(0) = &h9A

dim d as Double = mb.SingleValue(0)

break

Norman, I’ll be contacting my friends at Mensa and recommending they appoint you immediately. Thanks for the help. The “SingleValue” was where I got stuck, and you solved it before I had time to mention it. Many thanks! This seems to work like a charm:

dim myMB as New MemoryBlock(4)
dim myDouble as Double

myMB.LittleEndian = False

myMB.Byte(0) = &h42
myMB.Byte(1) = &h97
myMB.Byte(2) = &h99
myMB.Byte(3) = &h9A

myDouble=myMB.SingleValue(0)

MsgBox myDouble.ToText

// should be decimal: 75.800003

Hello everybody!
Here in Bergamo, Italy is so hot … And my neurons have decided to go on vacation …

I was reading your post. And it seems to me very useful for what I have to do.
I need to read a .is2 file (Fluke thermal image);
The temperature map is written using a simple data compression system.

In practice, using LITTLE_ENDIAN I have to read 2 bytes for example 0xDF11 and convert them to a Single Type variable

I wrote a class by translating something that was done in C.
But now I get an error when I try to use the ‘ByteBuffer’ class I can not fix.
Do you try to help me with courtesy?

Here’s the link for the class.

I’m not familiar with ByteBuffer class, and I cannot follow the link you posted to GitHub (perhaps my IT Director is blocking that URL). Is the class too large to paste directly into this ticket?

I’m sorry you can not have access to all the resources …
You put the zip file in google drive.
The class is a bit so complicated

Here is the link for google drive

… Have you tried google translate to open github ??? At least the link is no more than github …

Let me make sure I understand, you have (2) bytes and want to convert them to a value, in an Xojo application, correct? I just want to make sure there isn’t something more complicated you are trying to do…

Are you wanting to turn 0xDF11 into “6.41094e-42” (into a Double precision float)?

No, 0xDF11 = 76,6 or Something like that …

I have to do some tests because, I do not know exactly how the data is encoded in the file;
I think it works so, because from the beginning of the 0xE89 map at the end 26689 are exactly 153600 bytes, realizing that the map is from 320x240 = 76800 the data is saved in two bytes;
And are values from -1200.99 to 1200.99 so it should be so (and I hope)

Fortunately I know exactly where the temperature map begins and where it ends (ends with ‘PK’ = 0x504B)

Hi Massmiliano, I should hope someone else chimes in on this, but a single-precision floating-point requires 4-bytes, not 2-bytes as you show in your example.

Again, if I’m way off base please, someone give me a slap across my cheek.

https://en.wikipedia.org/wiki/Half-precision_floating-point_format

Xojo has no such floating point format SO you’d have to deal with conversion manually

You need the Bitwise functions (or use AND with two integers)

read the value into a Uint16 (which is 2 bytes) and “AND” things together and put the result in a SINGLE maybe

the conversion is listed on the wikipedia page

Probabilly first two bites are 00 … eg : 0x0000DF11

The response marked as the answer to this thread then handles it
https://forum.xojo.com/conversation/post/238207

No, my problema is other… Nave a outofbound exception when Reader position 0 offline memoryblock. Is for Two bytes l’essere ?

Massimiliano, is2 format is a point format (data point) that then you have to convert to double (in a approximated scale)

Sadly it’s a proprietary format so is hard to find some documentation.
I have found a couple of matlab functions that can be easily translated but both are “hard” linked to a specific model (there is no info about where the IR or IMG data starts)

Il formato relativo alla termografia inizia dal byte E89 e termina al byte 26689 . in pratica sono 153600 byte / 2 = 76800.
Se ovviamente il formato 320x240 thermal pixels; altrimenti il formato pi piccolo, 160x120 ad esempio; sono certo gli ultimi due byte DF11 dovrebbero corrispondere a 76,6 ( in fahrenheit degree ) per questo file.

For IMG data, are in RGB format, and are not important now.
Have a Java ( Android ) function and use ‘ByteBuffer’ function for work.

[code]package com.aolais.electroraven.is2viewerbeta.utils;

import java.io.ByteArrayInputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Map;

/**

  • Created by w7 on 02/03/2015.
    */
    public class EndianBinaryReader {
    private byte buff[];

    public EndianBinaryReader(Map<String, Object> irObject) {
    buff=(byte[]) irObject.get(“IR.data”);
    }
    /*
    public UShort[][] ReadUint16Array(int cols,int rows){
    }
    */

    public void TestWrapper(){
    byte[] buff;
    byte[] buff2;
    int int16;
    int num;
    short snum;
    char cnum;

     buff=new byte[4];
     buff[0]=-1;
     buff[1]=-1;
     buff[2]=00;
     buff[3]=00;
    
     ByteBuffer byBuff=ByteBuffer.wrap(buff);
     byBuff.order(ByteOrder.LITTLE_ENDIAN);
     int16=byBuff.getInt();
    
    
     buff=new byte[2];
     buff[0]=-1;
     buff[1]=-1;
    
     byBuff=ByteBuffer.wrap(buff);
     byBuff.order(ByteOrder.LITTLE_ENDIAN);
     snum=byBuff.getShort();
     cnum=(char)snum;
     num=(int)cnum;
    
     buff2=new byte[2];
     buff2[0]= (byte) (cnum  & (0xff));;
     buff2[1]= (byte) (cnum  >> 8);;
    
     buff[0]=30;
    

    }
    public char[][] ReadUint16Array(int cols,int rows){
    int num=320;
    char[][] Uint16Array=new char[cols][rows];
    byte buff[]=new byte[2];
    ByteArrayInputStream is=new ByteArrayInputStream(this.buff,num *2,this.buff.length);;

     for(int i=0;i<rows;i++){
         for(int j=0;j<cols;j++){
             is.read(buff,0,2);
             if(j==319) {
                 Uint16Array[j][i] = this.ReadUint16(buff);
             }
             else{
                 Uint16Array[j][i] = this.ReadUint16(buff);
             }
         }
     }
     return Uint16Array=null;
    

    }
    public char ReadUint16(byte[]buff){

     return ReadLittleEndianChar(buff);
    

    }
    public char ReadLittleEndianChar(byte[]buff){
    short sNum;
    char cNum;
    ByteBuffer byBuff=ByteBuffer.wrap(buff);
    byBuff.order(ByteOrder.LITTLE_ENDIAN);
    sNum=byBuff.getShort();
    cNum=(char)sNum;

     return cNum;
    

    }

    public int[][]ReadIntArray(int cols,int rows){
    int num=320;
    int[][] intArray=new int[cols][rows];
    byte buff[]=new byte[2];
    ByteArrayInputStream is=new ByteArrayInputStream(this.buff,num *2,this.buff.length);;

     for(int i=0;i<rows;i++){
         for(int j=0;j<cols;j++){
             is.read(buff,0,2);
                 intArray[j][i] = this.ReadInt(buff);
         }
     }
     return intArray;
    

    }
    public int ReadInt(byte[]buff){
    int num;
    byte[] mbuff=new byte[4];
    mbuff[0]=buff[0];
    mbuff[1]=buff[1];
    mbuff[2]=0;
    mbuff[3]=0;
    ByteBuffer byBuff=ByteBuffer.wrap(mbuff);
    byBuff.order(ByteOrder.LITTLE_ENDIAN);
    num=byBuff.getInt();

     return num;
    

    }
    }
    [/code]

Ok but where you find that data begin at that address and that it’s a 320x240 or a 160x120?
These info are within the file… somewhere

data are integer values to be “rescaled” and interpolated with a reference map

I lost in a glass of water …
I called a friend was working in Fluke;
He just explained that the temperatures are saved on file in format uint16, but we knew it already …
But how are they translated into temperature?
Simple, there is a simple calibration map at the beginning of the file that tells which report to use (such as simple division and subtraction) from the uint16 number to get the double value with a 0.01 degree accuracy.

Et voil !