Небезопасный На Пиксельный доступ, доступ на 30 мс для 1 756 000 пикселей

Когда вы создаете пользовательское правило, вы также должны правильно его объявить. Поскольку ваше пользовательское правило зависит от аргумента, вы должны передать аргумент при объявлении правила

rules: {
   country: {
       required: true,
       requiredcountry: "your argument here"  // <- declare the custom rule
   }
}
7
задан David Anderson 23 May 2009 в 15:43
поделиться

5 ответов

Небезопасный подход с использованием целых чисел вместо пикселей и одиночного цикла:

private static Bitmap GetInvalidFrame(Bitmap oldFrame, Bitmap newFrame)
{
    if (oldFrame.Size != newFrame.Size)
    {
        throw new ArgumentException();
    }
    Bitmap result = new Bitmap(oldFrame.Width, oldFrame.Height, oldFrame.PixelFormat);

    Rectangle lockArea = new Rectangle(Point.Empty, oldFrame.Size);
    PixelFormat format = PixelFormat.Format32bppArgb;
    BitmapData oldData = oldFrame.LockBits(lockArea, ImageLockMode.ReadOnly, format);
    BitmapData newData = newFrame.LockBits(lockArea, ImageLockMode.ReadOnly, format);
    BitmapData resultData = result.LockBits(lockArea, ImageLockMode.WriteOnly, format);

    int len = resultData.Height * Math.Abs(resultData.Stride) / 4;

    unsafe
    {
        int* pOld = (int*)oldData.Scan0;
        int* pNew = (int*)newData.Scan0;
        int* pResult = (int*)resultData.Scan0;

        for (int i = 0; i < len; i++)
        {
            int oldValue = *pOld++;
            int newValue = *pNew++;
            *pResult++ = oldValue != newValue ? newValue : 0 /* replace with 0xff << 24 if you need non-transparent black pixel */;
            // *pResult++ = *pOld++ ^ *pNew++; // if you can use XORs.
        }
    }

    oldFrame.UnlockBits(oldData);
    newFrame.UnlockBits(newData);
    result.UnlockBits(resultData);

    return result;
}

Я думаю, вы действительно можете использовать здесь кадры с XOR, и я надеюсь, что это может улучшить производительность с обеих сторон.

    private static void XorFrames(Bitmap leftFrame, Bitmap rightFrame)
    {
        if (leftFrame.Size != rightFrame.Size)
        {
            throw new ArgumentException();
        }

        Rectangle lockArea = new Rectangle(Point.Empty, leftFrame.Size);
        PixelFormat format = PixelFormat.Format32bppArgb;
        BitmapData leftData = leftFrame.LockBits(lockArea, ImageLockMode.ReadWrite, format);
        BitmapData rightData = rightFrame.LockBits(lockArea, ImageLockMode.ReadOnly, format);

        int len = leftData.Height * Math.Abs(rightData.Stride) / 4;

        unsafe
        {
            int* pLeft = (int*)leftData.Scan0;
            int* pRight = (int*)rightData.Scan0;

            for (int i = 0; i < len; i++)
            {
                *pLeft++ ^= *pRight++;
            }
        }

        leftFrame.UnlockBits(leftData);
        rightFrame.UnlockBits(rightData);
    }

] Вы можете использовать эту процедуру с обеих сторон следующим образом:
На стороне сервера вам необходимо оценить разницу между старым и новым кадром, отправить его клиенту и заменить старый кадр новым. Код сервера должен выглядеть примерно так:

  XorFrames(oldFrame, newFrame); // oldFrame ^= newFrame
  Send(oldFrame); // send XOR of two frames
  oldFrame = newFrame;

На стороне клиента вам необходимо обновить текущий кадр с помощью кадра xor, полученного с сервера:

  XorFrames((Bitmap)uxSurface.Image, e.Frame);
16
ответ дан 6 December 2019 в 07:52
поделиться

Удалось отрезать около 60 мс. Думаю, для этого потребуется графический процессор. Я не вижу никакого решения для этого с использованием ЦП, даже если сравнивать более одного байта / пикселя за раз, если только кто-то не может создать образец кода, чтобы показать мне обратное. По-прежнему составляет около 200–260 мс, что слишком медленно для 30 кадров в секунду.

