2016-09-08 27 views
20

Tôi có một ứng dụng chụp ảnh bằng cách sử dụng ảnh gốc Camera và sau đó tải chúng lên máy chủ. Vấn đề của tôi là tất cả các bức ảnh đều có giá trị định hướng EXIF ​​là 0, và điều này sẽ làm rối loạn màn hình ở nơi khác.Dữ liệu EXIF ​​Android luôn 0, cách thay đổi?

Làm cách nào để thay đổi hướng EXIF? Tôi không tìm cách sửa nó cho mọi hoàn cảnh, chỉ cần thay đổi nó thành một giá trị khác.

Tôi đang sử dụng Samsung Galaxy Note 4

tôi đã cố gắng giải pháp này đã đưa ra định hướng máy ảnh trước khi chụp ảnh: Setting Android Photo EXIF Orientation

Camera c = Camera.open(); 
c.setDisplayOrientation(90); 

Camera.Parameters params = mCamera.getParameters(); 
params.setRotation(0); // tried 0, 90, 180 
c.setParameters(params); 

nhưng nó không ảnh hưởng đến dữ liệu EXIF ​​kết quả, nó vẫn luôn 0

tôi cũng đã cố gắng những giải pháp mà hình ảnh được quay sau khi nó được thực hiện: EXIF orientation tag value always 0 for image taken with portrait camera app android

và trong khi điều này xoay ảnh, định hướng EXIF ​​vẫn phải lúc nào cũng 0.

Tôi cũng đã cố gắng thiết lập các dữ liệu EXIF ​​trực tiếp: How to save Exif data after bitmap compression in Android

private Camera.PictureCallback mPicture = new Camera.PictureCallback() { 
    @Override 
    public void onPictureTaken(byte[] data, Camera camera) { 
     final File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE, ""); 
     try { 
      FileOutputStream fos = new FileOutputStream(pictureFile); 

      ExifInterface exif = new ExifInterface(pictureFile.toString()); 
      exif.setAttribute(ExifInterface.TAG_ORIENTATION, "3"); 
      exif.saveAttributes(); 

      fos.write(data); 
      fos.close(); 

      //upload photo.. 
     } 
    } 
} 

nhưng EXIF ​​Định hướng vẫn là 0 sau khi tải lên.

Tôi cũng đã xem xét các giải pháp này:

Exif data TAG_ORIENTATION always 0

How to write exif data to image in Android?

How to get the Correct orientation of the image selected from the Default Image gallery

how to set camera Image orientation?

nhưng tất cả đều liên quan đến việc điều chỉnh định hướng bằng cách xoay, mà không ảnh hưởng đến dữ liệu EXIF ​​hoặc setti ng dữ liệu EXIF ​​trực tiếp mà dường như không hoạt động.

Làm cách nào để thay đổi dữ liệu định hướng EXIF ​​của tệp từ 0 đến 3?

UPDATE:

đây là mã tải lên của tôi:

Bitmap sBitmap = null; 
final File sResizedFile = getOutputMediaFile(MEDIA_TYPE_IMAGE, "_2"); 
try { 
    sBitmap = BitmapFactory.decodeStream(new FileInputStream(pictureFile), null, options); 
} catch (FileNotFoundException e) { 
    Log.e("App", "[MainActivity] unable to convert pictureFile to bitmap"); 
    e.printStackTrace(); 
    return; 
} 

// ... compute sw and sh int values 

Bitmap sOut = Bitmap.createScaledBitmap(sBitmap, sw, sh, false); 
Bitmap rotatedBitmap = rotateBitmap(sOut, 3); 
FileOutputStream sfOut; 
try { 
    sfOut = new FileOutputStream(sResizedFile); 
    rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 70, sfOut); 
    sfOut.flush(); 
    sfOut.close(); 
    sBitmap.recycle(); 
    sOut.recycle(); 
    rotatedBitmap.recycle(); 
} catch (Exception e) { 
    Log.e("App", "[MainActivity] unable to save thumbnail"); 
    e.printStackTrace(); 
    return; 
} 
// upload small thumbnail 
TransferObserver sObserver = transferUtility.upload(
      "stills/small",  /* The bucket to upload to */ 
      filename + ".jpg",  /* The key for the uploaded object */ 
      sResizedFile   /* The file where the data to upload exists */ 
); 
+0

trên thiết bị nào bạn đang thử? – MKJParekh

+0

Samsung Galaxy Note 4 – Cbas

