convertOrtValue method
Converts an OrtValue to a different data type
valueId
is the ID of the OrtValue to convert
targetType
is the target data type (e.g., 'float32', 'float16')
Implementation
@override
Future<Map<String, dynamic>> convertOrtValue(String valueId, String targetType) async {
try {
// Check if the tensor exists
if (!_ortValues.containsKey(valueId)) {
throw PlatformException(code: "INVALID_VALUE", message: "OrtValue with ID $valueId not found", details: null);
}
final tensor = _ortValues[valueId]!;
// Get tensor type and shape
final sourceType = tensor.getProperty('type'.toJS).toString();
final jsShape = tensor.getProperty('dims'.toJS) as JSObject;
final shapeLength = (jsShape.getProperty('length'.toJS) as JSNumber).toDartInt;
final shape = <int>[];
for (var i = 0; i < shapeLength; i++) {
final val = jsShape.getProperty(i.toString().toJS) as JSNumber;
shape.add(val.toDartInt);
}
// Get the data from the tensor
final jsData = tensor.getProperty('data'.toJS) as JSObject;
final dataLength = (jsData.getProperty('length'.toJS) as JSNumber).toDartInt;
// Create a new tensor based on the conversion type
JSObject newTensor;
// Handle different conversion scenarios
switch ('$sourceType-$targetType') {
// Float32 to Int32
case 'float32-int32':
final intArray = [];
for (var i = 0; i < dataLength; i++) {
final val = jsData.getProperty(i.toString().toJS) as JSNumber;
intArray.add(val.toDartDouble.toInt());
}
final jsIntArray = _convertToTypedArray(intArray, 'Int32Array');
newTensor = tensorConstructor.callAsConstructorVarArgs(['int32'.toJS, jsIntArray, jsArrayFrom(shape)]);
break;
// Float32 to Int64 (BigInt64Array)
case 'float32-int64':
// For int64 conversions in web, we need to skip the test
// since BigInt64Array is not properly supported in all browsers
// Throw a more user-friendly error
throw PlatformException(
code: "CONVERSION_ERROR",
message: "Int64 conversions are not fully supported in the web implementation yet",
details: null,
);
// Int32 to Float32
case 'int32-float32':
final floatArray = [];
for (var i = 0; i < dataLength; i++) {
final val = jsData.getProperty(i.toString().toJS) as JSNumber;
floatArray.add(val.toDartDouble);
}
final jsFloatArray = _convertToTypedArray(floatArray, 'Float32Array');
newTensor = tensorConstructor.callAsConstructorVarArgs(['float32'.toJS, jsFloatArray, jsArrayFrom(shape)]);
break;
// Int64 to Float32
case 'int64-float32':
final floatArray = [];
for (var i = 0; i < dataLength; i++) {
final val = jsData.getProperty(i.toString().toJS) as JSNumber;
// Convert BigInt to double for dart:js_interop
double doubleValue = 0.0;
try {
doubleValue = val.toDartDouble;
} catch (e) {
// Handle conversion errors
doubleValue = 0.0;
}
floatArray.add(doubleValue);
}
final jsFloatArray = _convertToTypedArray(floatArray, 'Float32Array');
newTensor = tensorConstructor.callAsConstructorVarArgs(['float32'.toJS, jsFloatArray, jsArrayFrom(shape)]);
break;
// Int32 to Int64
case 'int32-int64':
// For int64 conversions in web, we need to skip the test
// since BigInt64Array is not properly supported in all browsers
// Throw a more user-friendly error
throw PlatformException(
code: "CONVERSION_ERROR",
message: "Int64 conversions are not fully supported in the web implementation yet",
details: null,
);
// Int64 to Int32 (with potential loss of precision)
case 'int64-int32':
final intArray = [];
for (var i = 0; i < dataLength; i++) {
final val = jsData.getProperty(i.toString().toJS) as JSNumber;
// Convert BigInt to int for dart:js_interop
int intValue = 0;
try {
intValue = val.toDartInt;
} catch (e) {
// Handle conversion errors
intValue = 0;
}
intArray.add(intValue);
}
final jsIntArray = _convertToTypedArray(intArray, 'Int32Array');
newTensor = tensorConstructor.callAsConstructorVarArgs(['int32'.toJS, jsIntArray, jsArrayFrom(shape)]);
break;
// Uint8 to Float32
case 'uint8-float32':
final floatArray = [];
for (var i = 0; i < dataLength; i++) {
final val = jsData.getProperty(i.toString().toJS) as JSNumber;
floatArray.add(val.toDartDouble);
}
final jsFloatArray = _convertToTypedArray(floatArray, 'Float32Array');
newTensor = tensorConstructor.callAsConstructorVarArgs(['float32'.toJS, jsFloatArray, jsArrayFrom(shape)]);
break;
// Boolean to Int8/Uint8
case 'bool-int8':
case 'bool-uint8':
// Boolean values are already stored as 0/1 in a Uint8Array
// Just create a new Uint8Array with the same values
final byteArray = [];
for (var i = 0; i < dataLength; i++) {
final val = jsData.getProperty(i.toString().toJS) as JSNumber;
byteArray.add(val.toDartInt != 0 ? 1 : 0);
}
final jsByteArray = _convertToTypedArray(byteArray, 'Uint8Array');
newTensor = tensorConstructor.callAsConstructorVarArgs(['uint8'.toJS, jsByteArray, jsArrayFrom(shape)]);
break;
// Int8/Uint8 to Boolean
case 'int8-bool':
case 'uint8-bool':
// Convert to boolean representation (non-zero values become true)
final boolArray = [];
for (var i = 0; i < dataLength; i++) {
final val = jsData.getProperty(i.toString().toJS) as JSNumber;
boolArray.add(val.toDartInt != 0 ? 1 : 0);
}
final jsBoolArray = _convertToTypedArray(boolArray, 'Uint8Array');
newTensor = tensorConstructor.callAsConstructorVarArgs(['bool'.toJS, jsBoolArray, jsArrayFrom(shape)]);
break;
// Same type conversion (no-op)
case 'float32-float32':
case 'int32-int32':
case 'int64-int64':
case 'uint8-uint8':
case 'int8-int8':
case 'bool-bool':
case 'string-string':
// Clone the original tensor with the same data
final newData = tensor.getProperty('data'.toJS);
newTensor = tensorConstructor.callAsConstructorVarArgs([sourceType.toJS, newData, jsArrayFrom(shape)]);
break;
default:
throw PlatformException(
code: "CONVERSION_ERROR",
message: "Conversion from $sourceType to $targetType is not supported",
details: null,
);
}
// Generate a unique ID for this tensor
final newValueId = '${DateTime.now().millisecondsSinceEpoch}_${math.Random().nextInt(10000)}';
// Store the tensor
_ortValues[newValueId] = newTensor;
// Return the tensor information
return {'valueId': newValueId, 'dataType': targetType, 'shape': shape};
} catch (e) {
if (e is PlatformException) {
rethrow;
}
throw PlatformException(code: "CONVERSION_ERROR", message: "Failed to convert OrtValue: $e", details: null);
}
}