I photograph the universe with a large diversion - instantly rotate your photos

Foreword

The company has a project in the ancestral custom camera, before find it does not rotate in the horizontal position of the picture when it After some modifications in the above test machine tested successfully. On-line later found that only part of the phone is rotated correctly, after some effort, finally solved. And gives a stereotyped picture rotation with an online comparison of different in the end the rare fast rotation scheme .

Wrote this article after the next record to solve the problem, step by step analysis of a problem inside.

Only part of the phone rotate right

This approach is only partially correct rotary phone to get photos directly from your camera look at the code inside the callback method for processing onPictureTaken () is:

 public void onPictureTaken(byte[] data, Camera camera) {
                camera.stopPreview();
                //是否需要旋转
                boolean isOrientation = false;
                //用户是否横屏拍摄,true为横屏 0度左旋 90不旋 180右旋 270度旋
                if (CameraActivity.this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE
                        && (takePhotoOrientation <= 90+45)&&(takePhotoOrientation>=90-45)) {//不旋转
                    isOrientation = false;
                } else {
                    isOrientation = true;
                }
               //旋转太过消耗时间,是储存的40倍时间左右,考虑后去掉旋转。
               //---反注释start---
                if (isOrientation) {
                    //横屏拍摄,需要旋转90度
                   byte[] bytes = ImageUtils.rotatePic(data,takePhotoOrientation-90);
                    if (bytes != null) {
                        data = bytes;
                    }
                }
                //---反注释end---
                mPicPath = String.format("%s%s%s", AppConfig.getCarTradeFileDir("Camera"),
                            System.currentTimeMillis() + ".jpg", tempFileSuffex);
                FileSaveUtils.saveFile(data, mPicPath, new FileSaveUtils.SaveListener() {
                    @Override
                    public void saveComplete() {
                        finish();
                    }
                });
    }
复制代码

In fact, I'm here to do is put the code on the rotation of the anti-annotated.

An analysis done inside:

  1. takePhotoOrientation This variable is provided by a listener gravity, which is determined by the current state of the phone is in the horizontal position, horizontal position needs to be rotated;
  2. Then you can see the original author of the code is very close to where the comment rotation is very time-consuming, warned us not to rotate it, and then rotate the code commented out, I took him notes solved;
  3. ImageUtils.rotatePic () rotate pictures, go inside the core code is a search online is the rotation scheme:
public static byte[] rotatePic(byte[] data, int degree) {
        byte[] bytes = null;
        try {
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inPreferredConfig = Bitmap.Config.RGB_565;
            options.inJustDecodeBounds = false;
            options.inPurgeable = true;
            options.inInputShareable = true;
            Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);// data是字节数据,将其解析成位图
            bitmap = rotateBitmap(bitmap, degree);
            bytes = bitmap2Bytes(bitmap);
            if (bitmap != null && !bitmap.isRecycled()) {
                bitmap.recycle();
            }
        } catch (Error e) {
            e.printStackTrace();
        }
        return bytes;
    }
    /**
    * 网上一搜就有的旋转代码
    */
    public static Bitmap rotateBitmap(Bitmap bitmap, int degree) {
        Matrix matrix = new Matrix();
        matrix.postRotate(degree);
        Bitmap bm = null;
        try {
            bm = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        } catch (Exception e) {
            bm = bitmap;
        }
        return bm;
    }
    
    public static byte[] bitmap2Bytes(Bitmap bm) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        return baos.toByteArray();
    }
复制代码
  1. Save byte [] data. Internal photo storage method to achieve here is also a problem, but this is not the focus of our article, so ignore it first.

See here, some of the students may have been sighted to see why the authors said rotation with 40 times the time, yes it ~

ImageUtils.rotatePic () which is a problem: it is first byte [] parsed into bitmap, and then create a rotating bitmap, and then converted into bitmap byte [] to store. This process has not 40 times I did not practice, but imagine it takes a long time. Left to optimization.

Get EXIF

Optimization of the first things down, to solve business problems - rotation.

How can we know that the direction in which pictures of it? Small case, beat me to play photography, camera camera when there will put a hold called EXIF photo information, it is stored inside a lot of information about the photo, such as aperture, focal length, shutter speed, etc., the most important there we need the direction of rotation -orientation . With it we can not easily determine the direction! ?

Hey ~ I read:

    ExifInterface exifInterface = new ExifInterface(filepath);
    int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                            ExifInterface.ORIENTATION_NORMAL);
    ...
复制代码

emmmm ... This is where we can not immediately use this code to read, if you use the code for this project, read exif, you may have reached a dead end inside get out!

A first download the app exif can see, I use the Photo Exif Editor , it opens like this:

I Bobo cute?

Figure exif glance, but with a photo exif editor to view the project camera shot out of the map, all the exif data are empty, so if you use the code to read, never read only that you fill in the default values.

Go explore what reason exif lost it, I thought it was Carema Api problem, but in onPictureTaken () inside a callback directly save the picture, exif exist, obviously the problem lies in rotating the code inside, you can guess is converted into bitmap information exif lost when , after some inspection data, it is true.

What is Exif, why would lose Exif information?

Exif2.2 specification which can be found from the description of the compressed image file data, which has so a picture:

It describes such a fact : a compressed image file from the compressed image data and the marker code, where the code marker data comprises Exif. Obviously, bitmap image as a class contains only extract the image data.

to sum up

Photo converted to bitmap lost exif, so when you need to edit the pictures up to save after save exif modify the photo again to go.

