前一篇文章讲述了Android触屏setOnTouchListener实现突破缩放、移动、绘制和添加水印,继续我的"随手拍"项目完成给图片添加相框、圆形圆角显示图片和图像合成的功能介绍.希望文章对大家有所帮助.

一. 打开图片和显示assets文件中图片

首先,对XML中activity_main.xml进行布局,通过使用RelativeLayout相对布局完成(XML代码后面附).然后,在Mainctivity.java中public class MainActivity extends Activity函数添加代码如下,添加点击按钮监听事件:

[java]  view plain  copy  
  1. //控件
  2. private Button openImageBn;            //打开图片
  3. private Button showImageBn;            //显示assets资源图片
  4. private Button showImageBn1;           //模式1加成
  5. private Button showImageBn2;           //模式2加成
  6. private Button roundImageBn;           //圆角图片
  7. private ImageView imageShow;           //显示图片
  8. //自定义变量
  9. private Bitmap bmp;                    //原始图片
  10. private final int IMAGE_OPEN = 0;      //打开图片
  11. private Canvas canvas;                 //画布
  12. private Paint paint;                   //画刷
  13. @Override
  14. protected void onCreate(Bundle savedInstanceState) {
  15. super.onCreate(savedInstanceState);
  16. setContentView(R.layout.activity_main);
  17. //打开图片
  18. openImageBn = (Button)findViewById(R.id.button1);
  19. imageShow = (ImageView) findViewById(R.id.imageView1);
  20. openImageBn.setOnClickListener(new OnClickListener() {
  21. @Override
  22. public void onClick(View v) {
  23. Intent intent = new Intent(Intent.ACTION_PICK,
  24. android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
  25. startActivityForResult(intent, IMAGE_OPEN);
  26. }
  27. });
  28. if (savedInstanceState == null) {
  29. getFragmentManager().beginTransaction()
  30. .add(R.id.container, new PlaceholderFragment())
  31. .commit();
  32. }
  33. }
  34. //打开图片
  35. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  36. super.onActivityResult(requestCode, resultCode, data);
  37. if(resultCode==RESULT_OK && requestCode==IMAGE_OPEN) {
  38. Uri imageFileUri = data.getData();
  39. DisplayMetrics dm = new DisplayMetrics();
  40. getWindowManager().getDefaultDisplay().getMetrics(dm);
  41. int width = dm.widthPixels;    //手机屏幕水平分辨率
  42. int height = dm.heightPixels;  //手机屏幕垂直分辨率
  43. try {
  44. //载入图片尺寸大小没载入图片本身 true
  45. BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
  46. bmpFactoryOptions.inJustDecodeBounds = true;
  47. bmp = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageFileUri), null, bmpFactoryOptions);
  48. int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)height);
  49. int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)width);
  50. //inSampleSize表示图片占原图比例 1表示原图
  51. if(heightRatio>1&&widthRatio>1) {
  52. if(heightRatio>widthRatio) {
  53. bmpFactoryOptions.inSampleSize = heightRatio;
  54. }
  55. else {
  56. bmpFactoryOptions.inSampleSize = widthRatio;
  57. }
  58. }
  59. //图像真正解码 false
  60. bmpFactoryOptions.inJustDecodeBounds = false;
  61. bmp = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageFileUri), null, bmpFactoryOptions);
  62. imageShow.setImageBitmap(bmp);
  63. }
  64. catch(FileNotFoundException e) {
  65. e.printStackTrace();
  66. }
  67. }  //end if
  68. }

    上面点击"打开"按钮能实现打开图片,而在讲述为图片添加边框时,它其实就是通过两张或多张图片的合成实现的.
    在jacpy.may《Android图片处理总结》文档中建议图片不要放在drawable目录下,因为屏幕分辨率会影响图片的大小.最好放在assets目录里,它代表应用无法直接访问的原生资源(通常加载PNG透明图实现边框合成),只能以流的方式读取并且小于1M.
    读取assets文件夹中图片的方法如下,首先手动添加PNG图片至assets目录,然后在omCreate函数中添加如下代码:

