0

[Android] Chỉnh sửa ảnh với Effect

Android Effect

I. Giới thiệu

  • Bạn muốn xây dựng 1 bộ lọc ảnh chuyên nghiệp mà lại vô cùng đơn giản hãy sử dụng Effect.
  • Android Effect cho phép bạn áp dụng một loạt các hiệu ứng cho hình ảnh. Ví dụ, bạn có thể dễ dàng sửa chữa mắt đỏ, chuyển đổi hình ảnh sang màu sắc khác, điều chỉnh độ sáng, điều chỉnh độ bão hòa, xoay hình ảnh, hiệu ứng mắt cá ...
  • Effect thực hiện tất cả các xử lý hiệu ứng trên GPU để có được hiệu suất tối đa cùng với tốc độ vô cùng nhanh.

II. Hoạt động.

  • Để sử dụng Effect cần có 1 ràng buộc với GL_TEXTURE_2D texture image, chúng ta phải sử dụng 1 GLSurfaceView để thể hiện hình ảnh.

  • Hình ảnh được xử lý hiệu ứng thông qua EffectFactory, GLSurfaceView có vai trò thể hiện các hiệu ứng ảnh tương ứng.

  • EffectFactory cung cấp gần 30 hiệu ứng sẵn các hiệu ứng có thể thêm Parameter để tuy chỉnh thông số kỹ thuật, mỗi hiệu ứng chấp nhận các thông số Parameter đầu vào khác nhau tuy theo điều kiện.

    • EFFECT_AUTOFIX, EFFECT_BACKDROPPER, EFFECT_BITMAPOVERLAY, EFFECT_BLACKWHITE, EFFECT_BRIGHTNESS, EFFECT_CONTRAST, EFFECT_CROP, EFFECT_CROSSPROCESS, EFFECT_DOCUMENTARY, EFFECT_DUOTONE, EFFECT_FILLLIGHT, EFFECT_FISHEYE, EFFECT_FLIP, EFFECT_GRAIN, EFFECT_GRAYSCALE, EFFECT_LOMOISH, EFFECT_NEGATIVE, EFFECT_POSTERIZE, EFFECT_REDEYE,EFFECT_ROTATE, EFFECT_SATURATE, EFFECT_SEPIA, EFFECT_SHARPEN, EFFECT_STRAIGHTEN, EFFECT_TEMPERATURE, EFFECT_TINT, EFFECT_VIGNETTE
  • Hiệu ứng mới có thể được tạo ra từ sự kết hợp giữa nhiều hiệu ứng sẵn có. Các bạn có thể tự tạo hiệu ứng ảnh mang phong cách của mình

