Есть ли какой-нибудь способ выполнить квантование изображения безопасно и без сортировки?

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

Вопрос

В настоящее время я использую Brendan Tompkins ImageQuantization dll.http://codebetter.com/blogs/brendan.tompkins/archive/2007/06/14/gif-image-color-quantizer-now-with-safe-goodness.aspx

Но он не пользуется средним доверием в asp.net.

Кто-нибудь знает о библиотеке квантования изображений, которая работает со средним уровнем доверия?

Обновить Меня не волнует, что решение будет медленным.Мне просто нужно что-то, что работает.

Это было полезно?

Решение

Вы должны быть в состоянии заменить код, использующий Marshal, явным чтением базового потока через что-то вроде BinaryReader.Это может быть медленнее, поскольку вы должны полностью считывать поток в свою управляемую память или искать в нем, а не полагаться на то, что копия, уже находящаяся в неуправляемой памяти, будет быстро доступна, но, по сути, это ваш единственный вариант.

Вы просто не можете проникнуть в неуправляемую память из контекста среднего доверия, даже если выполняете только операции чтения.

Посмотрев на связанный код, я понял, почему вам не разрешено делать подобные вещи.Для начала, он игнорирует 64/32-битный аспект IntPtr!

Базовый класс BitmapData, который он использует, полностью основан на наличии неограниченного доступа на чтение к произвольной памяти, этого никогда не происходит при среднем доверии.
Потребуется значительное переписывание его базовой функциональности, чтобы либо использовать BitMap напрямую (с медленными вызовами GetPixel), либо считывать данные напрямую через обычные потоковые API, помещая их в массив (ы), а затем анализировать самостоятельно.Ни то, ни другое вряд ли будет приятным.Первый будет намного медленнее (я бы ожидал порядка величины из-за высоких накладных расходов на считывание пикселя), более поздний менее медленный (хотя все еще медленнее), но требует гораздо больших усилий с точки зрения перезаписи низкоуровневого анализа данных изображения.

Вот приблизительное руководство по тому, что вам нужно изменить на основе текущего кода:

из 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...
    }
}

вам нужно было бы сделать примерно то же самое в других функциях.Это устраняет любую необходимость в Color32, класс Bitmap справится со всем этим за вас.

Bitmap.SetPixel() разберемся со вторым проходом.Обратите внимание, что это самый простой способ переноса данных, но абсолютно не самый быстрый способ сделать это в среде среднего уровня доверия.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top