Est-il possible de le faire en toute sécurité et l'image Quantification sans sérialisation?

StackOverflow https://stackoverflow.com/questions/1099655

Question

J'utilise actuellement dll Brendan Tompkins ImageQuantization.

Était-ce utile?

La solution

Vous devriez être en mesure de remplacer le code à l'aide Marshal à la lecture explicite du flux sous-jacent par quelque chose comme BinaryReader. Cela peut être plus lent puisque vous devez lire le flux entièrement dans votre mémoire gérée ou chercher dans plutôt que de compter sur la copie déjà en mémoire non géré étant rapidement accessible, mais est fondamentalement votre seule option.

Vous ne pouvez pas vous spéléo dans la mémoire non géré à partir d'un contexte de confiance moyen, même si seulement effectuer des opérations de lecture.

Après avoir regardé le code lié il y a une raison que vous n'êtes pas autorisé à faire ce genre de chose. Pour commencer, il est en ignorant l'aspect 64 / 32bit du IntPtr!

La classe BitmapData sous-jacente qu'il utilise est tout à fait fondé sur l'accès de lecture sans entraves à la mémoire arbitraire, ce qui se passe jamais sous la confiance moyenne.
Une réécriture importante de sa fonctionnalité de base sera nécessaire d'utiliser soit directement de BitMap (avec les appels getPixel lents) ou lire les données directement via apis flux conventionnels, laissant tomber dans un tableau (s), puis analyser vous-même. Aucun de ceux-ci sont susceptibles d'être agréable. Le premier sera beaucoup plus lent (j'attendre ordre de grandeur en raison de la surcharge élevée par lecture de pixels), le plus tard moins lent (mais encore plus lent), mais a beaucoup plus d'efforts associés en termes de réécriture l'analyse syntaxique de bas niveau des données d'image .

Voici une idée approximative de ce que vous devez changer en fonction du code actuel:

de Quantizer.cs

public Bitmap Quantize(Image source)
{
    // Get the size of the source image
    int height = source.Height;
    int width = source.Width;
    // And construct a rectangle from these dimensions
    Rectangle bounds = new Rectangle(0, 0, width, height);
    // First off take a 32bpp copy of the image
    Bitmap copy = new Bitmap(width, height, PixelFormat.Format32bppArgb);
    // And construct an 8bpp version
    Bitmap output = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
    // Now lock the bitmap into memory
    using (Graphics g = Graphics.FromImage(copy))
    {
        g.PageUnit = GraphicsUnit.Pixel;
        // Draw the source image onto the copy bitmap,
        // which will effect a widening as appropriate.
            g.DrawImage(source, bounds);
    }

    //!! BEGIN CHANGES - no locking here
    //!! simply use copy not a pointer to it
    //!! you could also simply write directly to a buffer then make the final immage in one go but I don't bother here

    // Call the FirstPass function if not a single pass algorithm.
    // For something like an octree quantizer, this will run through
    // all image pixels, build a data structure, and create a palette.
    if (!_singlePass)
        FirstPass(copy, width, height);

    // Then set the color palette on the output bitmap. I'm passing in the current palette 
    // as there's no way to construct a new, empty palette.
    output.Palette = GetPalette(output.Palette);
    // Then call the second pass which actually does the conversion
    SecondPass(copy, output, width, height, bounds);
    //!! END CHANGES
    // Last but not least, return the output bitmap
    return output;
}

//!! Completely changed, note that I assume all the code is changed to just use Color rather than Color32
protected  virtual void FirstPass(Bitmap source, int width, int height)
{
    // Loop through each row
    for (int row = 0; row < height; row++)
    {
        // And loop through each column
        for (int col = 0; col < width; col++)
        {            
            InitialQuantizePixel(source.GetPixel(col, row)); 
        }   // Now I have the pixel, call the FirstPassQuantize function...
    }
}

vous devez faire à peu près la même chose dans les autres fonctions. Cela supprime tout besoin de Color32, la classe Bitmap traitera tout cela pour vous.

Bitmap.SetPixel() traitera de la deuxième passe. Notez que ceci est la meilleure façon de choses portuaires, mais absolument pas le meilleur moyen de le faire dans un environnement de confiance moyen.

scroll top