III. Các sử dụng

  • Tạo 1 GLSurfaceView và set trạng thái hình ảnh ban đầu cho nó.
     mEffectView = (GLSurfaceView) findViewById(R.id.effectsview);
     mEffectView.setEGLContextClientVersion(2);
     mEffectView.setRenderer(this);
     mEffectView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
  • Sử dụng 1 hàm EffectFactory để xử lý hình ảnh
    private void initEffect() {
		EffectFactory effectFactory = mEffectContext.getFactory();
		if (mEffect != null) {
			mEffect.release();
		}
		switch (mCurrentEffect) {
		case R.id.none:
			break;
		case R.id.autofix:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_AUTOFIX);
			mEffect.setParameter("scale", 0.5f);
			break;
		case R.id.bw:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_BLACKWHITE);
			mEffect.setParameter("black", .1f);
			mEffect.setParameter("white", .7f);
			break;
		case R.id.brightness:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_BRIGHTNESS);
			mEffect.setParameter("brightness", 2.0f);
			break;
		case R.id.contrast:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_CONTRAST);
			mEffect.setParameter("contrast", 1.4f);
			break;
		case R.id.crossprocess:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_CROSSPROCESS);
			break;
		case R.id.documentary:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_DOCUMENTARY);
			break;
		case R.id.duotone:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_DUOTONE);
			mEffect.setParameter("first_color", Color.YELLOW);
			mEffect.setParameter("second_color", Color.DKGRAY);
			break;
		case R.id.filllight:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_FILLLIGHT);
			mEffect.setParameter("strength", .8f);
			break;
		case R.id.fisheye:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_FISHEYE);
			mEffect.setParameter("scale", .5f);
			break;
		case R.id.flipvert:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_FLIP);
			mEffect.setParameter("vertical", true);
			break;
		case R.id.fliphor:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_FLIP);
			mEffect.setParameter("horizontal", true);
			break;
		case R.id.grain:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_GRAIN);
			mEffect.setParameter("strength", 1.0f);
			break;
		case R.id.grayscale:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_GRAYSCALE);
			break;
		case R.id.lomoish:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_LOMOISH);
			break;
		case R.id.negative:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_NEGATIVE);
			break;
		case R.id.posterize:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_POSTERIZE);
			break;
		case R.id.rotate:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_ROTATE);
			mEffect.setParameter("angle", 180);
			break;
		case R.id.saturate:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_SATURATE);
			mEffect.setParameter("scale", .5f);
			break;
		case R.id.sepia:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_SEPIA);
			break;
		case R.id.sharpen:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_SHARPEN);
			break;
		case R.id.temperature:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_TEMPERATURE);
			mEffect.setParameter("scale", .9f);
			break;
		case R.id.tint:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_TINT);
			mEffect.setParameter("tint", Color.MAGENTA);
			break;
		case R.id.vignette:
			mEffect = effectFactory.createEffect(EffectFactory.EFFECT_VIGNETTE);
			mEffect.setParameter("scale", .5f);
			break;
		default:
			break;
		}
	}
  • Hàm để xác nhận Effect
	private void applyEffect() {
		mEffect.apply(mTextures[0], mImageWidth, mImageHeight, mTextures[1]);
	}
  • Hàm load GLSurfaceView
    private void loadTextures() {
        mEffectContext = EffectContext.createWithCurrentGlContext();
		GLES20.glGenTextures(2, mTextures, 0);
		Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.logo);
		mImageWidth = bitmap.getWidth();
		mImageHeight = bitmap.getHeight();
		mTexRenderer.updateTextureSize(mImageWidth, mImageHeight);
		GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]);
		GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
		GLToolbox.initTexParams();
	}
  • Trong hàm onDrawFrame của (GLSurfaceView.Renderer) chúng ta xử lý load hiệu ứng ảnh, áp dụng và xác nhận Effect, Ngoài ra hàm này còn trả về 1 GL10. từ GL10 này chúng ta có thể lưu lại hình ảnh có chứa hiệu ứng hiện tại để sử dụng.
	public void onDrawFrame(GL10 gl) {
		if (!mInitialized) {
			loadTextures();
			mInitialized = true;
		}
		applyEffect();
		renderResult();
		if (saveFrame) {
			saveBitmap(takeScreenshot(gl));
		}
	}
  • VD Các hiệu ứng ảnh được tạo ra từ Effect

Screenshot_1.png

IV. Tổng Kết

  • Không cần sử dụng đến các thuật toán phức tạp để xử lý 1 bức ảnh.
  • Không cần quan tâm cấu hình máy có đủ mạnh để xử lý được các thuật toán lọc ảnh áp dụng với 1 bức ảnh có dung lượng lớn hay không.
  • Không cần phải tìm hiểu các thư viện OPENCV phức tạp.
  • Android Effec sẽ giúp chúng ta xử lý các hạn chế đó.
  • Chỉ cần bạn có 1 con mắt thẩm mỹ tốt sẽ tạo ra các hiệu ứng chỉnh sửa ảnh tuyệt vời giống như các app chỉnh sửa ảnh chuyên nghiệp hiện nay.

Tài liệu tham khảo: https://developer.android.com/reference/android/media/effect/EffectFactory.html


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí