Android 如何缩放图像而不模糊?
我正在尝试将一个小图像(大约20x40像素)缩放为任意大的图像。我通过设置ImageView.scaleType属性来进行缩放,但是当它确实缩放图像时,它会从一种原始像素颜色渐变到另一种,从而创建一个模糊的图像 这里有一些问题的背景。我正在尝试为Android创建一款老式的16位风格的游戏。我想将精灵/etc存储为小文件,然后根据用户的屏幕大小将其放大。这样,我就不必为每个精灵创建大量不同大小的图像。现在我正在进行概念验证,所以我尝试将一个小的20x40图像文件缩放到整个屏幕的大小 *编辑:我想出了如何使用Reflog推荐的方法。但是,它仍然会有一些衰减,只是远远小于默认算法 *edit2:明白了!我必须关闭抗锯齿功能 *edit3:这对我来说不可思议地停止了工作,我发现另一个地方需要禁用抖动/自动缩放。添加了选项行Android 如何缩放图像而不模糊?,android,image-processing,bitmap,Android,Image Processing,Bitmap,我正在尝试将一个小图像(大约20x40像素)缩放为任意大的图像。我通过设置ImageView.scaleType属性来进行缩放,但是当它确实缩放图像时,它会从一种原始像素颜色渐变到另一种,从而创建一个模糊的图像 这里有一些问题的背景。我正在尝试为Android创建一款老式的16位风格的游戏。我想将精灵/etc存储为小文件,然后根据用户的屏幕大小将其放大。这样,我就不必为每个精灵创建大量不同大小的图像。现在我正在进行概念验证,所以我尝试将一个小的20x40图像文件缩放到整个屏幕的大小 *编辑:我想
@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);
}
使用:
要使用NN缩放,这将减少模糊,但也会降低缩放的质量。也许此代码可以帮助您:
/**
* @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;
}
/**
*@param位图原始位图
*@param finWid新位图的宽度(剪切宽度)
*@param finHei新位图的高度(切割高度)
*@param-angulo旋转角(度)
*@param sx比例X
*@param sy scale Y
*@param tx Translate X
*@param-ty-Y
*新位图的@param config{@link config}
*@return{@link Bitmap}已转换
*/
公共位图CreateTranpixBitmap(位图位图、int-finWid、int-finHei、float-angulo、float-sx、float-sy、float-tx、float-ty、Config-Config){
返回Bitmap.createBitmap(createTransPixArray(位图、Bitmap.getWidth()、Bitmap.getHeight()、finWid、finHei、angulo、sx、sy、tx、ty)、finWid、finHei、config);
}
public int[]createTransPixArray(位图位图、int宽度、int高度、int finWid、int finHei、float angulo、float sx、float sy、float tx、float ty){
float scaWid=宽度*sx;
浮子scaHei=高度*sy;
int[]ori=新int[宽度*高度];
getPixels(ori,0,宽度,0,0,宽度,高度);
bitmap.recycle();
位图=空;
gc();
返回transformPix(ori、宽度、高度、scaWid、scaHei、finWid、finHei、angulo、tx、ty);
}
/**
*应用缩放、平移和旋转的核心功能(如果需要,也可以剪切图像)
*@param ori原始颜色数组
*@param-wid原始宽度
*@param-hei原始高度
*@param scaWid缩放原始宽度
*@param scaHei缩放原始高度
*@param finWid新位图的宽度
*@param finHei新位图的高度
*@param-angulo旋转角度
*@param tx Translate X
*@param-ty-Y
*@return int[]颜色
*/
私有int[]transformPix(int[]ori、int-wid、int-hei、float-scaWid、float-scaHei、int-finWid、int-finHei、float-angulo、float-tx、float-ty){
int[]fin=新int[finWid*finHei];
双正弦=数学正弦(数学托拉第安(安古洛));
双余弦=数学余弦(数学托拉迪安(安古洛));
int dx=(int)((scaWid finWid)/2);
int dy=(int)((scaHei-finHei)/2);
/*没有其他解释,只有一个相反的过程
*埃斯卡拉、罗塔、特拉达和科尔塔、托多·米斯莫·蒂恩波:D
*/
对于(int y=0;y=0&&tempRX=0&&tempRY
此函数只需缩放颜色阵列(如果不需要额外功能):
private int[]比例(int[]ori,int-wid,int-hei,int-finWid,int-finHei){
int[]fin=新int[finWid*finHei];
对于(int y=0;y
我希望这是有用的,我很高兴能得到一些改进代码的建议。听起来你想要最近邻缩放。不熟悉Android开发,但你可以尝试在文档中搜索。好的,谢谢。我是Android开发的新手,所以我想知道如何使用你告诉我的东西。我以前使用Xml将ImageView放入布局,但现在我尝试通过代码这样做,以便可以使用paint对象。我明天还要继续。那个“g”变量是画布吗?是的,那是画布。在重写的受保护的void onDraw(Canvas g)中使用此代码。嗯,显然评论不是在这个站点上继续讨论的地方,所以我将其添加到了原始问题中
/**
* @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;
}
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;
}