The first bitmap is set to fill the entire canvas. I then add another bitmap that has been created from an imageview using:
tattoo.buildDrawingCache();
Bitmap bit2 = tattoo.getDrawingCache();
I then want to add this bitmap over the other keeping it's same scale, rotation, and translation relative to the other bitmap. My issue is that, while the scale and rotation seem fine, the translation shifts to one side or the other.
public static Bitmap overlay(Bitmap bmp1, Bitmap bmp2) {
Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(), bmp1.getConfig());
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(bmp1, 0,0 , null);
Matrix matrix = new Matrix();
matrix.setScale(tattoo.getScaleX() / imageView.getScaleX(), tattoo.getScaleY() / imageView.getScaleY());
int[] tattooCoords = getRelativeCoords(tattoo);
int[] imageViewCoords = getRelativeCoords(imageView);
matrix.setTranslate(tattooCoords[0] - imageViewCoords[0], tattooCoords[1] - imageViewCoords[1]);
matrix.postRotate(tattoo.getRotation(), tattoo.getX() + tattoo.getWidth() / 2,
tattoo.getY() + tattoo.getHeight() / 2);
canvas.drawBitmap(bmp2, matrix, null);
bmp1.recycle();
bmp2.recycle();
return bmOverlay;
}
private static int[] getRelativeCoords(View v){
View parent = v.getRootView();
int[] viewLocation = new int[2];
v.getLocationInWindow(viewLocation);
int[] rootLocation = new int[2];
parent.getLocationInWindow(rootLocation);
int relativeLeft = viewLocation[0] - rootLocation[0];
int relativeTop = viewLocation[1] - rootLocation[1];
return new int[]{relativeLeft, relativeTop};
}
public static Bitmap combineBitmap(Bitmap background, Bitmap foreground) {
Bitmap result;
try {
if (background == null) {
return null;
}
int bgWidth = background.getWidth();
int bgHeight = background.getHeight();
int fgWidth = foreground.getWidth();
int fgHeight = foreground.getHeight();
result = Bitmap.createBitmap(bgWidth, bgHeight, Config.ARGB_8888);
Canvas cv = new Canvas(result);
cv.drawBitmap(background, 0, 0, null);
cv.drawBitmap(foreground, (bgWidth - fgWidth) / 2, (bgHeight - fgHeight) / 2, null);
cv.save(Canvas.ALL_SAVE_FLAG);
cv.restore();
return result;
} catch (Exception e) {
return null;
}
}
Check whether both Images have equal images have same height and width, then check for every pixel is equal.
boolean imagesEqualCheck(Image img1, Image img2)
{
if (img1.getHeight() != img2.getHeight()) return false;
if (img1.getWidth() != img2.getWidth()) return false;
for (int y = 0; y < img1.getHeight(); ++y)
for (int x = 0; x < img1.getWidth(); ++x)
if (img1.getPixel(x, y) != img2.getPixel(x, y)) return false;
return true;
}
Related
now I am getting only one Text over the image I am using Canvas and Bitmap :
here is my code :
public Bitmap drawTextArrayToBitmap(Context mContext, int resourceId,String mText) {
try {
Resources resources = mContext.getResources();
float scale = resources.getDisplayMetrics().density;
Bitmap bitmap = BitmapFactory.decodeResource(resources, resourceId);
android.graphics.Bitmap.Config bitmapConfig = bitmap.getConfig();
if(bitmapConfig == null) {
bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
}
bitmap = bitmap.copy(bitmapConfig, true);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.rgb(110,110, 110));
paint.setTextSize((int) (12 * scale));
paint.setShadowLayer(1f, 0f, 1f, Color.DKGRAY);
Rect bounds = new Rect();
paint.getTextBounds(mText, 0, mText.length(), bounds);
/* int x = (bitmap.getWidth() - bounds.width())/6;
int y = (bitmap.getHeight() + bounds.height())/5;*/
int x = 100, y = 100;
for(int i=0;i<20;i++)
{
canvas.drawText(mText, x * scale, y * scale, paint);
}
return bitmap;
} catch (Exception e) {
// TODO: handle exception
return null;
}
}
inside oncreate ;
ImageView mImageView = (ImageView)findViewById(R.id.imageView1);
// Bitmap bmp =drawTextToBitmap(this,R.drawable.man,"Hello Android");
Bitmap bmp =drawTextArrayToBitmap(this,R.drawable.man,"Smile");
mImageView.setImageBitmap(bmp);
In this above code, I want to add multiple texts on random position over Image and different style I have tried much time I could not get succeed yet. I have tried inside loop also.
Thank you in Advance I would appreciate your effort
I made this project from this open source https://github.com/uptechteam/MotionViews-Android
I'm actually creating a Memegenerator app,
The problem is when I resize the height/width of one of the bitmap inside canvas
The bitmap also moving aside, But it actually should not move from x y axis while I scroll the seekbar, Thats the problem.
This is the ImageEntity class
public ImageEntity(#NonNull Layer layer,
#NonNull Bitmap bitmap,
#IntRange(from = 1) int canvasWidth,
#IntRange(from = 1) int canvasHeight) {
super(layer, canvasWidth, canvasHeight);
this.bitmap = bitmap;
layer.widthSize(bitmap.getWidth());
layer.heightSize(bitmap.getHeight());
updateIMGEntity(false);
}
public void updateIMGEntity() {
updateIMGEntity(true);
}
private void updateIMGEntity(boolean moveToPreviousCenter) {
// save previous center
PointF oldCenter = absoluteCenter();
Bitmap newBitmap = Bitmap.createScaledBitmap(bitmap, layer.getWidth(),
layer.getHeight(), false);
// recycle previous bitmap (if not reused) as soon as possible
if (bitmap != null && bitmap != newBitmap && !bitmap.isRecycled()) {
bitmap.recycle();
}
this.bitmap = newBitmap;
float width = bitmap.getWidth();
float height = bitmap.getHeight();
#SuppressWarnings("UnnecessaryLocalVariable")
float widthAspect = 1.0F * canvasWidth / height;
// for text we always match text width with parent width
this.holyScale = widthAspect;
// initial position of the entity
srcPoints[0] = 0; srcPoints[1] = 0;
srcPoints[2] = width; srcPoints[3] = 0;
srcPoints[4] = width; srcPoints[5] = height;
srcPoints[6] = 0; srcPoints[7] = height;
srcPoints[8] = 0; srcPoints[8] = 0;
if (moveToPreviousCenter) {
// move to previous center
moveCenterTo(oldCenter);
}
}
#Override
public void drawContent(#NonNull Canvas canvas, #Nullable Paint drawingPaint) {
//updateMatrix();
canvas.drawBitmap(bitmap, matrix, drawingPaint);
//release();
}
Please someone help me.
I want to create application like this.
Flood fill algorithm
I applied that code and it is working fine with JPG or PNG file.
But I want to use that algorithm with Vector drawable imageview
Vector drawable imageview before flood fill
After flood fill of vector imageview
Expected result should be like this (Flood fill work perfectly when I set JPG or PNG file)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_flood_fill);
iv_FloodFillActivity_image = findViewById(R.id.iv_FloodFillActivity_image);
iv_FloodFillActivity_image.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
floodColor(event.getX(), event.getY());
}
return true;
}
});
}
private void floodColor(float x, float y) {
final Point p1 = new Point();
p1.x = (int) x;// X and y are co - ordinates when user clicks on the screen
p1.y = (int) y;
Bitmap bitmap = getBitmapFromVectorDrawable(iv_FloodFillActivity_image.getDrawable());
//bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
int pixel = bitmap.getPixel((int) x, (int) y);
int[] sourceColorRGB = new int[]{
Color.red(pixel),
Color.green(pixel),
Color.blue(pixel)
};
final int targetColor = Color.parseColor("#FF2200");
QueueLinearFloodFiller queueLinearFloodFiller = new QueueLinearFloodFiller(bitmap, sourceColor, targetColor);
int toleranceHex = Color.parseColor("#545454");
int[] toleranceRGB = new int[]{
Color.red(toleranceHex),
Color.green(toleranceHex),
Color.blue(toleranceHex)
};
queueLinearFloodFiller.setTolerance(toleranceRGB);
queueLinearFloodFiller.setFillColor(targetColor);
queueLinearFloodFiller.setTargetColor(sourceColorRGB);
queueLinearFloodFiller.floodFill(p1.x, p1.y);
bitmap = queueLinearFloodFiller.getImage();
iv_FloodFillActivity_image.setImageBitmap(bitmap);
}
private Bitmap getBitmapFromVectorDrawable(Drawable drawable) {
try {
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
} catch (OutOfMemoryError e) {
return null;
}
}
Check Class : QueueLinearFloodFiller
How can I use vector drawable?
i have following code:
public Drawable getMergedIcon(Drawable origIcon) {
Bitmap underlayBitmap = null, overlayBitmap = null;
if (isSupportUnderlays()) {
int overlayId = r.nextInt(Underlays.size());
underlayBitmap = Underlays.get(overlayId);
if(Overlays.size() == Underlays.size()) {
overlayBitmap = Overlays.get(overlayId);
}
if(underlayBitmap == null) {
return origIcon;
}
boolean needResize = false;
int targetWidth, targetHeight;
Bitmap iconBitmap = ((BitmapDrawable) origIcon).getBitmap();
if(iconBitmap.getHeight() > underlayBitmap.getHeight()) {
targetWidth = iconBitmap.getWidth();
targetHeight = iconBitmap.getHeight();
needResize = true;
} else {
targetWidth = underlayBitmap.getWidth();
targetHeight = underlayBitmap.getHeight();
}
Paint paint = new Paint();
Bitmap result = Bitmap.createBitmap(targetWidth, targetHeight, iconBitmap.getConfig());
Canvas canvas = new Canvas(result);
if(!needResize) {
canvas.drawBitmap(underlayBitmap, 0, 0, paint);
} else {
canvas.drawBitmap(Bitmap.createScaledBitmap(underlayBitmap, targetWidth,targetHeight, false), 0, 0, paint);
}
int left = (targetHeight - (int) (targetHeight * iconScale)) / 2;
int top = (targetWidth - (int) (targetWidth * iconScale)) / 2;
iconBitmap = Bitmap.createScaledBitmap(iconBitmap, (int) (targetWidth * iconScale),(int) (targetHeight * iconScale), false);
canvas.drawBitmap(iconBitmap, left, top, paint);
if(overlayBitmap != null) {
if(!needResize) {
canvas.drawBitmap(overlayBitmap, 0, 0, paint);
} else {
canvas.drawBitmap(Bitmap.createScaledBitmap(overlayBitmap, targetWidth,targetHeight, false), 0, 0, paint);
}
}
canvas.save();
BitmapDrawable icon = new BitmapDrawable(mContext.getResources(), result);
return icon;
}
return origIcon;
}
it takes random bitmap from overlays and underlays and places icon between it
but when i call this function layers is missed randomly.
f.e. on first call i have underlay and icon, on second overlay and icon and etc
i always have icon, but with only one layer(underlay or overlay) and never with bot of them.
Code was workable, was my stupid mistake...
I just placed wrong drawables in arrays.
How can i to get color/alpha of pixel from Sprite in andengine without creating any additional Bitmap?
I solved this problem by using this function
private void loadObjectsMask()
{
InputStream in = null;
Bitmap maskForObjects=null;
try {
final BitmapFactory.Options decodeOptions = new BitmapFactory.Options();
decodeOptions.inPreferredConfig = Bitmap.Config.ARGB_4444;
in = GameActivity.this.getAssets().open("images/" + BACKGROUND_PATH + getObjectImgFile());
maskForObjects = BitmapFactory.decodeStream(in, null, decodeOptions);
} catch (final IOException e) {
} finally {
StreamUtils.close(in);
}
if (maskForObjects != null)
{
objectsMask=new byte[maskForObjects.getWidth()][maskForObjects.getHeight()];
for(int pw=0;pw<maskForObjects.getWidth();++pw)
{
for(int ph=0;ph<maskForObjects.getHeight();++ph)
{
objectsMask[pw][ph]=(byte)(Color.alpha(maskForObjects.getPixel(pw, ph))==0?0:1);
}
}
maskForObjects.recycle();
System.out.printf("Bitmap size %d %d\n", maskForObjects.getWidth(),maskForObjects.getHeight());
}
else System.out.printf("Bitmap size error\n");
}
have a look this method, this method are used to effect on each pix
public Bitmap invert(Bitmap src) {
// image size
int width = src.getWidth();
int height = src.getHeight();
// create output bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
// color information
int A, R, G, B;
int pixel;
// scan through all pixels
for(int x = 0; x < width; ++x) {
for(int y = 0; y < height; ++y) {
// get pixel color
pixel = src.getPixel(x, y);
// get color on each channel
A = Color.alpha(pixel);
R = Color.red(pixel);
G = Color.green(pixel);
B = Color.blue(pixel);
// set new pixel color to output image
bmOut.setPixel(x, y, Color.argb(A, 255-R, 255-G, 255-B));
}
}
// return final image
return bmOut;
}
To convert Gray Scale
public static Bitmap toGrayscale(Bitmap bmpOriginal)
{
int width, height;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();
Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bmpOriginal, 0, 0, paint);
return bmpGrayscale;
}