Эффекты изображения с вращением и масштабированием для увеличения с помощью GLSurfaceView Android

Я разрабатывал приложение, чтобы применять эффекты / вращение / пинч для увеличения или уменьшения масштаба изображения. Я скачал демонстрационное приложение с https://github.com/Grishu/ImageEffects.

Это работает хорошо, теперь мои проблемы / вопросы как ниже:

  1. Примените несколько эффектов к изображениям со значением изменения прогресса (например, сначала примените эффект яркости, а в результате этого примените другой эффект, скажем, "контраст".)

    - проблема: в коде эффект всегда применяется к исходному изображению. Поэтому измените код, чтобы применить эффект к конечному изображению, например,

    if(isApplyEffectOnOriginalImage){//call first time only         
        mEffect.apply(mTextures[0], mImageWidth, mImageHeight, mTextures[1]);
    }else{
        mEffect.apply(mTextures[1], mImageWidth, mImageHeight, mTextures[1]);
    }
    

    Теперь, если применить эффект яркости к изменению прогресса в первый раз, он работает нормально. Но если я применяю тот же или другой (контрастный) эффект, теперь я думаю, что эффект изменения прогресса применяется к mTextures[1] и результирующему набору в mTextures[1], поэтому возможно ли создать временные mTextures[2] для хранения mTextures [ 1] изначально, и когда пользователь изменяет значение прогресса, применяет эффект к mTextures[2] и устанавливает результат для mTextures[1], как это происходит в условии if.

  2. Как применить пинч для увеличения изображения

  3. Проблема с поворотом: я поворачивал изображение на 90 градусов по часовой стрелке, просто установив значения (90,180,270 и т. Д.), Но проблема заключается в том, что при повороте изображения от 90 до 180 изображение отображается неправильно. увидеть

А) 0 угловое изображение

0 угол изображения

Б) 90 угловое изображение

90-градусное изображение

В) 180 угловое изображение

180-градусное изображение

1 ответ

Я изменил демонстрационный проект Гришу: вот запись экрана, а затем некоторые пояснения:

(Изображение повернуто, применено три эффекта - горизонтальный, перекрестный, рыбий глаз)

1) Для применения эффекта на результат, ваше предложение работает нормально. Я не очень понимаю, что вы имеете в виду под "эффектом изменения прогресса". Вы хотите настроить параметры эффекта?

2) Чтобы иметь жесты, вы должны расширить GLSurfaceView и реализовать GestureDetector.OnGestureListener и / или ScaleGestureDetector.OnScaleGestureListener в зависимости от ваших потребностей. См. TouchGLView здесь: источник или фрагмент ниже:

private class TouchGLView extends GLSurfaceView
        implements GestureDetector.OnGestureListener,
        ScaleGestureDetector.OnScaleGestureListener {
    private TextureRenderer mRenderer;
    private GestureDetector mTapDetector;
    private ScaleGestureDetector mScaleDetector;
    private float mLastSpan = 0;

    TouchGLView(Context c) {
        super(c);
        // Use Android's built-in gesture detectors to detect
        // which touch event the user is doing.
        mTapDetector = new GestureDetector(c, this);
        mTapDetector.setIsLongpressEnabled(false);
        mScaleDetector = new ScaleGestureDetector(c, this);

        // Create an OpenGL ES 2.0 context.
        setEGLContextClientVersion(2);
        mRenderer = new TextureRenderer(c);
        setRenderer(mRenderer);
    }
    @Override
    public boolean onTouchEvent(final MotionEvent e) {
        // Forward touch events to the gesture detectors.
        mScaleDetector.onTouchEvent(e);
        mTapDetector.onTouchEvent(e);
        return true;
    }
    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2,
                            final float dx, final float dy) {
        // Forward the drag event to the renderer.
        queueEvent(new Runnable() {
            public void run() {
                mRenderer.drag(dx, dy);
            }});
        return true;
    }
    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        // Forward the scale event to the renderer.
        final float amount = detector.getCurrentSpan() - mLastSpan;
        queueEvent(new Runnable() {
            public void run() {
                mRenderer.zoom(amount);
            }});
        mLastSpan = detector.getCurrentSpan();
        return true;
    }
    ...
}

3) Вы можете вращать изображение, изменяя координаты вершины и принимая во внимание области просмотра. Также вы можете применять разные повороты. Вы можете вращать (и масштабировать) само представление (координаты вершин) (что не влияет на исходный буфер текстур) или вращать пиксели в буфере текстур (что легко на 90°, 180° и т. Д.), А затем обновлять координаты вершины, соответствующие ширине / высоте нового изображения.

Вот пример для работы с координатами вершины:

private void computeOutputVertices() {
    if (mPosVertices != null) {
        float imgAspectRatio = mTexWidth / (float)mTexHeight;
        float viewAspectRatio = mViewWidth / (float)mViewHeight;
        float x0, y0, x1, y1;
        // Set initial vertex coords based in texture aspect
        if (imgAspectRatio > 1.0f) {
            x0 = -1.0f ;
            y0 = -1.0f / imgAspectRatio;
            x1 = 1.0f ;
            y1 = 1.0f / imgAspectRatio;
        } else {
            x0 = -1.0f *imgAspectRatio;
            y0 = -1.0f;
            x1 = 1.0f *imgAspectRatio;
            y1 = 1.0f;
        }
        float[] coords = new float[] { x0, y0, x1, y0, x0, y1, x1, y1 };
        // Scale coordinates with mZoom
        for (int i = 0; i < 8; i++) {
            coords[i] *= mZoom;
        }
        // Rotate coordinates with mRot
        float cosa = (float)Math.cos(mRot);
        float sina = (float)Math.sin(mRot);
        float x,y;
        for (int i = 0; i < 8; i+=2) {
            x = coords[i]; y = coords[i+1];
            coords[i]   = cosa*x-sina*y;
            coords[i+1] = sina*x+cosa*y;
        }
        // Finally scale again to match screen aspect
        if (viewAspectRatio > 1.0f) {
            for (int i = 0; i < 8; i+=2) {
                coords[i] = coords[i]/viewAspectRatio;
            }
        } else {
            for (int i = 1; i < 8; i+=2) {
                coords[i] = coords[i]*viewAspectRatio;
            }
        }
        mPosVertices.put(coords).position(0);
    }
}

Я предлагаю вам погрузиться в матрицы OpenGL и выполнить все эти преобразования, используя их.

Я модифицировал TextureRenderer класс для реализации GLSurfaceView.Rendererи изменил renderMode на RENDERMODE_CONTINUOUSLY,

Наконец, источник для модифицированного демо здесь.

Другие вопросы по тегам