[java]  view plain  copy  
  1. //显示assets中图片
  2. showImageBn = (Button)findViewById(R.id.button2);
  3. showImageBn.setOnClickListener(new OnClickListener() {
  4. @Override
  5. public void onClick(View v) {
  6. Bitmap bitmap = getImageFromAssets("image01.png");
  7. imageShow.setImageBitmap(bitmap);
  8. }
  9. });

   再通过自定义函数getImageFromAssets实现获取图片"image01.png":

[java]  view plain  copy  
  1. //获取assets中资源并转换为Bitmap
  2. private Bitmap getImageFromAssets(String fileName)
  3. {
  4. //Android中使用assets目录存放资源,它代表应用无法直接访问的原生资源
  5. Bitmap imageAssets = null;
  6. AssetManager am = getResources().getAssets();
  7. try {
  8. InputStream is = am.open(fileName);
  9. imageAssets = BitmapFactory.decodeStream(is);
  10. is.close();
  11. } catch(IOException e) {
  12. e.printStackTrace();
  13. }
  14. return imageAssets;
  15. }

   显示效果如下图所示:
             
   其中XML代码如下:

[html]  view plain  copy  
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:id="@+id/container"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. tools:context="com.example.touchimagetest.MainActivity"
  7. tools:ignore="MergeRootFrame" >
  8. <!-- 底部添加按钮 -->
  9. <RelativeLayout
  10. android:id="@+id/MyLayout_bottom"
  11. android:orientation="horizontal"
  12. android:layout_width="fill_parent"
  13. android:layout_height="50dp"
  14. android:layout_alignParentBottom="true"
  15. android:gravity="center">
  16. <LinearLayout
  17. android:layout_width="match_parent"
  18. android:layout_height="match_parent"
  19. android:orientation="horizontal"
  20. android:layout_alignParentBottom="true" >
  21. <Button
  22. android:id="@+id/button1"
  23. android:layout_width="wrap_content"
  24. android:layout_height="match_parent"
  25. android:layout_weight="1"
  26. android:text="打开" />
  27. <Button
  28. android:id="@+id/button2"
  29. android:layout_width="wrap_content"
  30. android:layout_height="match_parent"
  31. android:layout_weight="1"
  32. android:text="显示" />
  33. <Button
  34. android:id="@+id/button3"
  35. android:layout_width="wrap_content"
  36. android:layout_height="match_parent"
  37. android:layout_weight="1"
  38. android:text="边框" />
  39. <Button
  40. android:id="@+id/button4"
  41. android:layout_width="wrap_content"
  42. android:layout_height="match_parent"
  43. android:layout_weight="1"
  44. android:text="桃心" />
  45. <Button
  46. android:id="@+id/button5"
  47. android:layout_width="wrap_content"
  48. android:layout_height="match_parent"
  49. android:layout_weight="1"
  50. android:text="圆形" />
  51. </LinearLayout>
  52. </RelativeLayout>
  53. <!-- 顶部显示图片 -->
  54. <RelativeLayout
  55. android:id="@+id/Content_Layout"
  56. android:orientation="horizontal"
  57. android:layout_above="@id/MyLayout_bottom"
  58. android:layout_width="fill_parent"
  59. android:layout_height="wrap_content"
  60. android:layout_alignParentTop="true"
  61. android:background="#000000"
  62. android:gravity="center">
  63. <ImageView
  64. android:id="@+id/imageView1"
  65. android:layout_width="fill_parent"
  66. android:layout_height="fill_parent"
  67. android:layout_gravity="center_horizontal" />
  68. </RelativeLayout>
  69. </RelativeLayout>

二. 添加相框与图片合成

    然后开始完成图片合成的工作,这里我采用两种方法完成.继续在onCreate函数中添加代码:
[java]  view plain  copy  
  1. //模式1合成图片
  2. showImageBn1 = (Button)findViewById(R.id.button3);
  3. showImageBn1.setOnClickListener(new OnClickListener() {
  4. @Override
  5. public void onClick(View v) {
  6. Bitmap bitmap = getImageFromAssets("image01.png");
  7. addFrameToImage(bitmap);
  8. }
  9. });

   通过自定义函数addFrameToImage实现加载图片合成.首先创建一个空的可变为图对象,它的大小和配置与打开的图像相同,随后构建一个Canvas对象和一个Paint对象,在画布上绘制第一个位图对象,它成为了合成操作的目标.
    现在设置Paint对象上的过渡模式,通过传入一个定义操作模式的常量,实例化一个新的PorterDuffXfermode对象.然后在Canvas对象上绘制第二个位图对象,并将ImageView设置为新的位图对象.代码如下:

[java]  view plain  copy  
  1. //图片合成1
  2. private void addFrameToImage(Bitmap bm) //bmp原图(前景) bm资源图片(背景)
  3. {
  4. Bitmap drawBitmap =Bitmap.createBitmap(bmp.getWidth(),
  5. bmp.getHeight(), bmp.getConfig());
  6. canvas = new Canvas(drawBitmap);
  7. paint = new Paint();
  8. canvas.drawBitmap(bmp, 0, 0, paint);
  9. paint.setXfermode(new PorterDuffXfermode(android.
  10. graphics.PorterDuff.Mode.LIGHTEN));
  11. //对边框进行缩放
  12. int w = bm.getWidth();
  13. int h = bm.getHeight();
  14. //缩放比 如果图片尺寸超过边框尺寸 会自动匹配
  15. float scaleX = bmp.getWidth()*1F / w;
  16. float scaleY = bmp.getHeight()*1F / h;
  17. Matrix matrix = new Matrix();
  18. matrix.postScale(scaleX, scaleY);   //缩放图片
  19. Bitmap copyBitmap =  Bitmap.createBitmap(bm, 0, 0, w, h, matrix, true);
  20. canvas.drawBitmap(copyBitmap, 0, 0, paint);
  21. imageShow.setImageBitmap(drawBitmap);
  22. }

   第二种方法是参照《Android多媒体开发高级编程》,但是它图片十四合成效果不是很好:

[java]  view plain  copy  
  1. //模式2合成图片
  2. showImageBn2 = (Button)findViewById(R.id.button4);
  3. showImageBn2.setOnClickListener(new OnClickListener() {
  4. @Override
  5. public void onClick(View v) {
  6. Bitmap bitmap = getImageFromAssets("image07.png");
  7. //第二种合成方法
  8. imageShow.setImageBitmap(addFrameToImageTwo(bitmap));
  9. }
  10. });

    然后通过自定义函数实现:

