Мне нужно записать число с плавающей точкой с прямым порядком байтов в файле C # - PullRequest
2 голосов
/ 13 ноября 2010

У меня есть формат файла, который я пытаюсь записать в C #. Формат кодирует целочисленные значения цвета RGB в виде числа с плавающей запятой. Он также хранит значения как big-endian. Я нашел пример того, что я пытаюсь сделать, написанный на php, здесь: http://www.colourlovers.com/ase.phps

Я могу легко преобразовать порядок байтов. Я знаю, что этот код очень многословен, но я просто использую его для наблюдения за заменой битов во время поиска неисправностей.

    private uint SwapEndian(uint host) {
        uint ReturnValue;
        uint FirstHalf;
        uint LastHalf;
        FirstHalf = (host & 0xFFFF0000);
        FirstHalf = (FirstHalf >> 16);
        LastHalf = (host & 0x0000FFFF);
        LastHalf = (LastHalf << 16);
        ReturnValue = (FirstHalf | LastHalf);
        return ReturnValue;

    }   

C # не позволяет мне выполнять сдвиги битов на поплавках. Преобразование в int или uint для вызова моего метода SwapEndian, описанного выше, приводит к потере информации о кодировке, требуемой форматом файла.

Итак, как бы вы взяли число с плавающей запятой и изменили его порядковый номер, не теряя данные экспоненты?

Ответы [ 2 ]

4 голосов
/ 13 ноября 2010

Вы можете просто использовать:

var bytes = BitConverter.GetBytes(floatVal);

И инвертировать массив (при условии, что процессор имеет младший порядок, который вы проверяете), или просто получить доступ к массиву в нужном вам порядке.

Существует также способ сделать это с помощью небезопасного кода, рассматривая float * как байт *, чтобы вы могли получить байты в нужном вам порядке.

1 голос
/ 13 ноября 2010

Меня немного смущает вопрос о том, почему вы сдвигаете на 16 бит, а не на 8. Теперь я понимаю, почему вам нужен RGB в качестве числа с плавающей запятой (они обычно составляют 1 байт каждый). Но в любом случае.

вы можете использовать 'поддельный' союз, чтобы рассматривать float как uint

[StructLayout(LayoutKind.Explicit)]
public struct FloatIntUnion
{
    [FieldOffset(0)]        
    public  float f;
    [FieldOffset(0)]
    public uint i;
}

это позволяет вам присвоить float и затем обеспечить выполнение побитовых операций над частью uint объединения, а затем снова использовать float в качестве конечного значения.

Однако я бы, наверное, просто использовал:

var bytes = BitConverter.GetBytes (RGB);
if (BitConverter.IsLittleEndian)
    Array.Reverse (bytes);
return bytes;

до тех пор, пока производительность не стала проблемой (из-за ЭТОГО метода (сначала прочитайте профиль)).

...