bitmaporbitmapor
今天给各位分享bitmap or的知识,其中也会对bitmapor进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
本文目录
postgresql和mysql的区别Android系统中Bitmap是否有调用recycle方法的必要性什么是BitmapAndroid Bitmap 与 Drawable之间的区别和转换如何空清空TBitmap图象postgresql和mysql的区别区别就是两者意思是不一样具体的不同如下
PostgreSQL是一种特性非常齐全的自由软件的对象-关系型数据库管理系统(ORDBMS),是以加州大学计算机系开发的POSTGRES,4.2版本为基础的对象关系型数据库管理系统。
MySQL是一个关系型数据库管理系统,由瑞典MySQLAB公司开发,属于Oracle旗下产品。MySQL是最流行的关系型数据库管理系统之一,在WEB应用方面,MySQL是最好的RDBMS(RelationalDatabaseManagementSystem,关系数据库管理系统)应用软件之一。MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。MySQL所使用的SQL语言是用于访问数据库的最常用标准化语言。MySQL软件采用了双授权政策,分为社区版和商业版,由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,一般中小型和大型网站的开发都选择MySQL作为网站数据库。
Android系统中Bitmap是否有调用recycle方法的必要性1:Bitmap是否有调用recycle方法的必要性?
A:嵌入式系统总是格外注重空间的问题,不小心的话就会有OOM。但是应用层使用java的android平台有其天然的优势【java语言有自己的垃圾回收,android平台上各个application有自己的process自己的空间】。
无需调用bitmap的理由有:
a.垃圾回收会处理的;
b.当application关闭,process被杀掉,所有这个process占用的空间自然回归系统;
但是,如果你有点洁癖,或者有点理想主义,或者很有控制欲,或者很闲。。。bitmap的recycle函数的调用还是可以是有必要的,理
由有:a.垃圾回收虽然好使,但是有可能的话,我们还是让它少干点活吧。垃圾回收有很大的未来不确定性,会加重未来未知时间点的loading,若有大量bitmap需要垃圾回收处理,那必然垃圾回收需要做的次数就更多也发生地更频繁,小心会造成ANR。但是,若是自己recycle,就可以可控制地分散处理了这些回收任务了。
b.若是launcher那样一直运行的application,它的process一直存在,memory问题还是多多注意下比较好。
Q2:When?
A:Timing的问题在这里很重要。早了就大事不好了,会有这样的Exception:
java.lang.RuntimeException,Canvas:tryingtousearecycledbitmap
android.graphics.Bitmap@44ebeee0,Canvas.java,955
So,怎样才可以保证不会早了呢?
关于图片显示,重要的时间点:
step1:设置进去的时间点;
Step2:画面画出来的时间点;
最保险最笨的做法,在新的图片设置进去以后再recycle掉老的图片,这样做的坏处在于,在某个时间段,你需要的空间是double的【新旧两套都在】;
如果你不偏向于那么做,又有时间,可以考虑后面一个时间点,除了setImage以及其它代码中显示调用那个bitmap的时候我们会检查bitmap,在acticvity变为visible的时候系统还是会去找之前设置进去的bitmap【即使你的onResume方法里面并没有提到去refreshUI,这件事情它也是会去做的,大概不然它就不知道这次该显示些什么了】。所以,在UI线程里面,在一个不可能被打断的方法里面,是先设置新的bitmap还是先recycle旧的图片是没有影响的。
譬如说mBitmap.recycle();
mBitmap=…..//设置
mImageView.setImage(mBitmap);
这样的代码是完全可以的。
后面这样的做法,最重要的就是确保:在UI线程【因为设置UI显示只能在UI主线程里】里面一个不可能被打断的方法里面。这个是为了确保在两者之间UI主线程不可能被打断,不可能刚好从invisible变成visible。
所以,特别小心两种东西:
1.多线程【个人觉得最好不要在其他线程里面调用UI用过的bitmap的recycle方法,多线程之间是很难保证时间顺序的,暂时没有想出一种在backgroundthread里面recycle的合理的方式】;
2.非及时发生的方法:譬如,发intent啊,发notify啊去通知UI主线程去做UI重新刷新并不能替代mImageView.setImage(mBitmap);这样的句子。完全有可能,你确实发了intent出去了,但是目标activity之一还没有做UI重新设置【Q:maybe没收到or收到但还是等待处理,不确定这两种可能是不是都有可能】,这个时候这个acitivity变成visible了,系统仍然试图找旧的图片,找不到了就会报exception了。
PS:java.lang.RuntimeException,Canvas:tryingtousearecycledbitmapandroid.graphics.Bitmap@44ebeee0,Canvas.java,955这样的exception可能也许你并不能够看到,默认的log里面好像只能看到uncaughtexception,第一次看到是在monkey的events.log里面,若你知道怎么打开相应手机这方面的logtrace应该也是可以看到的。
什么是Bitmapa)Bitmap如何做到多维交叉计算的?
Bit即比特,是目前计算机系统里边数据的最小单位,8个bit即为一个Byte。一个bit的值,或者是0,或者是1;也就是说一个bit能存储的最多信息是2。
Bitmap可以理解为通过一个bit数组来存储特定数据的一种数据结构;由于bit是数据的最小单位,所以这种数据结构往往是非常节省存储空间。比如一个公司有8个员工,现在需要记录公司的考勤记录,传统的方案是记录下每天正常考勤的员工的ID列表,比如2012-01-01:[1,2,3,4,5,6,7,8]。假如员工ID采用byte数据类型,则保存每天的考勤记录需要N个byte,其中N是当天考勤的总人数。另一种方案则是构造一个8bit(01110011)的数组,将这8个员工跟员工号分别映射到这8个位置,如果当天正常考勤了,则将对应的这个位置置为1,否则置为0;这样可以每天采用恒定的1个byte即可保存当天的考勤记录。
综上所述,Bitmap节省大量的存储空间,因此可以被一次性加载到内存中。再看其结构的另一个更重要的特点,它也显现出巨大威力:就是很方便通过位的运算(AND/OR/XOR/NOT),高效的对多个Bitmap数据进行处理,这点很重要,它直接的支持了多维交叉计算能力。比如上边的考勤的例子里,如果想知道哪个员工最近两天都没来,只要将昨天的Bitmap和今天的Bitmap做一个按位的“OR”计算,然后检查那些位置是0,就可以得到最近两天都没来的员工的数据了,比如:
Android Bitmap 与 Drawable之间的区别和转换Bitmap-称作位图,一般位图的文件格式后缀为bmp,当然编码器也有很多如RGB565、RGB888。作为一种逐像素的显示对象执行效率高,但是缺点也很明显存储效率低。我们理解为一种存储对象比较好。
Drawable-作为Android平下通用的图形对象,它可以装载常用格式的图像,比如GIF、PNG、JPG,当然也支持BMP,当然还提供一些高级的可视化对象,比如渐变、图形等。
AbitmapisaDrawable.ADrawableisnotnecessarilyabitmap.Likeallthumbsarefingersbutnotallfingersarethumbs.
Bitmap是Drawable.Drawable不一定是Bitmap.就像拇指是指头,但不是所有的指头都是拇指一样.
TheAPIdictates:API规定:
Thoughusuallynotvisibletotheapplication,Drawablesmaytakeavarietyofforms:尽管通常情况下对于应用是不可见的,Drawables可以采取很多形式:
Bitmap:thesimplestDrawable,aPNGorJPEGimage.Bitmap:简单化的Drawable,PNG或JPEG图像.
NinePatch:anextensiontothePNGformatallowsittospecify
informationabouthowtostretchitandplacethingsinsideofit.
Shape:containssimpledrawingcommandsinsteadofarawbitmap,allowingittoresizebetterinsomecases.
Layers:acompounddrawable,whichdrawsmultipleunderlyingdrawablesontopofeachother.
States:acompounddrawablethatselectsoneofasetofdrawablesbasedonitsstate.
Levels:acompounddrawablethatselectsoneofasetofdrawablesbasedonitslevel.
Scale:acompounddrawablewithasinglechilddrawable,whoseoverallsizeismodifiedbasedonthecurrentlevel.
如何空清空TBitmap图象由Delphi中的图像灰度化代码看基本图像处理
基础篇]
首先看一段实现24位色图像灰度化转换的代码
procedureGrayscale(constBitmap:TBitmap);
var
X:Integer;
Y:Integer;
R,G,B,Gray:Byte;
Color:TColor;
begin
forY:=0to(Bitmap.Height-1)do
begin
forX:=0to(Bitmap.Width-1)do
begin
Color:=Bitmap.Canvas.Pixels[X,Y];
R:=Colorand$FF;
G:=(Colorand$FF00)shr8;
B:=(Colorand$FF0000)shr16;
Gray:=Trunc(0.3*R+0.59*G+0.11*B);
Bitmap.Canvas.Pixels[X,Y]:=Grayshl16orGrayshl8orGray;
end
end
end;
{这段代码效率是非常低的,但可以方便我们理解同时一些问题}
Delphi的帮助中对TColor已经有了详细的描述,这可以方便我们理解上面的代码!
首先看:
R:=Colorand$FF;
G:=(Colorand$FF00)shr8;
B:=(Colorand$FF0000)shr16;
这是段常见的从TColor中提取三原色的代码,但它是什么意思呢?
首先应该知道and是与(.)运算,0.1=0,0.0=0,1.1=1,以取绿色为例:$FF00实际上就是$00FF00,它与一个TColor类型数按位进行与运算后,表示红色和绿色的位都变为了$00,而表示绿色的部分不变(0,1和1进行与运算值都不变),再右移8位,自然就获得了绿色值的8位表示!
再获得三原色的值后,就是计算灰度值,0.3*Red+0.59*Green+0.11*Blue这是求加权平均值的公式。(因为人眼对颜色的敏感度不同,所以权值不同,就像在pf16bit中用了6位表示绿色,其它两种颜色只用了5位,这问题以后另写文章说明)
然后就是像素颜色信息的写回,刚才是右移,现在自然就是左移,而或(+)运算就是(0+1=1,0+0=0,1+1=1),举个简单例子就是:($FFshl16=$FF0000)or($FFshl8=$FF00)or$FF=$FFFFFF,其实这里的或运算当然也可以用+代替。
虽然上面的代码实现了24位色图像的灰度化,但当图像比较大时,速度非常慢,为什么?查看相关VCL代码可知调用Bitmap.Canvas.Pixels获取,写入像素的颜色信息实际上是利用了APIGetPixel、SetPixel,这种方法是非常低效的!(唯一的好处是在进行一些和颜色无关的操作,如图像的旋转,翻转时不需要因为PixelFormat的不同而修改代码)所以应该换一种更高效的访问像素点数据的方法,如用APIGetDIBits、SetDIBits,但这种方法比较复杂,好在Delphi3以后版本的TBitmap中提供了Scanline。利用Scanline可以快速对像素进行访问!
还是以24位色(PixelFormats=pf24bit)为例,可改写为:
procedureGrayscale(constBitmap:TBitmap);
const
PixelCountMax=32768;
type
pRGBTripleArray=^TRGBTripleArray;
TRGBTripleArray=ARRAY[0..PixelCountMax-1]OFTRGBTriple;
var
Row:pRGBTripleArray;
X:Integer;
Y:Integer;
Gray:Byte;
begin
forY:=0to(Bitmap.Height-1)do
begin
Row:=Bitmap.ScanLine[Y];
forX:=0to(Bitmap.Width-1)do
begin
Gray:=Trunc(0.3*Row^[X].rgbtRed+0.59*Row^[X].rgbtGreen+0.11*Row^[X].rgbtBlue);
Row^[X].rgbtRed:=Gray;
Row^[X].rgbtGreen:=Gray;
Row^[X].rgbtBlue:=Gray;
end;
end;
end;
上面的例子用了一个TRGBTriple数组
PRGBTriple=^TRGBTriple;
tagRGBTRIPLE=packedrecord
rgbtBlue:Byte;
rgbtGreen:Byte;
rgbtRed:Byte;
end;
TRGBTriple=tagRGBTRIPLE;
这种方法会限制位图的大小,但一般不用理会,直接用TBitmap可处理不了那么大的位图
当然也可用指针的移动实现,实测结果这样更快~~~
procedureGrayscale(constBitmap:TBitmap);
var
X:Integer;
Y:Integer;
PRGB:pRGBTriple;
Gray:Byte;
begin
forY:=0to(Bitmap.Height-1)do
begin
PRGB:=Bitmap.ScanLine[Y];
forX:=0to(Bitmap.Width-1)
dobegin
Gray:=Trunc(0.3*PRGB^.rgbtRed+0.59*PRGB^.rgbtGreen+0.11*PRGB^.rgbtBlue);
PRGB^.rgbtRed:=Gray;
PRGB^.rgbtGreen:=Gray;
PRGB^.rgbtBlue:=Gray;
Inc(PRGB);
end;
end;
end;
[颜色篇]
在上面提到了,那灰度化代码只能适用于24位色(PixelFormats=pf24bit),为什么?看看记录类型tagRGBTRIPLE,正好24位,所以这样只能处理24位色图!
那怎么处理其他的位图呢?
先对这各种类型的位图做些简单的介绍~~~
pf1bit:
每个像素只需要用一位表示,如调色板定义的是黑白两种颜色(0为黑,1为白),这时只能用位操作访问像素信息!如定义
varP:PByte
forY:=0to(Bitmap.Height-1)do
begin
p:=Bitmap.ScanLine[Y];
forX:=0to(Bitmap.width-1)DIV8+1do
begin
p^:=1or2or4or8or16or32or64or128;
Inc(PRGB,3);
end;
end;
p^:=1or2or4or8or16or32or64or128;
这行代码什么意思呢?1=1(二进制),2=10(二进制),4=100(二进制),8=1000(二进制)...
结合上篇中解释了的或运算,很容易理解就以八个字位为单位,给其赋上颜色信息!
pf4bit:
和pf1bit位图一样,操作pf4bit位图也需要用位操作。
pf8bit:
可直接利用Byte、TByteArray,但用Scanline取的值表示的只是调色板上颜色的索引。
pf15bit和pf16bit:
这两种位图都是16位的,pf15bit是第一位为0,后15位的每5位分别表示红、绿、蓝。而pf16bit中绿色占6位,其它两种颜色占用5位(人眼对绿色比较敏感)!
pf24bit位图转pf15bit位图代码
var
Row24:pRGBTriple;
Row15:PWord;
forj:=0TOBitmap.Height-1DO
begin
Row15:=Bitmap15.Scanline[j];
Row24:=Bitmap24.Scanline[j];
fori:=0TOBitmap.Width-1DO
begin
withRow24^do
Row15^:=(rgbtRedShr3)Shl10or(rgbtGreenShr3)Shl5or(rgbtBlueShr3);
Inc(Row24);
Inc(Row15);
end
end;
pf24bit和pf32bit:
pf24bit上面的已多次用到,就不多说了。而pf32bit和pf24bit一样,用24位(前24位)来记录三原色的颜色信息!
PRGBQuad=^TRGBQuad;
tagRGBQUAD=packedrecord
rgbBlue:Byte;
rgbGreen:Byte;
rgbRed:Byte;
rgbReserved:Byte;
end;
TRGBQuad=tagRGBQUAD;
如果要修改上面的程序,就是简单的PRGBQuad替换PRGBTriple,TRGBQuad替换TRGBTriple的过程~
测试表明在pf32bit中利用Scanline处理图像要比pf24bit快。
所以除了单色图(PixelFormats=pf1bit)外(没必要),其它都可转外32位色实现灰度化。这也是一种比较可行的方法!
[优化篇]
还以上篇中给出的灰度化代码为例
procedureGrayscale(constBitmap:TBitmap);
var
X:Integer;
Y:Integer;
PRGB:pRGBTriple;
Gray:Byte;
begin
forY:=0to(Bitmap.Height-1)do
begin
PRGB:=Bitmap.ScanLine[Y];
forX:=0to(Bitmap.Wid
th-1)dobegin
Gray:=Trunc(0.3*PRGB^.rgbtRed+0.59*PRGB^.rgbtGreen+0.11*PRGB^.rgbtBlue);
PRGB^.rgbtRed:=Gray;
PRGB^.rgbtGreen:=Gray;
PRGB^.rgbtBlue:=Gray;
Inc(PRGB);
end;
end;
end;
实
际应用中,这种方法已经很快了,但实际上还存在可以优化的余地,什么呢?Gray:=Trunc(0.3*Red+0.59*Green+0.11*Blue);//这句用的是浮点运算
在图像处理中,速度就是生命,能不用浮点运算,就最好不要用!
Gray:=(30*Red+59*Green+11*Blue)div100;
虽然这样一改,运算次数多了一次,但在我的雷鸟1.1G上,处理速度大概能提高5%左右!而同主频下(或略低,如Athlon1600+相当于P41.6G)AMD的CPU浮点运算能力比Intel的较强,整数运算能力较弱,所以用Intel的CPU在这里更能体现出优势!
注:xdiv100和Trunc(x/100)的效果是相同的,但查看其汇编代码可知一个用的指令是div,而另一个是fdiv(即进行浮点运算),还要调用函数Trunc,其处理速度差距非常大,所以能用xdiv100的时候就不要用Trunc(x/100)。
但这还不是最快的,再看一个:
Gray:=HiByte(77*Red+151*Green+28*Blue);
即
Gray:=(77*Red+151*Green+28*Blue)shr8;
(建议用后一种,不要调用函数)
这种方法比最原始的方法快了近3/4!
什么意思呢?用77,151,28分别除以256试试~~~
移位是什么意思呢,和10进制的进位,退位联系一下,是不是可以近似的理解为乘除2的n次方呢?当然这和真正意义的乘除法是不一样的!比如shr(右移),和真正的除法相比,比如shr1,只有最后一个字位为0时(既为2的倍数),它才等于除2!如二进制数110(6)右移1位变为11(3),和6/2=3结果相同。
当然这和一开始的灰度化效果有了些误差!
如果允许存在更大的误差,还可以考虑另一种方法:
Gray:=(Redshr2)+(Redshr4)+(Greenshr1)+(Greenshr4)+(Blueshr3);
连乘法都没用,完全用移位实现,结合上面的解释,用除法来理解该表达式,其值只是约等于(0.3125*Red+0.5625*Green+0.125*Blue),和一开始的加权平均值有了比较大的误差!但如果对速度有苛刻的要求的话,可以怎么用!这比上一种方法还能再快5%!
OK,关于bitmap or和bitmapor的内容到此结束了,希望对大家有所帮助。