private static BitmapData m_OldData;
private static BitmapData m_NewData;
private static unsafe Byte* m_OldPBase;
private static unsafe Byte* m_NewPBase;
private static unsafe Pixel* m_OldPixel;
private static unsafe Pixel* m_NewPixel;
private static Int32 m_X;
private static Int32 m_Y;
private static Stopwatch m_Watch = new Stopwatch();
private static GraphicsUnit m_GraphicsUnit = GraphicsUnit.Pixel;
private static RectangleF m_OldBoundsF;
private static RectangleF m_NewBoundsF;
private static Rectangle m_OldBounds;
private static Rectangle m_NewBounds;
private static Pixel m_TransparentPixel = new Pixel() { Alpha = 0x00, Red = 0, Green = 0, Blue = 0 };

private Bitmap GetInvalidFrame(Bitmap frame) {
    if (m_FrameBackBuffer == null) {
        return frame;
    }

    m_Watch.Start();

    unsafe {
        m_OldBoundsF = m_FrameBackBuffer.GetBounds(ref m_GraphicsUnit);
        m_OldBounds = new Rectangle((Int32)m_OldBoundsF.X, (Int32)m_OldBoundsF.Y, (Int32)m_OldBoundsF.Width, (Int32)m_OldBoundsF.Height);
        m_OldData = m_FrameBackBuffer.LockBits(m_OldBounds, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

        m_NewBoundsF = m_FrameBackBuffer.GetBounds(ref m_GraphicsUnit);
        m_NewBounds = new Rectangle((Int32)m_NewBoundsF.X, (Int32)m_NewBoundsF.Y, (Int32)m_NewBoundsF.Width, (Int32)m_NewBoundsF.Height);
        m_NewData = frame.LockBits(m_NewBounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

        m_OldPBase = (Byte*)m_OldData.Scan0.ToPointer();
        m_NewPBase = (Byte*)m_NewData.Scan0.ToPointer();

        do {
            for (m_X = 0; m_X < frame.Width; m_X++) {

                m_OldPixel = (Pixel*)(m_OldPBase + m_Y * m_OldData.Stride + 1 + m_X * sizeof(Pixel));
                m_NewPixel = (Pixel*)(m_NewPBase + m_Y * m_NewData.Stride + 1 + m_X * sizeof(Pixel));

                if (m_OldPixel->Alpha == m_NewPixel->Alpha // AccessViolationException accessing Property in get {}
                    || m_OldPixel->Red == m_NewPixel->Red
                    || m_OldPixel->Green == m_NewPixel->Green
                    || m_OldPixel->Blue == m_NewPixel->Blue) {

                    // Set the transparent pixel
                    *m_NewPixel = m_TransparentPixel;
                }
            }

            m_Y++; //Debug.WriteLine(String.Format("X: {0}, Y: {1}", m_X, m_Y));
        } while (m_Y < frame.Height);
    }

    m_Y = 0;

    m_Watch.Stop();
    Debug.WriteLine("Time elapsed: " + m_Watch.ElapsedMilliseconds.ToString());
    m_Watch.Reset();

    return frame;
}
0
ответ дан 6 December 2019 в 07:52
поделиться

Здесь: При использовании графического процессора с C # упоминаются некоторые библиотеки для использования графического процессора из C #.

3
ответ дан 6 December 2019 в 07:52
поделиться

Да, вы можете сделать это, используя небезопасный код.

BitmapData d = l.LockBits(new Rectangle(0, 0, l.Width, l.Height), ImageLockMode.ReadOnly,l.PixelFormat);
IntPtr scan = d.Scan0;
unsafe
{
    byte* p = (byte*)(void*)scan;
    //dostuff               
}

Проверьте http://www.codeproject.com/KB/GDI-plus /csharpgraphicfilters11.aspx для некоторых базовых примеров такого рода материалов. Мой код основан на этом.

Примечание: Одна из причин, по которой это будет намного быстрее, чем у вас, заключается в том, что вы сравниваете каждый канал отдельно, а не просто сравниваете весь байт с помощью одной операции. Точно так же изменение PixelAt, чтобы дать вам байт для облегчения этого, вероятно, даст вам улучшение.

3
ответ дан 6 December 2019 в 07:52
поделиться

Вместо проверки каждого пикселя вы можете просто выполнить базовое сравнение двух битовых карт в памяти. В C что-то вроде memcmp ().

Это позволит вам быстрее узнать, совпадают ли изображения или нет. Только когда вы знаете, что они разные, вам нужно прибегать к более дорогостоящему коду, который поможет вам определить, где они разные (если вам даже нужно это знать).

Я не специалист по C #, поэтому я не Не знаю, как легко получить доступ к необработанной памяти.

1
ответ дан 6 December 2019 в 07:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: