Есть ли способ сделать квантование изображения безопасно и без маршаллинга?

2

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

Но он не работает в средстве доверия в asp.net.

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

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

Теги:
image
medium-trust

1 ответ

3
Лучший ответ

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

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

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

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

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

из 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 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() будет иметь дело со вторым проходом. Обратите внимание, что это самый простой способ переносить вещи, но совсем не самый быстрый способ сделать это в среде среднего доверия.

  • 0
    Любые звонки к маршалу потерпят неудачу при среднем доверии. :-(
  • 0
    ну что-нибудь с требованием ссылки, требующей неуправляемого кода, который все из памяти. Разве вы не можете прочитать исходное растровое изображение напрямую?
Показать ещё 13 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню