PorterDuff.Mode.MULTIPLY inside ComposeShader doesn't work properly - android

I want to implement color palette into my application. This is the main onDraw method.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int h = canvas.getHeight();
int w = canvas.getWidth();
if (paint == null) {
paint = new Paint();
luar = new LinearGradient(0.f, 0.f, 0.f, h, 0xffffffff, 0xff000000, TileMode.CLAMP);
}
int rgb = Color.HSVToColor(color);
Shader dalam = new LinearGradient(0.f, 0.f, w, 0.f, 0xffffffff, rgb, TileMode.CLAMP);
ComposeShader shader = new ComposeShader( luar, dalam, PorterDuff.Mode.MULTIPLY);
paint.setShader(shader);
canvas.drawRect(0.f, 0.f, w, h, paint);
}
But, ComposeShader shader seems not working.
That is,
ComposeShader shader = new ComposeShader( dalam, luar, PorterDuff.Mode.MULTIPLY);
shows only vertical gradient. And if I change the parameters:
ComposeShader shader = new ComposeShader( luar, dalam, PorterDuff.Mode.MULTIPLY);
it shows horizontal gradient. No multiplication! Why?

Related

how to add timestamp like a camcorder while recording video using GLES20

I want to display date/time while recording the video and it should be displayed when we replay the videos like we do it in CCTV video recordings. i can display shapes using GLES20 i want to use text inside video to display Timestamp i am using textureview along with Mediarecorder andorid when i run GLText() it displays nothing instead of text "hellooo" on the video.
here is an example :
private void drawBox() {
GLES20.glEnable(GLES20.GL_SCISSOR_TEST);
GLES20.glScissor(0, 0, 100, 100);
GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
}
this code displays a box but i want to replace this with text and i am unable to find any solution ..
I tried this method but it didn't work
public void GLText() {
// Bitmap bitmap = Bitmap.createBitmap(64, 64, Bitmap.Config.ARGB_4444);
// Canvas canvas = new Canvas(bitmap);
// bitmap.eraseColor(0);
//
// Paint paint = new Paint();
// paint.setTextSize(18);
// paint.setAntiAlias(true);
// paint.setARGB(0xff, 0xff, 0xff, 0xff);
// paint.setTextAlign(Paint.Align.LEFT);
// paint.setTextScaleX(0.5f);
// canvas.drawText("testGLText", 0.f, 15.f, paint);
Bitmap bitmap = fromText("hellooo",50);
GLES20.glEnable(GLES20.GL_SCISSOR_TEST);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glEnable(GLES20.GL_BLEND); // this, and the next line
GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA); // and this were key! I'm still not completely sure as to what this is doing, but it works!
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, bitmap, 0);
}
public Bitmap fromText(String text, int textSize) {
Paint paint = new Paint();
paint.setTextSize(textSize);
paint.setColor(Color.WHITE);
float baseline = -paint.ascent(); // ascent() is negative
int width = (int) (paint.measureText(text) + 1.0f);
int height = (int) (baseline + paint.descent() + 1.0f);
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.setHasAlpha(true);
Canvas canvas = new Canvas(bitmap);
// canvas.drawColor(Color.argb(0, 255, 255, 255));
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
canvas.drawText(text, 0, baseline, paint);
return bitmap;
}
My entire code is :
if (showBox && (++mFrameCount & 0x04) == 0) {
drawBox(); // here drawBox draws a box but i when i call GLText() it draws nothing
}
}
/**
* Draws a red box in the corner.
*/
private void drawBox() {
GLES20.glEnable(GLES20.GL_SCISSOR_TEST);
GLES20.glScissor(0, 0, 100, 100);
GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
}
private void drawSquare() {
GLES20.glEnable(GLES20.GL_SCISSOR_TEST);
GLES20.glScissor(200, 300, 900, 100);
GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
}
public void GLText() {
// Bitmap bitmap = Bitmap.createBitmap(64, 64, Bitmap.Config.ARGB_4444);
// Canvas canvas = new Canvas(bitmap);
// bitmap.eraseColor(0);
//
// Paint paint = new Paint();
// paint.setTextSize(18);
// paint.setAntiAlias(true);
// paint.setARGB(0xff, 0xff, 0xff, 0xff);
// paint.setTextAlign(Paint.Align.LEFT);
// paint.setTextScaleX(0.5f);
// canvas.drawText("testGLText", 0.f, 15.f, paint);
Bitmap bitmap = fromText("hellooo",50);
GLES20.glEnable(GLES20.GL_SCISSOR_TEST);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glEnable(GLES20.GL_BLEND); // this, and the next line
GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA); // and this were key! I'm still not completely sure as to what this is doing, but it works!
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, bitmap, 0);
}
public Bitmap fromText(String text, int textSize) {
Paint paint = new Paint();
paint.setTextSize(textSize);
paint.setColor(Color.WHITE);
float baseline = -paint.ascent(); // ascent() is negative
int width = (int) (paint.measureText(text) + 1.0f);
int height = (int) (baseline + paint.descent() + 1.0f);
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.setHasAlpha(true);
Canvas canvas = new Canvas(bitmap);
// canvas.drawColor(Color.argb(0, 255, 255, 255));
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
canvas.drawText(text, 0, baseline, paint);
return bitmap;
}
Here I got an opensource library which works the similar way .. i can insert text inside a video and can do many other things.
https://github.com/INDExOS/media-for-mobile
I've faced the same issue of not being able to draw a transparent text texture on top of the video texture, using Grafika. I created a transparent text bitmap using the following :
public Bitmap fromText(String text, int textSize, #ColorInt int textColor) {
Paint paint = new Paint();
paint.setTextSize(textSize);
paint.setColor(Color.WHITE);
float baseline = -paint.ascent(); // ascent() is negative
int width = (int) (paint.measureText(text) + 1.0f);
int height = (int) (baseline + paint.descent() + 1.0f);
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.setHasAlpha(true);
Canvas canvas = new Canvas(bitmap);
// canvas.drawColor(Color.argb(0, 255, 255, 255));
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
canvas.drawText(text, 0, baseline, paint);
return bitmap;
}
When I save the above Bitmap as a PNG file, it's transparent with only white text, however it shows up with a black background when rendered with Grafika.
To set a bitmap to a texture handle use the following :
public void setBitmap(Bitmap bitmap, int textureId) {
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(mTextureTarget, textureId);
GLES20.glEnable(GLES20.GL_BLEND); // this, and the next line
GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA); // and this were key! I'm still not completely sure as to what this is doing, but it works!
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, bitmap, 0);
}
And lastly, there is a bug in Grafika where they have used GLES11Ext.GL_TEXTURE_EXTERNAL_OES in the createTextureObject() in Texture2dProgram, instead of mTargetTexture.

How to set LinearGradients into ComposeShader

I am trying to make ComposeShader using LinearGradients but may have few problem.
1) If I am only use one LinearGradient like
lgA = new LinearGradient(0, 0, 0, h, 0xff000000, 0xffffffff, Shader.TileMode.CLAMP);
then above part of the requirement correct
2) If use ComposeShader then result not like actual requirement
Actual Requirment :
Then how I can solve this problem please any one help me for this problem.
public class DrawGradient extends View {
Paint paint;
LinearGradient lgA;
LinearGradient lgB;
ComposeShader shader;
public DrawGradient(Context context) {
super(context);
initView();
}
private void initView() {
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
paint = new Paint();
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
lgA = new LinearGradient(0, 0, w, h, 0xff000000, 0xffffffff, Shader.TileMode.CLAMP);
lgB = new LinearGradient(0, h, w, 0, 0xffffffff, 0xff000000, Shader.TileMode.CLAMP);
shader = new ComposeShader(lgA, lgB, PorterDuff.Mode.MULTIPLY);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setShader(shader);
canvas.drawPaint(paint);
}
}
Code Output :
Since this four months I imagine this will be of little help now, but here it is for anyone else with a similar problem.
The problem lies in these two lines:
lgA = new LinearGradient(0, 0, w, h, 0xff000000, 0xffffffff, Shader.TileMode.CLAMP);
lgB = new LinearGradient(0, h, w, 0, 0xffffffff, 0xff000000, Shader.TileMode.CLAMP);
You've created two linear gradients; one going from top-left to bottom-left, the other going from bottom-left to top-right. What you are looking for is this:
lgA = new LinearGradient(0, 0, 0, h/2, Color.BLACK, Color.WHITE, Shader.TileMode.CLAMP);
lgB = new LinearGradient(0, h/2, 0, h, Color.WHITE, Color.BLACK, Shader.TileMode.CLAMP);
With these changes, it worked for me. It's important to note that ComposeShader wouldn't work without the line:
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
For reasons explained here.
ComposeShader seems to be mostly used for overlaying Shaders, such as LinearGradients, rather than creating a three colour transition which you're looking for. Alternatively you could have used LinearGradient by itself, but with the other constructor, which can take more than two different colours. E.g.
int[] colors = {Color.BLACK,Color.WHITE,Color.BLACK};
float[] pos = {0.0f,0.5f,1.0f};
paint.setShader(new LinearGradient(0,0,0,h,colors,pos,Shader.TileMode.CLAMP));
This would have given you the same effect, without needing ComposeShader. However I was using this method in my own project, but using Color.TRANSPARENT in the gradient and it was coming out black rather than transparent.

How to mask Bitmap with LinearGradient shader properly?