[java]  view plain  copy  
  1. //图片合成
  2. private Bitmap addFrameToImageTwo(Bitmap frameBitmap) //bmp原图 frameBitmap资源图片(边框)
  3. {
  4. //bmp原图 创建新位图
  5. int width = bmp.getWidth();
  6. int height = bmp.getHeight();
  7. Bitmap drawBitmap =Bitmap.createBitmap(width, height, Config.RGB_565);
  8. //对边框进行缩放
  9. int w = frameBitmap.getWidth();
  10. int h = frameBitmap.getHeight();
  11. float scaleX = width*1F / w;        //缩放比 如果图片尺寸超过边框尺寸 会自动匹配
  12. float scaleY = height*1F / h;
  13. Matrix matrix = new Matrix();
  14. matrix.postScale(scaleX, scaleY);   //缩放图片
  15. Bitmap copyBitmap =  Bitmap.createBitmap(frameBitmap, 0, 0, w, h, matrix, true);
  16. int pixColor = 0;
  17. int layColor = 0;
  18. int newColor = 0;
  19. int pixR = 0;
  20. int pixG = 0;
  21. int pixB = 0;
  22. int pixA = 0;
  23. int newR = 0;
  24. int newG = 0;
  25. int newB = 0;
  26. int newA = 0;
  27. int layR = 0;
  28. int layG = 0;
  29. int layB = 0;
  30. int layA = 0;
  31. float alpha = 0.8F;
  32. float alphaR = 0F;
  33. float alphaG = 0F;
  34. float alphaB = 0F;
  35. for (int i = 0; i < width; i++)
  36. {
  37. for (int k = 0; k < height; k++)
  38. {
  39. pixColor = bmp.getPixel(i, k);
  40. layColor = copyBitmap.getPixel(i, k);
  41. // 获取原图片的RGBA值
  42. pixR = Color.red(pixColor);
  43. pixG = Color.green(pixColor);
  44. pixB = Color.blue(pixColor);
  45. pixA = Color.alpha(pixColor);
  46. // 获取边框图片的RGBA值
  47. layR = Color.red(layColor);
  48. layG = Color.green(layColor);
  49. layB = Color.blue(layColor);
  50. layA = Color.alpha(layColor);
  51. // 颜色与纯黑色相近的点
  52. if (layR < 20 && layG < 20 && layB < 20)
  53. {
  54. alpha = 1F;
  55. }
  56. else
  57. {
  58. alpha = 0.3F;
  59. }
  60. alphaR = alpha;
  61. alphaG = alpha;
  62. alphaB = alpha;
  63. // 两种颜色叠加
  64. newR = (int) (pixR * alphaR + layR * (1 - alphaR));
  65. newG = (int) (pixG * alphaG + layG * (1 - alphaG));
  66. newB = (int) (pixB * alphaB + layB * (1 - alphaB));
  67. layA = (int) (pixA * alpha + layA * (1 - alpha));
  68. // 值在0~255之间
  69. newR = Math.min(255, Math.max(0, newR));
  70. newG = Math.min(255, Math.max(0, newG));
  71. newB = Math.min(255, Math.max(0, newB));
  72. newA = Math.min(255, Math.max(0, layA));
  73. //绘制
  74. newColor = Color.argb(newA, newR, newG, newB);
  75. drawBitmap.setPixel(i, k, newColor);
  76. }
  77. }
  78. return drawBitmap;
  79. }

   它的运行效果如下所示,其中前2附图是方法一,但是它的合成效果不是很优秀,而第三张图是第二种方法,但是它的响应时间稍微要长些.
             

   在第一种方法通过PoterDuffXfermode类作为过渡模式,该类因Thomas Porter和Tom Duff而得名,他们于1984年在ACM SIGGRAPH计算机图形学发表“Compositing digital images(合成数字图像)”的文章,它介绍了彼此重叠绘制图像的不同规则.这些规则定义了哪些图像的哪些部分将出现在结果输出中.
    在Android的PorterDuff.Mode类中列举了Porter和Duff及其他更多人制定的规则.
    android.graphics.PorterDuff.Mode.SRC:此规则意味着只绘制源图像,当前它正是应用此规则的Paint对象.
    android.graphics.PorterDuff.Mode.DST:此规则意味着只显示目标图像,在已有画布上的初始图像.
    如下图所示,定义Mode值如下:
                                   
    其中,有4个规则定义了当一幅图像放置在另一幅图像上时如何合成这两幅图像,它是我们经常使用的值:
    android.graphics.PorterDuff.Mode.LIGHTEN:获得每个位置上两幅图像中最亮的像素并显示.
    android.graphics.PorterDuff.Mode.DARKEN:获得每个位置上两幅图像中最暗的像素并显示.
    android.graphics.PorterDuff.Mode.MULTIPLY:将每个位置的两个像素相乘,除以255,使用该值创建一个新的像素进行显示.结果颜色=顶部颜色*底部颜色/255.
    android.graphics.PorterDuff.Mode.SCREEN:反转每个颜色,执行相同操作.结果颜色=255-(((255-顶部颜色)*(255-底部颜色))/255)

三. 圆形和圆角矩形显示图片

   最后讲述如何实现圆形和圆角矩形显示图片,在onCreate函数中添加如下代码:
[java]  view plain  copy  
  1. //圆角合成图片
  2. roundImageBn = (Button)findViewById(R.id.button5);
  3. roundImageBn.setOnClickListener(new OnClickListener() {
  4. @Override
  5. public void onClick(View v) {
  6. imageShow.setImageBitmap(getRoundedCornerBitmap(bmp) );
  7. }
  8. });

   然后通过自定义函数getRoundedCornerBitmap实现圆形:

[java]  view plain  copy  
  1. //生成圆角图片
  2. private Bitmap getRoundedCornerBitmap(Bitmap bitmap)
  3. {
  4. Bitmap roundBitmap = Bitmap.createBitmap(bitmap.getWidth(),
  5. bitmap.getHeight(), Config.ARGB_8888);
  6. Canvas canvas = new Canvas(roundBitmap);
  7. int color = 0xff424242;
  8. Paint paint = new Paint();
  9. //设置圆形半径
  10. int radius;
  11. if(bitmap.getWidth()>bitmap.getHeight()) {
  12. radius = bitmap.getHeight()/2;
  13. }
  14. else {
  15. radius = bitmap.getWidth()/2;
  16. }
  17. //绘制圆形
  18. paint.setAntiAlias(true);
  19. canvas.drawARGB(0, 0, 0, 0);
  20. paint.setColor(color);
  21. canvas.drawCircle( bitmap.getWidth()/ 2, bitmap.getHeight() / 2, radius, paint);
  22. paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
  23. canvas.drawBitmap(bitmap, 0, 0, paint);
  24. return roundBitmap;
  25. }

   同样,如果把该函数里面内容替换即可实现圆形矩形显示图片:

[java]  view plain  copy  
  1. private Bitmap getRoundedCornerBitmap(Bitmap bitmap)
  2. {
  3. //绘制圆角矩形
  4. Bitmap roundBitmap = Bitmap.createBitmap(bitmap.getWidth(),
  5. bitmap.getHeight(), Config.ARGB_8888);
  6. Canvas canvas = new Canvas(roundBitmap);
  7. int color = 0xff424242;
  8. Paint paint = new Paint();
  9. Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
  10. RectF rectF = new RectF(rect);
  11. float roundPx = 80;      //转角设置80
  12. //绘制
  13. paint.setAntiAlias(true);
  14. canvas.drawARGB(0, 0, 0, 0);
  15. paint.setColor(color);
  16. canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
  17. paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
  18. canvas.drawBitmap(bitmap, rect, rect, paint);
  19. }

   运行结果如下图所示:
                                   

    总结:
    该文章主要讲述如何给图像增加相框,圆角显示图像和图像合成的介绍.里面主要通过源码并有详细的过程,为什么要写这篇文章?因为在图像处理中我认为这种添加边框、改变边框、图片合成都属于同一种类型的变化和渲染.该图像处理软件还没有整合,推荐大家看下面资料中两本书.
    
最后希望文章对大家有所帮助,如果有不足或错误的地方请见谅!不论如何,我觉得这篇文章自己写得不错,自己先给自己一个赞吧!加油\(^o^)/~
    下载地址:http://download.csdn.net/detail/eastmount/8102845
    源码基本格式如下图所示:

