is there a way to make a pixel transformation in Android by program code, like you see in the pictures below? Source should be the original picture and the result the transformed picture.
It would be very nice if someone could send me the code for it.
I have no idea if it's possible with Android and how I have to programme it.
Thanks for your help
Best regards
Tom
Original picture
Picture after pixel transformation
I've found a solution....
package com.devcom_networks.graphicslibrary;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
public class Pixelize {
Bitmap originalBmp;
Bitmap obscuredBmp;
Canvas obscuredCanvas ;
Paint obscuredPaint;
private final static int PIXEL_BLOCK = 120;
public Bitmap createPixelizedBitmap(Bitmap bitmap, int pixelsize)
{
if (bitmap == null)
return null;
// Create the bitmap that we'll output from this method
obscuredBmp = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),bitmap.getConfig());
// Create the canvas to draw on
obscuredCanvas = new Canvas(obscuredBmp);
// Create the paint used to draw with
obscuredPaint = new Paint();
// Create a default matrix
Matrix obscuredMatrix = new Matrix();
// Draw the scaled image on the new bitmap
obscuredCanvas.drawBitmap(bitmap, obscuredMatrix, obscuredPaint);
pixelizeImage(obscuredBmp, obscuredCanvas, pixelsize);
return obscuredBmp;
}
private Bitmap pixelizeImage(Bitmap bitmap, Canvas canvas, int pixelSize)
{
originalBmp = bitmap;
if (pixelSize == 0)
pixelSize = (int)(bitmap.getWidth())/PIXEL_BLOCK;
if (pixelSize <= 0) //1 is the smallest it can be
pixelSize = 1;
int px, py;
for (int x = 0; x < originalBmp.getWidth() - 1; x+=pixelSize) {
for (int y = 0; y < originalBmp.getHeight() - 1; y+=pixelSize) {
px = (x/pixelSize)*pixelSize;
py = (y/pixelSize)*pixelSize;
try
{
int pixels[] = new int[pixelSize*pixelSize];
int newPixel = originalBmp.getPixel(px, py);
for (int i = 0; i < pixels.length; i++)
pixels[i] = newPixel;
originalBmp.setPixels(pixels, 0, pixelSize, px, py, pixelSize, pixelSize);
}
catch (IllegalArgumentException iae)
{
//something is wrong with our pixel math
break; //stop the filter
}
}
}
return originalBmp;
}
}
Related
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 have a feature request. The current flow is for the user to scan a code (not a QR code, not sure what it is, zxing will scan it), then scan the test card.
The client has asked for me allow the user to import the test from the library. So we need to be able to scan the code off an image.
Is it possible to do this in zxing or am I forced to use the camera / feature is not possible?
Thanks!
Here is my solution. I had to downsize the image, and inver the colors for it to work with zxing. I might add a convert to gray scale, but not today..
public static String scanDataMatrixImage(Bitmap bitmap) {
bitmap = doInvert(bitmap);
double scaling = getScaling(bitmap);
Bitmap resized;
if(scaling>0) {
resized = Bitmap.createScaledBitmap(bitmap, (int) (bitmap.getWidth() * scaling), (int) (bitmap.getHeight() * scaling), true);
}
else{
resized = bitmap;
}
String contents = null;
int[] intArray = new int[resized.getWidth() * resized.getHeight()];
//copy pixel data from the Bitmap into the 'intArray' array
resized.getPixels(intArray, 0, resized.getWidth(), 0, 0, resized.getWidth(), resized.getHeight());
LuminanceSource source = new RGBLuminanceSource(resized.getWidth(), resized.getHeight(), intArray);
BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(source));
MultiFormatReader reader = new MultiFormatReader();
try
{
Result result = reader.decode(binaryBitmap);
contents = result.getText();
} catch (
Exception e
)
{
Log.e("QrTest", "Error decoding barcode", e);
}
return contents;
}
private static double getScaling(Bitmap bitmap){
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int smallest = width;
if(smallest > height){
smallest = height;
}
double ratio = 200.0/smallest;
return ratio;
}
public static Bitmap doInvert(Bitmap src) {
// create new bitmap with the same settings as source bitmap
Bitmap bmOut = Bitmap.createBitmap(src.getWidth(), src.getHeight(), src.getConfig());
// color info
int A, R, G, B;
int pixelColor;
// image size
int height = src.getHeight();
int width = src.getWidth();
// scan through every pixel
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
// get one pixel
pixelColor = src.getPixel(x, y);
// saving alpha channel
A = Color.alpha(pixelColor);
// inverting byte for each R/G/B channel
R = 255 - Color.red(pixelColor);
G = 255 - Color.green(pixelColor);
B = 255 - Color.blue(pixelColor);
// set newly-inverted pixel to output image
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
}
}
// return final bitmap
return bmOut;
}
I want to show a CustomOverlay on a Google Maps V2. The loading of the tiles works as expected, the only thing is, that the shown tiles are not appearing to be sharp at all, kind of blurry. Google did not get me to an usable answer.
I took the approach of adding classical 256px x 256px tiles for the TileProvider. I managed to get a tile source where the images were #2x (retina), which made the whole visual experience much sharper, but I would rather not use this source, as the data transfer rate is four times higher, hence not usable on mobile devices and slow internet speeds.
I included two different examples (screenshots) of the rendered map, both with the same configuration (OSM - 256x256 tiles) and with the provided TileProviderOsm. One is on a Galaxy Nexus and the other on a Nexus 5 phone. Both do not look like they were rendered correctly.
Any idea what I could do to prevent the blurriness or increase the sharpness?
My TileProvider looks like following:
public class TileProviderOsm extends UrlTileProvider {
private static final String MAP_URL = "http://tile.openstreetmap.org/%d/%d/%d.png";
private static int TILE_WIDTH = 256;
private static int TILE_HEIGHT = 256;
public static int MIN_ZOOM = 7;
public static int MAX_ZOOM = 15;
public TileProviderOsm() {
super(TILE_WIDTH, TILE_HEIGHT);
}
#Override
public synchronized URL getTileUrl(int x, int y, int zoom) {
String s = String.format(Locale.US, MAP_URL, zoom, x, y);
URL url = null;
try {
url = new URL(s);
} catch (MalformedURLException e) {
e.printStackTrace();
}
return url;
}
}
Here's how I add the overlay to the map:
map.addTileOverlay(new TileOverlayOptions().tileProvider(new TileProviderOsm()));
Here are some examples of the rendered Google Map:
I am solving this issue by drawing four tiles into one tile.
I wrote this TileProvider which is using another tile provider to create higher resolution tiles.
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import com.google.android.gms.maps.model.Tile;
import com.google.android.gms.maps.model.TileProvider;
import java.io.ByteArrayOutputStream;
public class CanvasTileProvider implements TileProvider {
static final int TILE_SIZE = 512;
private TileProvider mTileProvider;
public CanvasTileProvider(TileProvider tileProvider) {
mTileProvider = tileProvider;
}
#Override
public Tile getTile(int x, int y, int zoom) {
byte[] data;
Bitmap image = getNewBitmap();
Canvas canvas = new Canvas(image);
boolean isOk = onDraw(canvas, zoom, x, y);
data = bitmapToByteArray(image);
image.recycle();
if (isOk) {
Tile tile = new Tile(TILE_SIZE, TILE_SIZE, data);
return tile;
} else {
return mTileProvider.getTile(x, y, zoom);
}
}
Paint paint = new Paint();
private boolean onDraw(Canvas canvas, int zoom, int x, int y) {
x = x * 2;
y = y * 2;
Tile leftTop = mTileProvider.getTile(x, y, zoom + 1);
Tile leftBottom = mTileProvider.getTile(x, y + 1, zoom + 1);
Tile rightTop = mTileProvider.getTile(x + 1, y, zoom + 1);
Tile rightBottom = mTileProvider.getTile(x + 1, y + 1, zoom + 1);
if (leftTop == NO_TILE && leftBottom == NO_TILE && rightTop == NO_TILE && rightBottom == NO_TILE) {
return false;
}
Bitmap bitmap;
if (leftTop != NO_TILE) {
bitmap = BitmapFactory.decodeByteArray(leftTop.data, 0, leftTop.data.length);
canvas.drawBitmap(bitmap, 0, 0, paint);
bitmap.recycle();
}
if (leftBottom != NO_TILE) {
bitmap = BitmapFactory.decodeByteArray(leftBottom.data, 0, leftBottom.data.length);
canvas.drawBitmap(bitmap, 0, 256, paint);
bitmap.recycle();
}
if (rightTop != NO_TILE) {
bitmap = BitmapFactory.decodeByteArray(rightTop.data, 0, rightTop.data.length);
canvas.drawBitmap(bitmap, 256, 0, paint);
bitmap.recycle();
}
if (rightBottom != NO_TILE) {
bitmap = BitmapFactory.decodeByteArray(rightBottom.data, 0, rightBottom.data.length);
canvas.drawBitmap(bitmap, 256, 256, paint);
bitmap.recycle();
}
return true;
}
private Bitmap getNewBitmap() {
Bitmap image = Bitmap.createBitmap(TILE_SIZE, TILE_SIZE,
Bitmap.Config.ARGB_8888);
image.eraseColor(Color.TRANSPARENT);
return image;
}
private static byte[] bitmapToByteArray(Bitmap bm) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, bos);
byte[] data = bos.toByteArray();
try {
bos.close();
} catch (Exception e) {
e.printStackTrace();
}
return data;
}
}
It's a problem with the zoom level and scaling of the map tiles. This seems to be a problem with the Maps API V2 for Android. The behavior is supposedly intended as stated here: gmaps-api-issues #4840
I solved it by requesting larger tiles from the WMS - just replace 256x256 with 512x512.
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;
}
i created a sprite class and in this example it runs a spritesheet of 44 frames, i want to set the frame rate to 10fps so the all animation will be 4 seconds more or less.
this is my code, it works but with very slow rate and i cant understand why:
package sprite2.sprite2;
import sprite2.sprite2.Sprite2Activity.Panel;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
public class Sprite {
int x,y;
int xSpeed, ySpeed;
int height, width;
Bitmap b;
Panel ov;
int currentFrame = 0;
int direction = 0;
int framePeriod;
long frameTicker;
int frameNr;
public Sprite(Panel panel, Bitmap _scratch) {
b = _scratch;
ov = panel;
height = 480;
width = b.getWidth()/44;
x = y = 0;
ySpeed = 0;
framePeriod = 1000 / 10;
frameTicker = 0;
frameNr = 44;
// TODO Auto-generated constructor stub
}
public void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
update(System.currentTimeMillis());
int srcX = currentFrame * width;
Rect src = new Rect (srcX, 0 , srcX+width, height);
Rect dest = new Rect(0, 0, canvas.getWidth(), canvas.getHeight());
canvas.drawBitmap(b, src, dest, null);
}
public void update(long videotime) {
if (videotime > frameTicker + framePeriod) {
frameTicker = videotime;
// increment the frame
currentFrame++;
if (currentFrame >= frameNr) {
currentFrame = 0;
}
}
}
}