I'm trying to mask Bitmap with gradient alpha at bottom. Gradient size are fixed and independed of Bitmap size. But it draws incorrect: bottom of gradient at top, than top.
What's wrong?
There is sample code:
final int GRADIENT_HEIGHT = 32;
public Bitmap addGradient(Bitmap src) {
int w = src.getWidth();
int h = src.getHeight();
Bitmap overlay = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(overlay);
canvas.drawBitmap(src, 0, 0, null);
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0, 0, 0, GRADIENT_HEIGHT, 0xFFFFFFFF, 0x00FFFFFF, TileMode.REPEAT);
paint.setShader(shader);
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
canvas.drawRect(0, h - GRADIENT_HEIGHT, w, h, paint);
return overlay;
}
Thanks!
Change your LinearGradient to this:
LinearGradient shader = new LinearGradient(0, h - GRADIENT_HEIGHT, 0, h, 0xFFFFFFFF, 0x00FFFFFF, Shader.TileMode.CLAMP);

Drawing Trasparent Text on Bitmap in Android

Im trying to draw a string on top of an Image,The code works but the transparency is not obtained i have used several values for alpha,but does not work.
paint.setAlpha(alpha);
Can some one tell me what are the range of values for transparency or what im doing wrong here
public static Bitmap drawtext(Bitmap src, String txt,int alpha) {
int w = src.getWidth();
int h = src.getHeight();
Bitmap result = Bitmap.createBitmap(w, h, src.getConfig());
Canvas canvas = new Canvas(result);
canvas.drawBitmap(src, 0, 0, null);
Paint paint = new Paint();
paint.setAlpha(alpha);
paint.setColor(Color.RED);
paint.setTextSize(18);
paint.setAntiAlias(true);
paint.setUnderlineText(true);
canvas.drawText(txt, 20, 25, paint);
return result;
}
See:
http://developer.android.com/reference/android/graphics/Paint.html#setColor(int)
The setColor will overwrite the alpha value you just set before that call. That should work:
paint.setColor(Color.RED);
paint.setAlpha(alpha);
Try this code or download demo here
public Bitmap drawText(String text, int textWidth, int color) {
// Get text dimensions
TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setColor(Color.parseColor("#ff00ff"));
textPaint.setTextSize(30);
StaticLayout mTextLayout = new StaticLayout(text, textPaint, textWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);
// Create bitmap and canvas to draw to
Bitmap b = Bitmap.createBitmap(textWidth, mTextLayout.getHeight(), Bitmap.Config.ARGB_4444);
Canvas c = new Canvas(b);
// Draw background
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG);
paint.setStyle(Paint.Style.FILL);
paint.setColor(color);
c.drawPaint(paint);
// Draw text
c.save();
c.translate(0, 0);
mTextLayout.draw(c);
c.restore();
return b;
}
set the returned image to imageview
//background transparent
int colorT=Color.TRANSPARENT;
Bitmap img1=drawText(text,width,colorT);
img2.setImageBitmap(img1);

Add Watermark to an image just like flipboard in Android

I want to add watermark to images just like flipboard does.
As you can see text is added at the bottom of the images with black transparent background. I want to do the exact same thing. Till now I've managed to write text on image but I am not able to make it's background black transparent just like the above picture.
Here's my code so far which I found from here.
public Bitmap mark(Bitmap src, String watermark) {
int w = src.getWidth();
int h = src.getHeight();
Shader shader = new LinearGradient(0, 0, 100, 0, Color.TRANSPARENT, Color.BLACK, TileMode.CLAMP);
Bitmap result = Bitmap.createBitmap(w, h, src.getConfig());
Canvas canvas = new Canvas(result);
canvas.drawBitmap(src, 0, 0, null);
Paint paint = new Paint();
paint.setColor(Color.WHITE);
paint.setTextSize(50);
paint.setAntiAlias(true);
paint.setShader(shader);
paint.setUnderlineText(false);
canvas.drawText(watermark, 10 , h-15, paint);
return result;
}
I think it doesn't require gradient, you can draw it using simple color and using drawRect() method.
Sample code is below, i gonna take the black background size as 25% of whole image.
public Bitmap mark(Bitmap src, String watermark) {
int w = src.getWidth();
int h = src.getHeight();
Paint bgPaint=new Paint();
bgPaint.setColor(Color.parse("AA000000")); //transparent black,change opacity by changing hex value "AA" between "00" and "FF"
Bitmap result = Bitmap.createBitmap(w, h, src.getConfig());
Canvas canvas = new Canvas(result);
canvas.drawBitmap(src, 0, 0, null);
Paint paint = new Paint();
paint.setColor(Color.WHITE);
paint.setTextSize(50);
paint.setAntiAlias(true);
paint.setUnderlineText(false);
//should draw background first,order is important
int left=0;
int right=w;
int bottom=h;
int top=bottom-(h*.25);
canvas.drawRect(left,top,right,bottom,bgPaint);
canvas.drawText(watermark, 10 , h-15, paint);
return result;
}

Categories

Resources