| package com.doumee.lib_coremodel.util.luban; | 
|   | 
| import android.graphics.BitmapFactory; | 
| import android.util.Log; | 
|   | 
| import java.io.ByteArrayOutputStream; | 
| import java.io.File; | 
| import java.io.IOException; | 
| import java.io.InputStream; | 
| import java.util.Arrays; | 
|   | 
| enum Checker { | 
|   SINGLE; | 
|   | 
|   private static final String TAG = "Luban"; | 
|   | 
|   private static final String JPG = ".jpg"; | 
|   | 
|   private final byte[] JPEG_SIGNATURE = new byte[]{(byte) 0xFF, (byte) 0xD8, (byte) 0xFF}; | 
|   | 
|   /** | 
|    * Determine if it is JPG. | 
|    * | 
|    * @param is image file input stream | 
|    */ | 
|   boolean isJPG(InputStream is) { | 
|     return isJPG(toByteArray(is)); | 
|   } | 
|   | 
|   /** | 
|    * Returns the degrees in clockwise. Values are 0, 90, 180, or 270. | 
|    */ | 
|   int getOrientation(InputStream is) { | 
|     return getOrientation(toByteArray(is)); | 
|   } | 
|   | 
|   private boolean isJPG(byte[] data) { | 
|     if (data == null || data.length < 3) { | 
|       return false; | 
|     } | 
|     byte[] signatureB = new byte[]{data[0], data[1], data[2]}; | 
|     return Arrays.equals(JPEG_SIGNATURE, signatureB); | 
|   } | 
|   | 
|   private int getOrientation(byte[] jpeg) { | 
|     if (jpeg == null) { | 
|       return 0; | 
|     } | 
|   | 
|     int offset = 0; | 
|     int length = 0; | 
|   | 
|     // ISO/IEC 10918-1:1993(E) | 
|     while (offset + 3 < jpeg.length && (jpeg[offset++] & 0xFF) == 0xFF) { | 
|       int marker = jpeg[offset] & 0xFF; | 
|   | 
|       // Check if the marker is a padding. | 
|       if (marker == 0xFF) { | 
|         continue; | 
|       } | 
|       offset++; | 
|   | 
|       // Check if the marker is SOI or TEM. | 
|       if (marker == 0xD8 || marker == 0x01) { | 
|         continue; | 
|       } | 
|       // Check if the marker is EOI or SOS. | 
|       if (marker == 0xD9 || marker == 0xDA) { | 
|         break; | 
|       } | 
|   | 
|       // Get the length and check if it is reasonable. | 
|       length = pack(jpeg, offset, 2, false); | 
|       if (length < 2 || offset + length > jpeg.length) { | 
|         Log.e(TAG, "Invalid length"); | 
|         return 0; | 
|       } | 
|   | 
|       // Break if the marker is EXIF in APP1. | 
|       if (marker == 0xE1 && length >= 8 | 
|           && pack(jpeg, offset + 2, 4, false) == 0x45786966 | 
|           && pack(jpeg, offset + 6, 2, false) == 0) { | 
|         offset += 8; | 
|         length -= 8; | 
|         break; | 
|       } | 
|   | 
|       // Skip other markers. | 
|       offset += length; | 
|       length = 0; | 
|     } | 
|   | 
|     // JEITA CP-3451 Exif Version 2.2 | 
|     if (length > 8) { | 
|       // Identify the byte order. | 
|       int tag = pack(jpeg, offset, 4, false); | 
|       if (tag != 0x49492A00 && tag != 0x4D4D002A) { | 
|         Log.e(TAG, "Invalid byte order"); | 
|         return 0; | 
|       } | 
|       boolean littleEndian = (tag == 0x49492A00); | 
|   | 
|       // Get the offset and check if it is reasonable. | 
|       int count = pack(jpeg, offset + 4, 4, littleEndian) + 2; | 
|       if (count < 10 || count > length) { | 
|         Log.e(TAG, "Invalid offset"); | 
|         return 0; | 
|       } | 
|       offset += count; | 
|       length -= count; | 
|   | 
|       // Get the count and go through all the elements. | 
|       count = pack(jpeg, offset - 2, 2, littleEndian); | 
|       while (count-- > 0 && length >= 12) { | 
|         // Get the tag and check if it is orientation. | 
|         tag = pack(jpeg, offset, 2, littleEndian); | 
|         if (tag == 0x0112) { | 
|           int orientation = pack(jpeg, offset + 8, 2, littleEndian); | 
|           switch (orientation) { | 
|             case 1: | 
|               return 0; | 
|             case 3: | 
|               return 180; | 
|             case 6: | 
|               return 90; | 
|             case 8: | 
|               return 270; | 
|           } | 
|           Log.e(TAG, "Unsupported orientation"); | 
|           return 0; | 
|         } | 
|         offset += 12; | 
|         length -= 12; | 
|       } | 
|     } | 
|   | 
|     Log.e(TAG, "Orientation not found"); | 
|     return 0; | 
|   } | 
|   | 
|   String extSuffix(InputStreamProvider input) { | 
|     try { | 
|       BitmapFactory.Options options = new BitmapFactory.Options(); | 
|       options.inJustDecodeBounds = true; | 
|       BitmapFactory.decodeStream(input.open(), null, options); | 
|       return options.outMimeType.replace("image/", "."); | 
|     } catch (Exception e) { | 
|       return JPG; | 
|     } | 
|   } | 
|   | 
|   boolean needCompress(int leastCompressSize, String path) { | 
|     if (leastCompressSize > 0) { | 
|       File source = new File(path); | 
|       return source.exists() && source.length() > (leastCompressSize << 10); | 
|     } | 
|     return true; | 
|   } | 
|   | 
|   private int pack(byte[] bytes, int offset, int length, boolean littleEndian) { | 
|     int step = 1; | 
|     if (littleEndian) { | 
|       offset += length - 1; | 
|       step = -1; | 
|     } | 
|   | 
|     int value = 0; | 
|     while (length-- > 0) { | 
|       value = (value << 8) | (bytes[offset] & 0xFF); | 
|       offset += step; | 
|     } | 
|     return value; | 
|   } | 
|   | 
|   private byte[] toByteArray(InputStream is) { | 
|     if (is == null) { | 
|       return new byte[0]; | 
|     } | 
|   | 
|     ByteArrayOutputStream buffer = new ByteArrayOutputStream(); | 
|   | 
|     int read; | 
|     byte[] data = new byte[4096]; | 
|   | 
|     try { | 
|       while ((read = is.read(data, 0, data.length)) != -1) { | 
|         buffer.write(data, 0, read); | 
|       } | 
|     } catch (Exception ignored) { | 
|       return new byte[0]; | 
|     } finally { | 
|       try { | 
|         buffer.close(); | 
|       } catch (IOException ignored) { | 
|       } | 
|     } | 
|   | 
|     return buffer.toByteArray(); | 
|   } | 
| } |