How can I scale an image without blurring?

I am trying to scale a small image (approximately 20x40 pixels) to an arbitrarily large image. I am doing the scaling by setting the ImageView.scaleType property, but as long as it scales the image, it fades from one source pixel color to the next, creating a large blurry version of the image.

Here is some context for the question. I'm trying to create an old school 16-bit Android game. I want to store / etc sprites as tiny files and then scale them more depending on the user's screen size. Thus, I do not need to create a ton of different images of different sizes for each sprite. Now I'm just working on a proof of concept, so I'm trying to scale a tiny 20x40 image file to fit the entire screen.

* edit: I figured out how to use the Reflog method. However, it still does some attenuation, which is much smaller than the default algorithm.

* edit2: Got it! I had to turn off anti-aliasing

* edit3: This mysteriously stopped working for me, and I found another place where I had to turn off anti-aliasing / autoscaling. Added parameter strings.

@Override protected void onDraw(Canvas canvas) { Paint paint = new Paint(); paint.setDither(false); paint.setAntiAlias(false); BitmapFactory.Options options = new BitmapFactory.Options(); options.inDither = false; options.inScaled = false; Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.tinyimg, options); canvas.drawBitmap(bitmap, null, new RectF(getLeft(), getTop(), getRight()/2, getBottom()/2), paint); } 
+7
source share
2 answers

Using:

 paint.setDither(false); g.drawBitmap(img, src, dst, paint); 

to use NN scaling, this will reduce blur, but also reduce the quality of scaling.

+5
source

Perhaps this code may help you:

 /** * @param bitmap Bitmap original * @param finWid width of the new Bitmap (width of the cut) * @param finHei height of the new Bitmap (height of the cut) * @param angulo angle of rotation in degrees * @param sx scale X * @param sy scale Y * @param tx Translate X * @param ty Translate Y * @param config {@link Config} of the new Bitmap * @return {@link Bitmap} transformed */ public Bitmap createTransPixBitmap(Bitmap bitmap, int finWid, int finHei, float angulo, float sx, float sy, float tx, float ty, Config config){ return Bitmap.createBitmap(createTransPixArray(bitmap, bitmap.getWidth(), bitmap.getHeight(), finWid, finHei, angulo, sx, sy, tx, ty), finWid, finHei, config); } public int[] createTransPixArray(Bitmap bitmap, int width, int height, int finWid, int finHei, float angulo, float sx, float sy, float tx, float ty){ float scaWid = width*sx; float scaHei = height*sy; int[] ori = new int[width*height]; bitmap.getPixels(ori, 0, width, 0, 0, width, height); bitmap.recycle(); bitmap = null; System.gc(); return transformPix(ori, width, height, scaWid, scaHei, finWid, finHei, angulo, tx, ty); } /** * Core function for apply scale, translate and rotation (cut the image if you want too) * @param ori original color array * @param wid original width * @param hei original height * @param scaWid scaled original width * @param scaHei scaled original height * @param finWid width of the new Bitmap * @param finHei height of the new Bitmap * @param angulo rotation in degrees * @param tx Translate X * @param ty Translate Y * @return int[] of colors */ private int[] transformPix(int[] ori, int wid, int hei, float scaWid, float scaHei, int finWid, int finHei, float angulo, float tx, float ty){ int[] fin = new int[finWid*finHei]; double sin = Math.sin(Math.toRadians(angulo)); double cos = Math.cos(Math.toRadians(angulo)); int dx = (int)((scaWid-finWid)/2); int dy = (int)((scaHei-finHei)/2); /* No se como explicar esto, solo puedo decir que el proceso de escalado es en sentido inverso * escala, rota, translada y corta, todo al mismo tiempo :D */ for(int y = 0; y < finHei; y++){ for(int x = 0; x < finWid; x++){ int tempX = (int)Math.floor(((x+dx-((float)scaWid/2))*((float)wid/scaWid))+0.5f-tx); int tempY = (int)Math.floor(((y+dy-((float)scaHei/2))*((float)hei/scaHei))+0.5f-ty); int tempRX = (int)Math.floor(((cos*(float)tempX)+(sin*(float)tempY))+0.5f+((float)wid/2)); int tempRY = (int)Math.floor(((cos*(float)tempY)-(sin*(float)tempX))+0.5f+((float)hei/2)); if((tempRX >= 0 && tempRX < wid) && (tempRY >= 0 && tempRY < hei)) fin[x+(y*finWid)] = ori[tempRX+(tempRY*wid)]; } } ori = null; return fin; } 

This function simply scales the array of colors (if you do not want additional functions):

 private int[] scale(int[] ori, int wid, int hei, int finWid, int finHei){ int[] fin = new int[finWid*finHei]; for(int y = 0; y < finHei; y++){ for(int x = 0; x < finWid; x++){ int temp = (int)(x*(wid/finWid))+((int)(y*(hei/finHei))*wid); fin[x+(y*finWid)] = ori[temp]; } } return fin; } 

Hope this is helpful and I’ll be happy to take some tips to improve this code.

+1
source

All Articles