+0

@Cbas, là _ "Giá trị định hướng EXIF ​​của 0" _ ** trước ** hoặc ** sau ** bạn tải lên nhóm trực tuyến không? Tôi vừa thử nghiệm nhóm AWS của Amazon và họ giữ lại EXIF ​​** sau khi tải lên **. Bạn phải sử dụng một máy chủ dựa trên nhóm khác (ví dụ: Google Cloud), phải không? Sau đoạn mã đầu tiên bạn nói _ "nó không ảnh hưởng đến dữ liệu EXIF ​​kết quả, nó vẫn luôn là 0" _ ** vì vậy đó là vấn đề về mã **? Sau đó, sau đoạn mã thứ hai bạn nói _ "nhưng định dạng EXIF ​​vẫn là 0 ** sau khi tải lên **." _ ** vì vậy đó là sự cố tải lên/máy chủ? ** Vui lòng xác nhận nếu giá trị EXIF ​​luôn bằng 0 ngay cả trước khi tải lên hoặc chỉ sau tải lên? –

Trả lời

6

Hóa ra mã của tôi là có thể đặt dữ liệu EXIF, nhưng có sự khác biệt giữa cách Android diễn giải dữ liệu này và cách iOS và Chrome trên máy Mac (nơi tôi kiểm tra tệp kết quả) diễn giải nó.

Đây là mã duy nhất cần thiết để thiết lập định hướng EXIF:

ExifInterface exif = new ExifInterface(pictureFile.toString()); 
exif.setAttribute(ExifInterface.TAG_ORIENTATION, "3"); 
exif.saveAttributes(); 

Tuy nhiên, thiết lập 3 xuất hiện như 0 trên iOS và hình ảnh là ngang trong Chrome.

cài đặt 6 hiển thị dưới dạng 3 trên iOS và hình ảnh trông ngay trong Chrome.

+0

+1 cho tiến trình về vấn đề của riêng mình. Bạn nên đề cập đến vấn đề thử nghiệm Android/iOS. Điều duy nhất tôi có thể thêm là iOS là Big Endian và Android là Little Endian. Tôi sẽ mở rộng trong hộp Trả lời ... –

12

Như bạn có thể thấy, các thông tin Các EXIF ​​là không đáng tin cậy trên Android (đặc biệt là các thiết bị Samsung).

Tuy nhiên, cơ sở dữ liệu SQL của điện thoại giữ các tham chiếu đến đối tượng Media là đáng tin cậy. Tôi sẽ cầu hôn theo cách này.

Bắt định hướng từ Uri:

private static int getOrientation(Context context, Uri photoUri) { 
    Cursor cursor = context.getContentResolver().query(photoUri, 
      new String[]{MediaStore.Images.ImageColumns.ORIENTATION}, null, null, null); 

    if (cursor.getCount() != 1) { 
     cursor.close(); 
     return -1; 
    } 

    cursor.moveToFirst(); 
    int orientation = cursor.getInt(0); 
    cursor.close(); 
    cursor = null; 
    return orientation; 
} 

Sau đó khởi quay Bitmap:

public static Bitmap rotateBitmap(Context context, Uri photoUri, Bitmap bitmap) { 
    int orientation = getOrientation(context, photoUri); 
    if (orientation <= 0) { 
     return bitmap; 
    } 
    Matrix matrix = new Matrix(); 
    matrix.postRotate(orientation); 
    bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false); 
    return bitmap; 
} 

Nếu bạn muốn thay đổi định hướng của hình ảnh, hãy thử các đoạn mã sau:

public static boolean setOrientation(Context context, Uri fileUri, int orientation) { 
    ContentValues values = new ContentValues(); 
    values.put(MediaStore.Images.Media.ORIENTATION, orientation); 
    int rowsUpdated = context.getContentResolver().update(fileUri, values, null, null); 
    return rowsUpdated > 0; 
} 

Nếu bạn đặt hướng của hình ảnh, sau đó nó sẽ là consta ntly đặt đúng hướng. Cần phải sử dụng ExifInterface sau đó, vì hình ảnh đã được xoay theo cách thích hợp.

Nếu phương pháp này là không thỏa đáng, sau đó bạn có thể thử this method

+0

Có, bạn là chính xác chúng ta nên có được định hướng của dữ liệu Uri chọn từ thư viện. Cảm ơn giải pháp của bạn đã làm việc cho tôi !!! –

+0

