11
votes

Comment remodeler un tableau en C #

J'ai une gamme 3D d'octets en C # que j'ai lu depuis un bitmap: xxx pré>

Quelle est la manière la plus facile et la plus performante de remodeler ce tableau en 2D (linéaire) forme? p> xxx pré>

En d'autres termes, je veux conserver le nombre de canaux (fonctionnalités) mais dans une forme linéaire (plutôt qu'une forme carrée) p>

let Moi essaye d'illustrer l'entrée et la sortie souhaitée: p>

entrée: p>

|(r1,g1,b1)    (r2,g2,b2)    (r3,g3,b3)    (r4,g4,b4)    (r5,g5,b5)    (r6,g6,b6) ...|


0 commentaires

3 Réponses :


9
votes

Cela semble fonctionner bien, car le tableau est déjà dans la bonne forme en mémoire : xxx


pour les personnes intéressées: comme pour quoi Faites si vous voulez vraiment transposer un tableau 2D en 1D: xxx

Ceci devrait tirer parti de la mise en cache dans la CPU. J'ai seulement effectué des tests limités à ce sujet - cela pourrait toujours être lent. Essayez de le modifier si c'est.
Vous pouvez (un peu de manière non trivialement) l'étendre à un tableau 3D.


8 commentaires

Ouf, je ne suis pas sûr que vous puissiez obtenir des problèmes avec la mise en page de la mémoire. Les matrices de garantie de spécification sont-elles stockées dans la mémoire mappée séquentielle?


@Johannes: Ils sont Dans l'ordre majeur de la ligne , mais je pense que la colonne-major fonctionnerait également. Vous ne vous souciez pas du rembourrage spécifique à la plate-forme car blockcopy devrait en prendre soin de toute façon.


@Mehrdad, alors cela signifie-t-il que je vais obtenir cela dans le résultat?: [Couche 1ère 1ère ligne] [2ème rangée 1ère couche] ... [1er rangée 2ème couche] [2ème rangée 2ème couche] ... ?


@Mehrdad: Bon à savoir, NEVR a travaillé avec BlockCopy, mais heureux cela gère cela.


@Valipour: dépend de ce que vous entendez par "rangée". Dans l'exemple de arr [A, B, C] , C est la ligne, pas a . Et dans ce cas, vous passerez à travers la ligne avant de passer à travers la colonne suivante.


@Mehrdad: S'il vous plaît voir mes nouvelles notes dans la question


@Valipour: whoops mon mauvais - c'était une faute de frappe; Bien sûr, B est la ligne. Laissez-moi reformuler: la foulée la plus petite se produit lorsque vous incrémentez C . Je pense que ma réponse fait ce que vous attendez (essayez-le!), Mais je pense que j'ai mal compris ce que vous avez écrit dans votre commentaire - j'ai lu "calque" comme "colonne", donc je pensais que cela ne fait pas ce que vous attendiez ; Cependant, ça fait.


Y a-t-il un moyen pas pour copier le tableau?



3
votes

tampon.blockcopie code> le fera. Au moins, cela fonctionne dans ce test simple.

byte[, ,] src = new byte[10, 10, 3];
byte[,] dest = new byte[100, 3];

List<byte> srcList = new List<byte>();
Random rnd = new Random();
for (int i = 0; i < 10; ++i)
{
    for (int j = 0; j < 10; ++j)
    {
        for (int k = 0; k < 3; ++k)
        {
            byte b = (byte)rnd.Next();
            src[i, j, k] = b;
            srcList.Add(b);
        }
    }
}

Buffer.BlockCopy(src, 0, dest, 0, 300);

List<byte> destList = new List<byte>();
for (int i = 0; i < 100; ++i)
{
    for (int j = 0; j < 3; ++j)
    {
        destList.Add(dest[i, j]);
    }
}

// See if they're in the same order
for (int i = 0; i < srcList.Count; ++i)
{
    Console.WriteLine("{0,3:N0} - {1,3:N0}", srcList[i], destList[i]);
    if (srcList[i] != destList[i])
    {
        Console.WriteLine("ERROR!");
    }
}


2 commentaires

Pourquoi ne serait-il pas blockcopy prendre soin des problèmes de rembourrage? Les problèmes de rembourrage doivent être transparents au programmeur, c'est donc la la responsabilité de blockcopy pour le garder de cette façon. (Pensez-y: sinon, cela corrompre votre mémoire!) Il y a aucune raison pour éviter blockcopy wharse.


Pour d'autres, lisez cette réponse, prenez note que le quatrième paramètre à tampon.BlockCopy est le nombre de octets pour copier non la longueur ou le nombre d'éléments à copier. Dans cet exemple, car nous copions des octets, les chiffres sont identiques, mais si votre tampon était un autre type de données comme flottant, n'oubliez pas de multiplier par tailleOf (flotteur) pour copier le nombre correct d'éléments. i.e. tampon.blockcopie (SRCFLOATARRAY, 0, DESTFLOATARRAY, 0, TAILLEOF (FLOAT) * 300);



1
votes