(By:Eastmount 2014-10-31 夜3点 http://blog.csdn.net/eastmount)
参考资料与推荐博文:

1.最该感谢的是两本书的作者《Android多媒体开发高级编程》和《Android图片处理总结 著:jacpy.may》,网上很多资料都是它们.
2.android图像处理系列之六--给图片添加边框(下)-图片叠加 
作者-SJF0115 他是转载了该书的一些文章,也非常不错.
3.Android 图片合成:添加蒙板效果 不规则相框 透明度渐变效果的实现
作者-HappyDelano 非常不错的文章,讲述了4张图实现桃心显示的效果.
4.Android图片合成 作者-johnlxj 讲述了图片合成的实现过程.
5.Android 完美实现图片圆角和圆形(对实现进行分析)
作者-鸿洋_ 该作者很多android文章都非常不错
6.android 画图之setXfermode 作者-lipeng88213 推荐起链接的Android图片倒影
7.Android ImageView点击选中后添加边框 作者-黑米粥 该方法在切换图片中实用
8.android 轻松实现在线即时聊天【图片、语音、表情、文字】 作者-anonymousblogs


Android给图像添加相框、圆形圆角显示图片、图像合成知识相关推荐

  1. [Android] 给图像添加相框、圆形圆角显示图片、图像合成知识

        前一篇文章讲述了Android触屏setOnTouchListener实现突破缩放.移动.绘制和添加水印,继续我的"随手拍"项目完成给图片添加相框.圆形圆角显示图片和图像合 ...

  2. [Android] 给图像加入相框、圆形圆角显示图片、图像合成知识

        前一篇文章讲述了Android触屏setOnTouchListener实现突破缩放.移动.绘制和加入水印,继续我的"随手拍"项目完毕给图片加入相框.圆形圆角显示图片和图像合 ...

  3. 给图像添加相框、圆形圆角显示图片、图像合成知识

    前一篇文章讲述了Android触屏setOnTouchListener实现突破缩放.移动.绘制和添加水印,继续我的"随手拍"项目完成给图片添加相框.圆形圆角显示图片和图像合成的功能 ...

  4. android如何给整个视图view圆角显示

    关于如何给一个view设置圆角,有哪些方法呢? 1.给该view设置一个圆角的背景,这是最常见的用法.如以下代码: round_bg.xml <?xml version="1.0&qu ...

  5. opengl生成图片php,(转)使用OpenGL显示图像(七)Android OpenGLES2.0——纹理贴图之显示图片...

    转:http://blog.csdn.net/junzia/article/details/52842816 前面几篇博客,我们将了Android中利用OpenGL ES 2.0绘制各种形体,并在上一 ...

  6. 微信小程序 解决圆形头像显示图片不完全问题

    最近在做微信小程序,遇到这样一个难题,绘制一个圆形的头像,但是有的图片会因为宽度大于高度而致使图片在圆形区域内显示不全,为解决这个问题,我采用了以下办法,现贴出代码共享给大家,大家如果有更好的解决方案 ...

  7. Qt案例:实现显示图片

    效果图: 17.1 组件使用 17.1.1 QDockWidget 含义:停靠区窗口,和状态栏.标题栏是一个等级 属性: allowedAreas:设置允许停靠区域,或者使用代码setAllowedA ...

  8. [Android开发]不操作Bitmap实现圆角ImageView、圆形ImageView,支持添加背景圆形或圆角矩形边框、边框支持渐变色

    一.主要解决的使用场景 1.使用Glide加载图片时,我们往往需要设置加载中和加载失败的图片,app中不同的页面的显示的图片可能是圆形,也可能是圆角矩形图,Glide设置placeholder和err ...

  9. Android 自定义View 圆形圆角图片

    [Android 自定义View 圆形圆角图片] 基于Xfermode 实现 1.概述 在很久以前也写过一个利用Xfermode 实现圆形.圆角图片的(Android 完美实现图片圆角和圆形(对实现进 ...

最新文章

  1. Python学习之函数及流程控制
  2. Hibernate 逆向工程生成POJO类和映射文件
  3. python比较运算符重载_python运算符重载
  4. sum函数两个同行的元素相加_Excel函数公式大全:利用sum函数进行汇总以及对多个汇总进行求和...
  5. 攻防世界web2(逆向加密算法)
  6. java 页面传值_java-jsp springmvc-controller 传值到页面的方法
  7. C++基础::运算符重载
  8. 在MFC程序中显示 JPG/GIF图像
  9. Gradle、 Gradle Android Plugin 、 Build Tools之间关系
  10. 机器学习实战之路—— 1 线性回归 (二)
  11. wpa_supplicant使用
  12. oracle静默安装集群,Oracle RAC 静默安装实践
  13. Guava学习笔记-Joiner
  14. Linux linux mb() / rmb() / wmb()
  15. 去掉Win7快捷方式小箭头
  16. oracle自动建立分区interval,使用Oracle 11g创建Interval分区表(转)
  17. 程序员怎么提高代码编写的速度?
  18. ShareSDK⭐一、QQ登陆、获取QQ用户信息
  19. refresh matlab path,Matlab 习惯常用命令收集 转
  20. SpringBoot sharding 分库分表使用及配置

热门文章

  1. 基于FPGA的LD3320语音识别模块驱动设计
  2. win10打开蓝牙_这4个Win10新增的快捷键,提高效率必备
  3. OC callback
  4. 设置微信分享的标题 缩略图 连接 描述
  5. 第1-7课:基础开胃菜
  6. vivo智能手机产能
  7. 备份路由器配置文件到服务器,教你如何备份路由器配置文件
  8. 怎么打印加密的PDF文件?
  9. (java)socket全双工长连接通信实例
  10. PHP fpdi合并多个PDF文件,取多个PDF特定页数合并以及导出