Bạn chắc chắn xứng đáng nhận được hơn 10 phiếu cho câu trả lời này.Cảm ơn bạn –

+0

Hoạt động như một sự quyến rũ. Cảm ơn bạn! – Jorge181

3

Tham khảo dự án GitHub này https://github.com/pandiaraj44/Camera. Nó có hoạt động máy ảnh tùy chỉnh nơi EXIF ​​TAG_ORIENTATION được xử lý chính xác. Bạn có thể sao chép dự án và kiểm tra. Để biết chi tiết mã, vui lòng tham khảo https://github.com/pandiaraj44/Camera/blob/master/app/src/main/java/com/pansapp/cameraview/CameraFragment.java

+0

ExifInterface: Hình ảnh không hợp lệ: ExifInterface có tệp định dạng hình ảnh không được hỗ trợ (ExifInterface chỉ hỗ trợ định dạng JPEG và một số định dạng ảnh RAW) hoặc tệp JPEG bị hỏng đối với ExifInterface. khi tôi chạy mã của bạn – yarin

3

Có một lớp để đọc và cập nhật các thông tin hình ảnh này.

Để cập nhật các thuộc tính bạn có thể sử dụng như thế này

ExifInterface ef = new ExifInterface(filePath); 
      ef.setAttribute(MAKE_TAG, MAKE_TAG); 
      ef.setAttribute(ExifInterface.TAG_ORIENTATION, orientation+""); 
      ef.saveAttributes(); 

và cho việc đọc, bạn có thể sử dụng như thế này

ExifInterface exif = null; 
     try { 
      exif = new ExifInterface(absolutePath+path); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 
       ExifInterface.ORIENTATION_UNDEFINED); 

Tôi hy vọng nó sẽ giúp bạn

5

Bạn đã chấp nhận câu trả lời của riêng mình làm giải pháp. Rant của tôi chỉ là thông tin phụ hữu ích, anyways ...

"Tuy nhiên ..." trong Câu trả lời của bạn cho thấy trong khi bây giờ bạn biết nguyên nhân, bạn không khắc phục.

Hóa ra mã của tôi đã có thể thiết lập các dữ liệu EXIF, nhưng có một sự khác biệt giữa cách Android giải thích dữ liệu này và làm thế nào iOS ... diễn giải nó.

Đây có thể là vấn đề về cuối cùng. Bạn có thể thử bằng tay thay đổi thiết lập endianness của Exif bằng cách mở jpeg của bạn trong trình soạn thảo hex và tìm ...

  • Các byte 45 78 69 66 (làm cho "Exif" text) tiếp theo là hai zero byte 00 00.
  • Sau đó, nó phải là 49 49 (làm cho văn bản "II") có nghĩa là đọc dữ liệu dưới dạng định dạng cuối cùng nhỏ.
  • Nếu bạn thay thế bằng 4D 4D (hoặc văn bản "MM") thì bên đọc sẽ xem xét dữ liệu là kết thúc lớn.

Kiểm tra điều này trong iOS để xem liệu số liệu có chính xác không.

và về vấn đề này ...

Tuy nhiên, thiết lập 3 xuất hiện như 0 trên iOS và hình ảnh là đi ngang trong Chrome.
Đặt 6 hiển thị dưới dạng 3 trên iOS và hình ảnh trông ngay trong Chrome.

Chỉ có điều tôi có thể thêm là iOS Mac là Big Endian * và Android/PC được Little Endian. Về cơ bản Little Endian đọc/ghi các byte từ phải qua trái trong khi Big Endian ngược lại.

Trong nhị phân: 011 nghĩa và 110 nghĩa . Sự khác biệt giữa 3 và 6 chỉ đơn giản là thứ tự đọc của các bit đó trong số các số & số không. Vì vậy, hệ thống đọc là zero-one-one được kết quả là nhưng hệ thống Endian khác sẽ đọc một byte có cùng bit như one-one-zero và cho bạn biết kết quả là . Tôi không thể giải thích lý do tại sao "3 hiển thị dưới dạng 0" mà không có tệp kiểm tra để phân tích byte nhưng đó là kết quả lạ đối với tôi.

</end rant>
<sleep>

* lưu ý: Trong khi Mac là Big Endian, kiểm tra hai lần nói iOS sử dụng hệ thống Endian nhỏ sau khi tất cả. Con số của bạn vẫn cho thấy một vấn đề Big vs Little Endian.

Các vấn đề liên quan