2011-01-12 4 views
1

Кто-нибудь знает об эффективном способе сглаживания 2-мерного массива (без зубьев) на C# до 1d и обратно. Я знаю, что в конце C# должен ухватиться за него как массив 1d, я бы просто хотел получить дескриптор массива 1d, если это вообще возможно.Convert byte [,] to byte []

Причина, по которой я хотел бы сделать это, заключается в том, что я хотел бы иметь возможность в управляемом коде иметь его как 2d, иногда я хотел бы передать его как 1d в неуправляемый dll импортированный код (оптимизированный сборка в цифровой обработке изображений является хорошим примером).

+0

Зачем вам это нужно? – Oded

+2

«Я знаю, что в конце концов C# должен держаться за него как 1-й массив». Почему вы так думаете? Это не обязательно так. – jason

+1

@ Джейсон: На ​​самом деле следующая строка в спецификации, по-видимому, предполагает, что вы _can_ предположите, что базовое представление представляет собой линейный массив. Из §18.6: «Учитывая способ хранения массивов, мы можем рассматривать массив любого измерения, как если бы он был линейным». Однако, обратите внимание, что это не обязательно должно быть, но очень приятно, что это правда. – jason

ответ

3

Вы не можете получить управляемый массив byte[] из byte[,] без его копирования (не то, что я знаю, во всяком случае).

Если вы знакомы с unsafe код, который вы можете исправить byte* на массиве, и я считаю, что должно работать:

fixed (byte* ptr = array) 
{ 
    for (int i = 0; i < N; ++i) 
    { 
     byte b = ptr[i]; 
     // Do whatever you need. 
    } 
} 
+0

Если это работает, это именно то, что мне нужно – dko

+0

@dko: Это действительно работает. См. Мой комментарий к ответу Джона Скита: http://stackoverflow.com/questions/4674394/convert-byte-to-byte/4674427#4674427. – jason

+0

@Jason Знаете ли вы, если он хранится в строчном порядке или в главном порядке столбца? AKA byte [5,5] temp, индексирование темпа [0,3] будет 3-м байтом или 15-м байтом? – dko

3

Для перехода от 2D индекса к индексу 1D:

int i = y * width + x; 

И обратно:

int x = i % width; 
int y = i/width; 

Тогда проще всего просто перебрать массиве, копирования значений по одному.

+0

Это далеко не самый эффективный способ копирования данных. –

+1

@ Jon Skeet: На самом деле я не видел Buffer.BlockCopy, поэтому я не оценил его производительность. Я возьму ваше слово, что это быстрее. :) Было бы интересно увидеть некоторые показатели производительности, чтобы увидеть, в чем разница. Я запомню этот вопрос, так как этот вопрос возникает много (я уверен, что этот вопрос на самом деле является дубликатом, просто не может найти другого сейчас, это хорошее совпадение). –

+0

Да, это далеко не то, что я имел в виду как эффективный способ. – dko

11

Ну, сам объект не является byte[], хотя он сам имеет данные в одном непрерывном блоке памяти. Не забывайте, что массив знает свои ряды и длины и т. Д.

Однако вы можете использовать Buffer.BlockCopy, чтобы скопировать массив быстро. Например:

byte[,] source = new byte[5,5]; 
byte[] dest = new byte[source.Length]; 
Buffer.BlockCopy(source, 0, dest, 0, source.Length); 

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

+0

Соответствующая строка из спецификации из §18.6: «Учитывая способ хранения массивов, мы можем рассматривать массив любого измерения, как если бы он был линейным». В частности, можно сказать 'byte [] destination = new byte [source.Length]; unsafe {fixed (byte * p = source) {for (int i = 0; i jason

+0

Кроме того, очевидно, что лучше сказать 'byte [] dest = новый байт [source.Length];' и 'Buffer.BlockCopy (source, 0, dest, 0, source.Length * sizeof (byte));' – jason

+0

@ Джейсон: Да, это правда, хотя я бы не стал беспокоиться о 'sizeof (byte)' ... возможно, для чего-то менее тривиального, хотя :) –

0
var myFlattenedByteArray = my2DByteArray.SelectMany(b=>b).ToArray(); 

Это будет возвращать каждый элемент каждой подрешетки байтового массива 2D в подэлемент-элемент: myFlattenedByteArray [1] == my2DByteArray [0] [1]. Есть, вероятно, более эффективные или эффективные решения (в частности, slupring из Enumerable, производимого SelectMany, в его собственный массив), но это однострочный.