I have experience retrieving AX 4.0 graphic images from SQL, though I have never used them in a report.
The encoding of Binary data into an SQL Image field changed during an AX 4.0 Service Pack, and I can no longer remember which one. So, depending on the AX version in place when the image was saved, the format may vary.
If you view the SQL Image field using SQL Server Management Studio (for example), the following structure exists for SP2+.
0x 07 2B L1 L2 L3 L4 FF D8 ..
In this case, the 2B in the 2nd byte indicates the newer format (SP2+). Immediately following that are 4 bytes that represent the length (L1-L4 in little endian) of the stored Binary data, starting immediately after that (FF D8 in this case, which is how all JPG files start). The length represented by L1-L4 will be 7 less than the DATALENGTH(..) of your raw Image field. I'm not sure if the first byte being 07 is a coincidence or not.
The other format I have seen looks like this.
0x XX FD YY L1 L2 L3 L4 FF D8 ..
In this case, the FD in the 2nd byte indicates the older format. Skipping one byte, the length is again found as L1-L4, and the Binary data starts one byte later (seen here as FF D8 again, for JPG as an example).
it appears to me that there's an extra byte at the end of the Binary data that is not actually part of the image. Perhaps it's a checksum or single byte terminator used by AX, but it does not belong in your graphic Binary data. For example, in one of my stored images, the DATALENGTH(image) is 8330 or 0x208A, and the data shows 0x83 0x20 0x00 0x00 or 0x2083, a difference of 7. Skipping the first 6 bytes (it started 0x 07 2B so it's the new format), that leaves an extra at the end.
Be careful of your substring usage. In .NET, substring is 0 based, meaning that substring(.., 7) in fact skips a full 7 characters (NOT bytes), Substring("abc", 1, 1) returns "b" not "a". And if you're using Unicode string variables, then Substring(.., 7) could in fact skip 14 bytes.
You probably want to skip 6 bytes and start at the 7th position, discarding the last byte. You can sanity check your code by saving a JPG image for testing and validating during debugging that your Binary result starts with FF D8 and ends with FF D9, since all JPG files start and end this way. You can also code your logic to check the 2nd byte position for the 2B or FD indicator and adjust the starting position of the Binary data accordingly, in case you have a mixture of old and new Image data.
Good luck.