WAP之家:为您提供最全最新的WAP技术,CP.SP.3G等行业资讯。 WAP之家交流论坛全新开放 点击进入>>
WAP资讯 | 3G动态 | SP动态 | 运营商动态 | 内容商动态 | 制造商动态 | 论坛讨论>> 每次自动访问
WAP技术 | WAP源码 | 手机编程 | 手机源码 | 无线技术 | J2ME技术 | 手机软件 添加到收藏夹
IVR技术 | SP资料 | SMS MMS技术 | 商业方案 | IVR下载 | 书籍教程 | 工具软件 语言:繁體中文

WAP之家技术文章J2ME技术程序开发J2ME插值算法实现图片的放大缩小

J2ME插值算法实现图片的放大缩小
作者:未知  来源:www.00muzhi.com  发布时间:2005-7-15 14:47:46
的像素信息,非可变图像,无法获取像素信息。所以我们要用srcImg.isMutable() 来判断,原始图像是不是可变图像,然后分两种情况来处理。如果srcImg是可变图像,我们就直接用getPixels()来获取它的像素信息,并保存在srcBuf里。如果srcImg不是可变图像,我们就需要把srcImage画到事先生成的可变图像desImg上,然后再获取desImg的像素信息。
Image desImg = Image.createImage(srcW, srcH);
if (srcImg.isMutable()) { /*如果是可变图像*/
DirectUtils.getDirectGraphics(srcImg.getGraphics()).
getPixels(srcBuf, 0, srcW, 0, 0, srcW, srcH, 444);
} else { /*如果是非可变图像*/
desImg.getGraphics().drawImage(srcImg, 0, 0, 0);
DirectUtils.getDirectGraphics(desImg.getGraphics()).
getPixels(srcBuf, 0, srcW, 0, 0, srcW, srcH, 444);
}

再往下就是缩放算法的重点:插值表的生成。插值表分水平差值表和垂直插值表,我们要分别生成原始图像矩阵的2种插值表,然后利用插值表生成放大缩小后的图像矩阵。由于这个内容比较抽象,很难用文字表述清楚,所以我们用实例进行介绍。
大家看下面这个水平的1*4的表格
-----------------
| 0 | 1 | 2 | 3 |
-----------------
如果要将这个表格放大成1*6的表格,放大的表格比原始表格多出了2个格子,我们只能对这多出来的2个格子进行插值,才能完成放大的操作。现在结合生成水平插值表的代码来完成这个过程。

distance = srcW > desW ? srcW : desW;
for (int i = 0; i <= distance; i++) { /*水平方向*/
tabX[db] = (short) sb;
tems += srcW;
temd += desW;
if (tems > distance) {
tems -= distance;
sb++;
}
if (temd > distance) {
temd -= distance;
db++;
}
}

很明显原始表格宽度srcW = 4;放大后的表格宽度desW = 6;所以distance = desW = 6
接下来进入for循环,我们一步步的演算其循环的过程
-----------------------------------------------
| i| tabX赋值操作| tems | temd| sb | db |
-----------------------------------------------
|0| tabX[0] = 0 | 4 | 6 | 0 | 0 |
-----------------------------------------------
|1| tabX[0] = 0 | 2 | 6 | 1 | 1 |
-----------------------------------------------
|2| tabX[0] = 1 | 6 | 6 | 1 | 2 |
-----------------------------------------------
|3| tabX[0] = 1 | 4 | 6 | 2 | 3 |
-----------------------------------------------
|4| tabX[0] = 2 | 2 | 6 | 3 | 4 |
-----------------------------------------------
|5| tabX[0] = 3 | 6 | 6 | 3 | 5 |
-----------------------------------------------
|6| tabX[0] = 3 | 4 | 6 | 4 | 6 |
-----------------------------------------------
有此得到放大后1*6的表格为下图所示。其中每一个单元格中的数字n表示这个单元格的内容,和原始表格中第n个单元格的内容一样。
--------------------------
| 0 | 1 | 1 | 2 | 3 | 3 |
--------------------------
例如,左图为原始表格,右图为放大的表格
--------------------- --------------------------------
| 红 | 绿 | 兰 | 紫 | | 红 | 绿 | 绿 | 兰 | 紫 | 紫 |
--------------------- --------------------------------
同样,垂直方向的插值表我们也可以用相同的方法获得。

有了2个插值表,下面就可以生成放大和缩小后的图像了。
short[] desBuf = new short[desW * desH];
int dx = 0;
int dy = 0;
int sx = 0;
int sy = 0;
int oldy = -1;
for (int i = 0; i < desH; i++) {
if (oldy == tabY[i]) { /**********情况一**********/
System.arraycopy(desBuf, dy - desW, desBuf, dy, desW);

} else { /**********情况二**********/
dx = 0;
for (int j = 0; j < desW; j++) {
desBuf[dy + dx] = srcBuf[sy + tabX[j]];
dx++;
}
sy += (tabY[i] - oldy) * srcW;

}
oldy = tabY[i];
dy += desW;
}

desBuf是用来保存放大缩小后的图像数据。例如我们把一个4*4像素的图像A放大成6*6的图像B,据前面的介绍我们可以生成2个插值表。tabX = {0,1,1,2,3,3},tabY = {0,1,1,2,3,3}。
在循环中会判断是否oldy 等于 tabY[i],这个操作等同于tabY[i-1]是否等于tabY[i]。如果等于,表示图像B前一行已经生成的数据和即将要生成的第i行数据相同,则只要执行System.arraycopy(desBuf, dy - desW, desBuf, dy, desW)把上一行的数据复制过来即可;如果不等,则需要对照水平插值表tabX生成这一行的数据。
算法演示过程如下:
----------------------------
| i|oldy|tabY[i]|运算情况|
----------------------------
|0|-1 | 0 | 情况2 |
----------------------------
|1| 0 | 1 | 情况2 |
----------------------------
|2| 1 | 1 | 情况1 |
----------------------------
|3| 1 | 2 | 情况2 |
----------------------------
|4| 2 | 3 | 情况2 |
----------------------------
|5| 3 | 3 | 情况1 |
----------------------------
然后我们用desBuf生成最终放大或缩小后的图片
desImg = Image.createImage(desW, desH);
DirectUtils.getDirectGraphics(desImg.getGraphics()).
drawPixels(desBuf, true, 0, desW, 0, 0, desW, desH, 0, 444);
return desImg;

最后要说明一点的是,由于该算法中使用了Image.createImage(w, h)来创建图像,这个函数会创建一个w*h像素的全白可变图像,所以透明图片放大缩小后,背景不再透明,而是白色了,这是j2me本身的缺憾和算法没有关系。对于这个问题,有一个解决办法,就是程序的图片不采用Image来保存,而是采用short[]数组保存,画图的时候用drawPixels()来画图。^-^

上一页  [1] [2] 

[] [返回上一页] [打 印]
文章评论

用户名: 查看更多评论

分 值:100分 85分 70分 55分 40分 25分 10分 0分

内 容:

         (注“”为必填内容。) 验证码: 验证码,看不清楚?请点击刷新验证码