webapp中html5调用系统相机拍照问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_27063119/article/details/80838702

webapp中html5调用系统相机拍照问题

一. 引言:

    webapp之所以现在很流行,主要是现在的手机硬件配置都过剩了,用网页做的UI界面流畅度上与原生的差距很小,关键是开发速度得到了很大的提升,而且可以跨平台,IOS和Android可以使用同一界面,但是其中也会有一些问题,这里就说说调用系统相机出现的问题。

二. 在webapp中调用系统相机拍照存在的问题:

1. 部分手机通过html5调用系统相机拍照时,生成的照片是被旋转的。代表机型:小米6(Android8.0)

2. 部分手机拍照后点击确认,没有照片数据返回。代表机型: 红米note4(Android6.0)

3. 部分手机拍照后,点击确认键无任何反应。代表机型:魅族5(Android5.1)

三. 解决方法

1. 对于部分手机拍照后被旋转的问题,由于不是原生写的自定义相机,所以不能在拍照时候使用重力感应器等来矫正图片的旋转角度,而解决该类问题的方式也很简单,就是在系统相机拍完后会返回路径地址,我们拿到图片后,开始读取图片里面的orientation方向信息,当角度值为0的时候就不用旋转了,否则就要进行旋转。

/**
     * 获取图片正确显示需要旋转的角度(顺时针)
     * @return
     */
    public static String getRotateAngleForPhoto(String filePath){
        File file = new File(filePath);
        int angle = 0;
        try {
        	Metadata metadata = JpegMetadataReader.readMetadata(file);
            Directory directory = metadata.getDirectory(ExifDirectory.class);
                if(directory.containsTag(ExifDirectory.TAG_ORIENTATION)){ 
                  // Exif信息中方向  
                   int orientation = directory.getInt(ExifDirectory.TAG_ORIENTATION); 
                   // 原图片的方向信息
                   if(6 == orientation ){
                       //6旋转90
                       angle = 90;
                   }else if( 3 == orientation){
                      //3旋转180
                       angle = 180;
                   }else if( 8 == orientation){
                      //8旋转90
                       angle = 270;
                   }
                }  
        } catch (JpegProcessingException e) {
            e.printStackTrace();
        } catch (MetadataException e) {
            e.printStackTrace();
        }
        return angle+"";
    }

拿到方向信息后,并可以进行校正图片的旋转角度了,矫正的时候,需要将图片文件转化成Bitmap,

//读取拍照生成的照片
					FileInputStream is = new FileInputStream(new File(sourcePath));
					//转化成Bitmap
					Bitmap bitmap = BitmapFactory.decodeStream(is);

再通过方向信息将Bitmap图片进行旋转。

    /**
     * 旋转图片
     *
     * @param angle  旋转角度
     * @param bitmap 要旋转的图片
     * @return 旋转后的图片
     */
    public static Bitmap rotate(Bitmap bitmap, int angle) {
        Matrix matrix = new Matrix();
        matrix.postRotate(angle);
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                bitmap.getHeight(), matrix, true);
    }

旋转后返回的仍是Bitmap,需要转化为文件,可以直接替换掉源文件:

/**
     *  保存图片
     * @return 
     */
    public static void saveImageFile(String savepath,Bitmap bmp) {
        File f = new File(savepath);
        try {
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(f));
            bmp.compress(Bitmap.CompressFormat.JPEG, 100, bos);
            bos.flush();
            bos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bmp != null && !bmp.isRecycled()) {
                bmp.recycle();
                bmp = null;
            }
        }
    }


以上的步骤大致为:获取旋转的角度信息 -> 原图片转成Bitmap -> 根据角度信息去旋转生成Bitmap  -> 将Bitmap转化成图片文件

中间显然走了弯路,有没有可能根据方向角度信息直接把图片文件进行旋转呢,答案是肯定的,可以使用java桌面编程的awt包,不过我在android中没有成功过,代码是网上找的:

/**
     * 旋转图片
     * @param fullPath
     * @param angel
     * @return
     */
    public static String rotatePhonePhoto(String fullPath, int angel){
        BufferedImage src;
        try {
            src = ImageIO.read(new File(fullPath));  
            int src_width = src.getWidth(null);  
            int src_height = src.getHeight(null);  
            int swidth=src_width;  
            int sheight=src_height;  
            if(angel==90||angel==270){  
                swidth = src_height;  
                sheight= src_width;  
            }  
            Rectangle rect_des = new Rectangle(new Dimension(swidth,sheight));  
            BufferedImage res = new BufferedImage(rect_des.width, rect_des.height,BufferedImage.TYPE_INT_RGB);  
            Graphics2D g2 = res.createGraphics();
            g2.translate((rect_des.width - src_width) / 2,(rect_des.height - src_height) / 2);  
            g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);  
            g2.drawImage(src, null, null);  
            ImageIO.write(res, "jpg", new File(fullPath));  
        } catch (IOException e) {
            e.printStackTrace();
            return e.getMessage();
        }
        return fullPath;  
    }

上面会用到jar包:借助mediautil-1.0.jar,metadata-extractor-2.3.1.jar,


2. 部分手机拍照后,点击确认,没有数据返回,测试的时候是红米note4上出现的这种问题,从网上找了一些资料看了,发现是文件夹权限问题

(1). Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath()+ "/WebViewUploadImage";
(2). Environment.getExternalStorageDirectory().getPath() + "/WebViewUploadImage";

之前是使用了第二种,之后调整为第一种,红米note4上就没有问题了。


3. 部分手机点击确认无反应,从log上观察到了很奇怪的问题,网页点击拍照后跳转到系统相机后,日志随着点击完成按钮,就开始消失了,就开始怀疑是不是跳转到系统相机后,我猜想可能跟activity入栈有关,按照这个思路找资料,发现确实有人遇到这种问题,在Intent跳转时加上就可以了。

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);






猜你喜欢

转载自blog.csdn.net/qq_27063119/article/details/80838702