Exif want to understand if there is a 2.2 version of the specification document Exif2.2 portal .

Now that you know well, Exif read it!

    ExifInterface exifInterface = new ExifInterface(filepath);
    int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                            ExifInterface.ORIENTATION_NORMAL);
    ...
复制代码

I read ~~~~ ↓

Millet: Photo direction coincides with the direction of the phone, not properly rotated, Exif 90 °;

VIVO: Picture orientation is inconsistent with the direction of the phone, rotate right, Exif 90 °.

Shocked! Actually expected and inconsistent. . This proved such a difference in the internal phone system is emerging, Android fragmentation!

Work came to a standstill. . Daniel can only be moved out of the fish brother ~

After some inquiry, Columbia fish show his code to solve my problem - thank Columbia fish again

Camera configuration parameters

Camera # Parameters of this class and I believe that the students will not be unfamiliar familiar with the camera, it can be used to access and configure the camera parameters: Get a preview size, set the flash, focus mode, etc., are regulated by the class in this configuration, we want correction method turned out to be hiding in here!

public class IOrientationEventListener extends OrientationEventListener {
        
        public IOrientationEventListener(Context context) {
            super(context);
        }
        
        @Override
        public void onOrientationChanged(int orientation) {
            if (ORIENTATION_UNKNOWN == orientation) {
                return;
            }
            Camera.CameraInfo info = new Camera.CameraInfo();
            Camera.getCameraInfo(defaultCameraId, info);
            orientation = (orientation + 45) / 90 * 90;
            int rotation = 0;
            if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                rotation = (info.orientation - orientation + 360) % 360;
            } else {
                rotation = (info.orientation + orientation) % 360;
            }
            
            if (null != mCamera) {
                Camera.Parameters parameters = mCamera.getParameters();
                parameters.setRotation(rotation);//关键代码
                mCamera.setParameters(parameters);
            }
        }
    }
复制代码

After acquiring the examples are in Callback # # SurfaceHolder surfaceCreated () and Callback # # SurfaceHolder surfaceDestroyed () call at the instance enable () and disable () can be unified camera rotation issue .

Since onOrientationChanged () callback frequent, more optimized approach fishes camera can be set after pressing the capture button.

It can be found by modifying the value of the rotation, as long as the value of a certain rotation, the direction of all camera phones are unified, meaning that manufacturers set the direction of the camera defaults fragmented.

Customize your camera so far to solve the rotation problem.


Rapidly rotating photos

Through the above description of a large wheel, clever students may already suspect that the rapid rotation of the program - is the use of Exif.

Because the picture itself is generated by the Exif device, which comprises a label photo orientation direction, the image is loaded will be displayed frame by reading the orientation of the picture, that is, by modifying the values in the Exif orientation, i.e., rotate photos can be achieved the effect ! And requires only a small operating parameters can be done, instantaneous speed of Leverage! No longer afraid to rotate the picture slow it!

Glide look at the process: Exif resolve to confirm the image orientation

    //默认的图片头解析器
    public final class DefaultImageHeaderParser implements ImageHeaderParser {
        ...
        private int getOrientation(Reader reader, ArrayPool byteArrayPool) throws IOException {
            ...
            int exifSegmentLength = moveToExifSegmentAndGetLength(reader);
            if (exifSegmentLength == -1) {
                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "Failed to parse exif segment length, or exif segment not found");
                }
                return UNKNOWN_ORIENTATION;
            }

            byte[] exifData = byteArrayPool.get(exifSegmentLength, byte[].class);
            try {
                return parseExifSegment(reader, exifData, exifSegmentLength);
            } finally {
                byteArrayPool.put(exifData);
            }
            ...
        }
        ...
    }
复制代码

Counterclockwise code:

 ExifInterface exifInterface = new ExifInterface(currentPath);
                    // 获取图片的旋转信息
                    int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                            ExifInterface.ORIENTATION_NORMAL);
                    LogUtils.v("exif orientation:" + orientation);
                    //根据当前图片方向设置想要的图片方向
                    switch (orientation) {
                        case ExifInterface.ORIENTATION_ROTATE_90://正常角度
                            exifInterface.setAttribute(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_NORMAL+"");
                            break;
                        case ExifInterface.ORIENTATION_ROTATE_180:
                            exifInterface.setAttribute(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_ROTATE_90+"");
                            break;
                        case ExifInterface.ORIENTATION_ROTATE_270:
                            exifInterface.setAttribute(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_ROTATE_180+"");
                            break;
                        case ExifInterface.ORIENTATION_NORMAL:
                            exifInterface.setAttribute(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_ROTATE_270+"");
                            break;
                    }
                    exifInterface.saveAttributes();
复制代码

Caution: This program can only be used with a photo's Exif, rotate the photo after the show needs attention cache problem , after each rotation to update the cache to display photos correct.

Glide when you load pictures directly through the signature () method modified as new ObjectKey incoming file cache can be marked:

Glide.with(context)
     .load(filePath)
     .signature(new ObjectKey(file.lastModified())
     .into(imageView);
复制代码

If other frameworks Find your own friends ~

end

Finally finished, and if you find it useful or have to expand the knowledge on the point of a chant praise to show their support

Thank you for watching and learning! Next time bye ~

Reproduced in: https: //juejin.im/post/5cf76785f265da1b827a8a98

Guess you like

Origin blog.csdn.net/weixin_34405354/article/details/93172286