+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/navigation_bar"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal">
- <Button android:id="@+id/menu_button"
- android:divider="?android:attr/listDividerAlertDialog"
- style="?android:attr/borderlessButtonStyle"
- android:singleLine="true"
- android:gravity="left|center_vertical"
- android:paddingRight="25dip"
- android:layout_width="wrap_content"
- android:layout_height="match_parent" />
-</LinearLayout>
<string name="process_caching_requests" msgid="8722939570307386071">"መሸጎጫ ጥየቃዎች ሂደት"</string>
<string name="caching_label" msgid="4521059045896269095">"በመሸጎጥ ላይ..."</string>
<string name="crop_action" msgid="3427470284074377001">"ከርክም"</string>
- <!-- no translation found for trim_action (703098114452883524) -->
- <skip />
+ <string name="trim_action" msgid="703098114452883524">"አሳጥር"</string>
<string name="set_as" msgid="3636764710790507868">"እንደ"</string>
<string name="video_err" msgid="7003051631792271009">"ቪዲዮ ማጫወት አይቻልም።"</string>
<string name="group_by_location" msgid="316641628989023253">"በስፍራ"</string>
<string name="process_caching_requests" msgid="8722939570307386071">"Запыты на кэшаванне працэсу"</string>
<string name="caching_label" msgid="4521059045896269095">"Кэшаванне..."</string>
<string name="crop_action" msgid="3427470284074377001">"Абрэзаць"</string>
- <!-- no translation found for trim_action (703098114452883524) -->
- <skip />
+ <string name="trim_action" msgid="703098114452883524">"Рамка"</string>
<string name="set_as" msgid="3636764710790507868">"Ўсталяваць у якасці"</string>
<string name="video_err" msgid="7003051631792271009">"Не атрымліваецца прайграць відэа."</string>
<string name="group_by_location" msgid="316641628989023253">"Па месцазнаходжанні"</string>
<string name="process_caching_requests" msgid="8722939570307386071">"S\'estan processant les sol·licituds de memòria cau"</string>
<string name="caching_label" msgid="4521059045896269095">"S\'està desant a la memòria cau..."</string>
<string name="crop_action" msgid="3427470284074377001">"Retalla"</string>
- <!-- no translation found for trim_action (703098114452883524) -->
- <skip />
+ <string name="trim_action" msgid="703098114452883524">"Retalla"</string>
<string name="set_as" msgid="3636764710790507868">"Defineix com a"</string>
<string name="video_err" msgid="7003051631792271009">"No es pot reproduir el vídeo."</string>
<string name="group_by_location" msgid="316641628989023253">"Per ubicació"</string>
<string name="process_caching_requests" msgid="8722939570307386071">"Håndterer anmodninger om cachelagring"</string>
<string name="caching_label" msgid="4521059045896269095">"Cachelagrer..."</string>
<string name="crop_action" msgid="3427470284074377001">"Beskær"</string>
- <!-- no translation found for trim_action (703098114452883524) -->
- <skip />
+ <string name="trim_action" msgid="703098114452883524">"Beskær"</string>
<string name="set_as" msgid="3636764710790507868">"Indstil som"</string>
<string name="video_err" msgid="7003051631792271009">"Videoen kan ikke afspilles."</string>
<string name="group_by_location" msgid="316641628989023253">"Efter placering"</string>
<string name="process_caching_requests" msgid="8722939570307386071">"Caching-Anfragen werden verarbeitet."</string>
<string name="caching_label" msgid="4521059045896269095">"Caching läuft..."</string>
<string name="crop_action" msgid="3427470284074377001">"Zuschneiden"</string>
- <!-- no translation found for trim_action (703098114452883524) -->
- <skip />
+ <string name="trim_action" msgid="703098114452883524">"Zuschneiden"</string>
<string name="set_as" msgid="3636764710790507868">"Festlegen als"</string>
<string name="video_err" msgid="7003051631792271009">"Video kann nicht wiedergegeben werden."</string>
<string name="group_by_location" msgid="316641628989023253">"Nach Standort"</string>
<string name="process_caching_requests" msgid="8722939570307386071">"Επεξεργασία αιτημάτων προσωρινής αποθήκευσης"</string>
<string name="caching_label" msgid="4521059045896269095">"Προσωρ. αποθ..."</string>
<string name="crop_action" msgid="3427470284074377001">"Περικοπή"</string>
- <!-- no translation found for trim_action (703098114452883524) -->
- <skip />
+ <string name="trim_action" msgid="703098114452883524">"Περικοπή"</string>
<string name="set_as" msgid="3636764710790507868">"Ορισμός ως"</string>
<string name="video_err" msgid="7003051631792271009">"Δεν είναι δυνατή η αναπαραγωγή βίντεο."</string>
<string name="group_by_location" msgid="316641628989023253">"Κατά τοποθεσία"</string>
<string name="process_caching_requests" msgid="8722939570307386071">"Process Caching Requests"</string>
<string name="caching_label" msgid="4521059045896269095">"Caching..."</string>
<string name="crop_action" msgid="3427470284074377001">"Crop"</string>
- <!-- no translation found for trim_action (703098114452883524) -->
- <skip />
+ <string name="trim_action" msgid="703098114452883524">"Trim"</string>
<string name="set_as" msgid="3636764710790507868">"Set as"</string>
<string name="video_err" msgid="7003051631792271009">"Cannot play video"</string>
<string name="group_by_location" msgid="316641628989023253">"By location"</string>
<string name="process_caching_requests" msgid="8722939570307386071">"Demandes de mise en cache en cours de traitement"</string>
<string name="caching_label" msgid="4521059045896269095">"Mise en cache…"</string>
<string name="crop_action" msgid="3427470284074377001">"Rogner"</string>
- <!-- no translation found for trim_action (703098114452883524) -->
- <skip />
+ <string name="trim_action" msgid="703098114452883524">"Rogner"</string>
<string name="set_as" msgid="3636764710790507868">"Définir comme"</string>
<string name="video_err" msgid="7003051631792271009">"Impossible de lire la vidéo."</string>
<string name="group_by_location" msgid="316641628989023253">"Par emplacement"</string>
<string name="process_caching_requests" msgid="8722939570307386071">"Elaborazione richieste memorizzazione cache"</string>
<string name="caching_label" msgid="4521059045896269095">"Memorizzazione..."</string>
<string name="crop_action" msgid="3427470284074377001">"Ritaglia"</string>
- <!-- no translation found for trim_action (703098114452883524) -->
- <skip />
+ <string name="trim_action" msgid="703098114452883524">"Ritaglia"</string>
<string name="set_as" msgid="3636764710790507868">"Imposta come"</string>
<string name="video_err" msgid="7003051631792271009">"Impossibile riprodurre il video."</string>
<string name="group_by_location" msgid="316641628989023253">"Per luogo"</string>
<string name="process_caching_requests" msgid="8722939570307386071">"מעבד בקשות העברה למטמון"</string>
<string name="caching_label" msgid="4521059045896269095">"מעביר למטמון..."</string>
<string name="crop_action" msgid="3427470284074377001">"חתוך"</string>
- <!-- no translation found for trim_action (703098114452883524) -->
- <skip />
+ <string name="trim_action" msgid="703098114452883524">"חתוך"</string>
<string name="set_as" msgid="3636764710790507868">"הגדר בתור"</string>
<string name="video_err" msgid="7003051631792271009">"לא ניתן להפעיל את סרטון הווידאו."</string>
<string name="group_by_location" msgid="316641628989023253">"לפי מיקום"</string>
<string name="process_caching_requests" msgid="8722939570307386071">"Behandler forespørsler om bufring"</string>
<string name="caching_label" msgid="4521059045896269095">"Henter …"</string>
<string name="crop_action" msgid="3427470284074377001">"Beskjær"</string>
- <!-- no translation found for trim_action (703098114452883524) -->
- <skip />
+ <string name="trim_action" msgid="703098114452883524">"Beskjær"</string>
<string name="set_as" msgid="3636764710790507868">"Angi som"</string>
<string name="video_err" msgid="7003051631792271009">"Kan ikke spille av video."</string>
<string name="group_by_location" msgid="316641628989023253">"Etter posisjon"</string>
<string name="process_caching_requests" msgid="8722939570307386071">"Cacheverzoeken verwerken"</string>
<string name="caching_label" msgid="4521059045896269095">"In cache opslaan..."</string>
<string name="crop_action" msgid="3427470284074377001">"Bijsnijden"</string>
- <!-- no translation found for trim_action (703098114452883524) -->
- <skip />
+ <string name="trim_action" msgid="703098114452883524">"Bijsnijden"</string>
<string name="set_as" msgid="3636764710790507868">"Instellen als"</string>
<string name="video_err" msgid="7003051631792271009">"Video kan niet worden afgespeeld."</string>
<string name="group_by_location" msgid="316641628989023253">"Op locatie"</string>
<string name="process_caching_requests" msgid="8722939570307386071">"Przetwarzanie żądań dotyczących buforowania"</string>
<string name="caching_label" msgid="4521059045896269095">"Buforowanie…"</string>
<string name="crop_action" msgid="3427470284074377001">"Przytnij"</string>
- <!-- no translation found for trim_action (703098114452883524) -->
- <skip />
+ <string name="trim_action" msgid="703098114452883524">"Przytnij"</string>
<string name="set_as" msgid="3636764710790507868">"Ustaw jako"</string>
<string name="video_err" msgid="7003051631792271009">"Nie można odtworzyć filmu."</string>
<string name="group_by_location" msgid="316641628989023253">"Według lokalizacji"</string>
<string name="process_caching_requests" msgid="8722939570307386071">"A processar pedidos de colocação em cache"</string>
<string name="caching_label" msgid="4521059045896269095">"A col. cache..."</string>
<string name="crop_action" msgid="3427470284074377001">"Recortar"</string>
- <!-- no translation found for trim_action (703098114452883524) -->
- <skip />
+ <string name="trim_action" msgid="703098114452883524">"Recortar"</string>
<string name="set_as" msgid="3636764710790507868">"Definir como"</string>
<string name="video_err" msgid="7003051631792271009">"Não é possível reproduzir vídeo."</string>
<string name="group_by_location" msgid="316641628989023253">"Por localização"</string>
<string name="process_caching_requests" msgid="8722939570307386071">"Begäran om cachelagring bearbetas"</string>
<string name="caching_label" msgid="4521059045896269095">"Cachelagrar ..."</string>
<string name="crop_action" msgid="3427470284074377001">"Beskär"</string>
- <!-- no translation found for trim_action (703098114452883524) -->
- <skip />
+ <string name="trim_action" msgid="703098114452883524">"Beskär"</string>
<string name="set_as" msgid="3636764710790507868">"Använd som"</string>
<string name="video_err" msgid="7003051631792271009">"Det går inte att spela upp videon."</string>
<string name="group_by_location" msgid="316641628989023253">"Efter plats"</string>
<string name="process_caching_requests" msgid="8722939570307386071">"Maombi ya kuakibisha michakato"</string>
<string name="caching_label" msgid="4521059045896269095">"Inaakibisha..."</string>
<string name="crop_action" msgid="3427470284074377001">"Punguza"</string>
- <!-- no translation found for trim_action (703098114452883524) -->
- <skip />
+ <string name="trim_action" msgid="703098114452883524">"Punguza"</string>
<string name="set_as" msgid="3636764710790507868">"Weka kama"</string>
<string name="video_err" msgid="7003051631792271009">"Video haiwezi kuchezwa."</string>
<string name="group_by_location" msgid="316641628989023253">"Kwa mahali"</string>
<string name="process_caching_requests" msgid="8722939570307386071">"Ilungisa izicelo zokufaka kwinqolobane"</string>
<string name="caching_label" msgid="4521059045896269095">"Ukulondoloza isikhashana..."</string>
<string name="crop_action" msgid="3427470284074377001">"Khropha"</string>
- <!-- no translation found for trim_action (703098114452883524) -->
- <skip />
+ <string name="trim_action" msgid="703098114452883524">"Lungisa"</string>
<string name="set_as" msgid="3636764710790507868">"Hlela njenge"</string>
<string name="video_err" msgid="7003051631792271009">"Ayikwazi ukudlala ividiyo"</string>
<string name="group_by_location" msgid="316641628989023253">"Ngendawo"</string>
import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
import android.os.Vibrator;
import android.provider.MediaStore;
import android.widget.Toast;
import com.android.gallery3d.ui.AlbumSlotRenderer;
import com.android.gallery3d.ui.DetailsHelper;
import com.android.gallery3d.ui.DetailsHelper.CloseListener;
-import com.android.gallery3d.ui.FadeTexture;
import com.android.gallery3d.ui.GLCanvas;
import com.android.gallery3d.ui.GLRoot;
import com.android.gallery3d.ui.GLView;
import com.android.gallery3d.ui.RelativePosition;
import com.android.gallery3d.ui.SelectionManager;
import com.android.gallery3d.ui.SlotView;
-import com.android.gallery3d.ui.SynchronizedHandler;
import com.android.gallery3d.util.Future;
import com.android.gallery3d.util.GalleryUtils;
import com.android.gallery3d.util.MediaSetUtils;
private MediaSet mMediaSet;
private boolean mShowDetails;
private float mUserDistance; // in pixel
- private Handler mHandler;
-
private Future<Integer> mSyncTask = null;
private int mLoadingBits = 0;
mSlotView.startScatteringAnimation(mOpenCenter);
}
}
-
- mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {
- @Override
- public void handleMessage(Message message) {
- switch (message.what) {
- case MSG_PICK_PHOTO: {
- pickPhoto(message.arg1);
- break;
- }
- default: throw new AssertionError(message.what);
- }
- }
- };
}
@Override
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
R.string.empty_album, Toast.LENGTH_LONG).show();
mActivity.getStateManager().finishState(this);
} else {
- emptyGalleryPrompt((Activity) mActivity);
+ emptyGalleryPrompt(mActivity);
}
} else if (mEmptyGalleryPrompt != null) {
mEmptyGalleryPrompt = null;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.Window;
+import com.android.camera.Util;
import com.android.gallery3d.R;
import com.android.gallery3d.common.ApiHelper;
import com.android.gallery3d.common.BitmapUtils;
-import com.android.gallery3d.common.ExifTags;
import com.android.gallery3d.common.Utils;
import com.android.gallery3d.data.DataManager;
import com.android.gallery3d.data.LocalImage;
import com.android.gallery3d.data.MediaItem;
import com.android.gallery3d.data.MediaObject;
import com.android.gallery3d.data.Path;
+import com.android.gallery3d.exif.ExifData;
+import com.android.gallery3d.exif.ExifOutputStream;
+import com.android.gallery3d.exif.ExifReader;
+import com.android.gallery3d.exif.ExifTag;
+import com.android.gallery3d.exif.IfdId;
import com.android.gallery3d.picasasource.PicasaSource;
import com.android.gallery3d.ui.BitmapTileProvider;
import com.android.gallery3d.ui.CropView;
import com.android.gallery3d.util.ThreadPool.JobContext;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
}
private File saveMedia(
- JobContext jc, Bitmap cropped, File directory, String filename) {
+ JobContext jc, Bitmap cropped, File directory, String filename, ExifData exifData) {
// Try file-1.jpg, file-2.jpg, ... until we find a filename
// which does not exist yet.
File candidate = null;
try {
FileOutputStream fos = new FileOutputStream(candidate);
try {
- saveBitmapToOutputStream(jc, cropped,
- convertExtensionToCompressFormat(fileExtension), fos);
+ if (exifData != null) {
+ ExifOutputStream eos = new ExifOutputStream(fos);
+ eos.setExifData(exifData);
+ saveBitmapToOutputStream(jc, cropped,
+ convertExtensionToCompressFormat(fileExtension), eos);
+ } else {
+ saveBitmapToOutputStream(jc, cropped,
+ convertExtensionToCompressFormat(fileExtension), fos);
+ }
} finally {
fos.close();
}
return candidate;
}
+ private ExifData getExifData(String path) {
+ FileInputStream is = null;
+ try {
+ is = new FileInputStream(path);
+ ExifReader reader = new ExifReader();
+ ExifData data = reader.read(is);
+ return data;
+ } catch (Throwable t) {
+ Log.w(TAG, "Cannot read EXIF data", t);
+ return null;
+ } finally {
+ Util.closeSilently(is);
+ }
+ }
+
+ private void changeExifImageSizeTag(ExifData data, int width, int height) {
+ data.getIfdData(IfdId.TYPE_IFD_0).getTag(ExifTag.TIFF_TAG.TAG_IMAGE_WIDTH).setValue(width);
+ data.getIfdData(IfdId.TYPE_IFD_0).getTag(ExifTag.TIFF_TAG.TAG_IMAGE_HEIGHT).setValue(
+ height);
+ }
+
private Uri saveToMediaProvider(JobContext jc, Bitmap cropped) {
if (PicasaSource.isPicasaImage(mMediaItem)) {
return savePicasaImage(jc, cropped);
String filename = PicasaSource.getImageTitle(mMediaItem);
int pos = filename.lastIndexOf('.');
if (pos >= 0) filename = filename.substring(0, pos);
- File output = saveMedia(jc, cropped, DOWNLOAD_BUCKET, filename);
+ File output = saveMedia(jc, cropped, DOWNLOAD_BUCKET, filename, null);
if (output == null) return null;
copyExif(mMediaItem, output.getAbsolutePath(), cropped.getWidth(), cropped.getHeight());
String filename = oldPath.getName();
int pos = filename.lastIndexOf('.');
if (pos >= 0) filename = filename.substring(0, pos);
- File output = saveMedia(jc, cropped, directory, filename);
- if (output == null) return null;
+ File output = null;
- copyExif(oldPath.getAbsolutePath(), output.getAbsolutePath(),
- cropped.getWidth(), cropped.getHeight());
+ ExifData exifData = null;
+ if (convertExtensionToCompressFormat(getFileExtension()) == CompressFormat.JPEG) {
+ exifData = getExifData(oldPath.getAbsolutePath());
+ if (exifData != null) {
+ changeExifImageSizeTag(exifData, cropped.getWidth(), cropped.getHeight());
+ }
+ }
+ output = saveMedia(jc, cropped, directory, filename, exifData);
+ if (output == null) return null;
long now = System.currentTimeMillis() / 1000;
ContentValues values = new ContentValues();
String filename = new SimpleDateFormat(TIME_STAMP_NAME).
format(new Date(now));
- File output = saveMedia(jc, cropped, DOWNLOAD_BUCKET, filename);
+ File output = saveMedia(jc, cropped, DOWNLOAD_BUCKET, filename, null);
if (output == null) return null;
ContentValues values = new ContentValues();
}
});
try {
- bitmap.compress(format, DEFAULT_COMPRESS_QUALITY, os);
+ bitmap.compress(format, DEFAULT_COMPRESS_QUALITY, ios);
return !jc.isCancelled();
} finally {
jc.setCancelListener(null);
- Utils.closeSilently(os);
+ Utils.closeSilently(ios);
}
}
private boolean saveBitmapToUri(JobContext jc, Bitmap bitmap, Uri uri) {
try {
- return saveBitmapToOutputStream(jc, bitmap,
- convertExtensionToCompressFormat(getFileExtension()),
- getContentResolver().openOutputStream(uri));
+ OutputStream out = getContentResolver().openOutputStream(uri);
+ try {
+ return saveBitmapToOutputStream(jc, bitmap,
+ convertExtensionToCompressFormat(getFileExtension()), out);
+ } finally {
+ Utils.closeSilently(out);
+ }
} catch (FileNotFoundException e) {
Log.w(TAG, "cannot write output", e);
}
}
}
- private static final String[] EXIF_TAGS = {
- ExifInterface.TAG_DATETIME,
- ExifInterface.TAG_MAKE,
- ExifInterface.TAG_MODEL,
- ExifInterface.TAG_FLASH,
- ExifInterface.TAG_GPS_LATITUDE,
- ExifInterface.TAG_GPS_LONGITUDE,
- ExifInterface.TAG_GPS_LATITUDE_REF,
- ExifInterface.TAG_GPS_LONGITUDE_REF,
- ExifInterface.TAG_GPS_ALTITUDE,
- ExifInterface.TAG_GPS_ALTITUDE_REF,
- ExifInterface.TAG_GPS_TIMESTAMP,
- ExifInterface.TAG_GPS_DATESTAMP,
- ExifInterface.TAG_WHITE_BALANCE,
- ExifInterface.TAG_FOCAL_LENGTH,
- ExifInterface.TAG_GPS_PROCESSING_METHOD};
-
private static void copyExif(MediaItem item, String destination, int newWidth, int newHeight) {
try {
ExifInterface newExif = new ExifInterface(destination);
Log.w(TAG, "cannot copy exif: " + item, t);
}
}
-
- private static void copyExif(String source, String destination, int newWidth, int newHeight) {
- try {
- ExifInterface oldExif = new ExifInterface(source);
- ExifInterface newExif = new ExifInterface(destination);
-
- newExif.setAttribute(ExifInterface.TAG_IMAGE_WIDTH, String.valueOf(newWidth));
- newExif.setAttribute(ExifInterface.TAG_IMAGE_LENGTH, String.valueOf(newHeight));
- newExif.setAttribute(ExifInterface.TAG_ORIENTATION, String.valueOf(0));
-
- for (String tag : EXIF_TAGS) {
- String value = oldExif.getAttribute(tag);
- if (value != null) {
- newExif.setAttribute(tag, value);
- }
- }
-
- // Handle some special values here
- String value = oldExif.getAttribute(ExifTags.TAG_APERTURE);
- if (value != null) {
- try {
- float aperture = Float.parseFloat(value);
- newExif.setAttribute(ExifTags.TAG_APERTURE,
- String.valueOf((int) (aperture * 10 + 0.5f)) + "/10");
- } catch (NumberFormatException e) {
- Log.w(TAG, "cannot parse aperture: " + value);
- }
- }
-
- // TODO: The code is broken, need to fix the JHEAD lib
- /*
- value = oldExif.getAttribute(ExifTags.TAG_EXPOSURE_TIME);
- if (value != null) {
- try {
- double exposure = Double.parseDouble(value);
- testToRational("test exposure", exposure);
- newExif.setAttribute(ExifTags.TAG_EXPOSURE_TIME, value);
- } catch (NumberFormatException e) {
- Log.w(TAG, "cannot parse exposure time: " + value);
- }
- }
-
- value = oldExif.getAttribute(ExifTags.TAG_ISO);
- if (value != null) {
- try {
- int iso = Integer.parseInt(value);
- newExif.setAttribute(ExifTags.TAG_ISO, String.valueOf(iso) + "/1");
- } catch (NumberFormatException e) {
- Log.w(TAG, "cannot parse exposure time: " + value);
- }
- }*/
- newExif.saveAttributes();
- } catch (Throwable t) {
- Log.w(TAG, "cannot copy exif: " + source, t);
- }
- }
}
mLayoutReady = false;
mEyePosition.resetPosition();
- Activity activity = (Activity) mActivity;
int slotViewTop = mActivity.getGalleryActionBar().getHeight();
int slotViewBottom = bottom - top;
- View footer = activity.findViewById(R.id.footer);
+ View footer = mActivity.findViewById(R.id.footer);
if (footer != null) {
int location[] = {0, 0};
footer.getLocationOnScreen(location);
}
private void initializeViews() {
- Activity activity = (Activity) mActivity;
+ Activity activity = mActivity;
mSelectionManager = new SelectionManager(mActivity, true);
mSelectionManager.setSelectionListener(this);
}
private void initializeFooterViews() {
- Activity activity = (Activity) mActivity;
+ Activity activity = mActivity;
LayoutInflater inflater = activity.getLayoutInflater();
mFooterContent = inflater.inflate(R.layout.manage_offline_bar, null);
private void showToast() {
if (mAlbumCountToMakeAvailableOffline > 0) {
- Activity activity = (Activity) mActivity;
+ Activity activity = mActivity;
Toast.makeText(activity, activity.getResources().getQuantityString(
R.plurals.make_albums_available_offline,
mAlbumCountToMakeAvailableOffline),
}
private void showToastForLocalAlbum() {
- Activity activity = (Activity) mActivity;
+ Activity activity = mActivity;
Toast.makeText(activity, activity.getResources().getString(
R.string.try_to_set_local_album_available_offline),
Toast.LENGTH_SHORT).show();
long expectedBytes = mCacheStorageInfo.getExpectedUsedBytes();
long freeBytes = mCacheStorageInfo.getFreeBytes();
- Activity activity = (Activity) mActivity;
+ Activity activity = mActivity;
if (totalBytes == 0) {
progressBar.setProgress(0);
progressBar.setSecondaryProgress(0);
});
}
+ @SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void showSystemUi(boolean visible) {
if (!ApiHelper.HAS_VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE) return;
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
if (!visible) {
+ // We used the deprecated "STATUS_BAR_HIDDEN" for unbundling
flag |= View.STATUS_BAR_HIDDEN | View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
}
private NfcAdapter mNfcAdapter;
- private Menu mActionBarMenu;
-
private final MyMenuVisibilityListener mMenuVisibilityListener =
new MyMenuVisibilityListener();
// The path should be "/local/image", "local/video" or "/local/all"
public class LocalAlbumSet extends MediaSet
implements FutureListener<ArrayList<MediaSet>> {
+ @SuppressWarnings("unused")
+ private static final String TAG = "LocalAlbumSet";
+
public static final Path PATH_ALL = Path.fromString("/local/all");
public static final Path PATH_IMAGE = Path.fromString("/local/image");
public static final Path PATH_VIDEO = Path.fromString("/local/video");
- private static final String TAG = "LocalAlbumSet";
-
private static final Uri[] mWatchUris =
{Images.Media.EXTERNAL_CONTENT_URI, Video.Media.EXTERNAL_CONTENT_URI};
private final GalleryApp mApplication;
private final int mDeviceId;
private final String mDeviceName;
- private final DataManager mDataManager;
private final MtpContext mMtpContext;
private final String mName;
private final ChangeNotifier mNotifier;
mApplication = application;
mDeviceId = deviceId;
mDeviceName = UsbDevice.getDeviceName(deviceId);
- mDataManager = application.getDataManager();
mMtpContext = mtpContext;
mName = name;
mNotifier = new ChangeNotifier(this, Uri.parse("mtp://"), application);
import com.android.gallery3d.app.GalleryApp;
import com.android.gallery3d.common.ApiHelper;
import com.android.gallery3d.provider.GalleryProvider;
-import com.android.gallery3d.util.ThreadPool;
import com.android.gallery3d.util.ThreadPool.Job;
import com.android.gallery3d.util.ThreadPool.JobContext;
private int mObjectSize;
private long mDateTaken;
private String mFileName;
- private final ThreadPool mThreadPool;
private final MtpContext mMtpContext;
private final MtpObjectInfo mObjInfo;
private final int mImageWidth;
mFileName = objInfo.getName();
mImageWidth = objInfo.getImagePixWidth();
mImageHeight = objInfo.getImagePixHeight();
- mThreadPool = application.getThreadPool();
mMtpContext = mtpContext;
}
import java.util.ArrayList;
public class SizeClustering extends Clustering {
+ @SuppressWarnings("unused")
private static final String TAG = "SizeClustering";
private Context mContext;
mContext = context;
}
+ @SuppressWarnings("unchecked")
@Override
public void run(MediaSet baseSet) {
- final ArrayList<Path>[] group =
- (ArrayList<Path>[]) new ArrayList[SIZE_LEVELS.length];
+ @SuppressWarnings("unchecked")
+ final ArrayList<Path>[] group = new ArrayList[SIZE_LEVELS.length];
baseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() {
@Override
public void consume(int index, MediaItem item) {
}
}
- mClusters = (ArrayList<Path>[]) new ArrayList[count];
+ mClusters = new ArrayList[count];
mNames = new String[count];
mMinSizes = new long[count];
import com.android.gallery3d.app.GalleryApp;
+import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
private static final String TAG = "UriSource";
private static final String IMAGE_TYPE_PREFIX = "image/";
private static final String IMAGE_TYPE_ANY = "image/*";
+ private static final String CHARSET_UTF_8 = "utf-8";
private GalleryApp mApplication;
if (segment.length != 3) {
throw new RuntimeException("bad path: " + path);
}
- String uri = URLDecoder.decode(segment[1]);
- String type = URLDecoder.decode(segment[2]);
- return new UriImage(mApplication, path, Uri.parse(uri), type);
+ try {
+ String uri = URLDecoder.decode(segment[1], CHARSET_UTF_8);
+ String type = URLDecoder.decode(segment[2], CHARSET_UTF_8);
+ return new UriImage(mApplication, path, Uri.parse(uri), type);
+ } catch (UnsupportedEncodingException e) {
+ throw new AssertionError(e);
+ }
}
private String getMimeType(Uri uri) {
}
if (type.startsWith(IMAGE_TYPE_PREFIX)) {
- return Path.fromString("/uri/" + URLEncoder.encode(uri.toString())
- + "/" +URLEncoder.encode(type));
+ try {
+ return Path.fromString("/uri/"
+ + URLEncoder.encode(uri.toString(), CHARSET_UTF_8)
+ + "/" +URLEncoder.encode(type, CHARSET_UTF_8));
+ } catch (UnsupportedEncodingException e) {
+ throw new AssertionError(e);
+ }
}
// We have no clues that it is an image
return null;
import java.nio.ByteOrder;
import java.util.ArrayList;
+import java.util.Arrays;
/**
* This class stores the EXIF header in IFDs according to the JPEG specification.
public ByteOrder getByteOrder() {
return mByteOrder;
}
+
+ /**
+ * Returns true if this header contains compressed strip of thumbnail.
+ */
+ public boolean hasUncompressedStrip() {
+ return mStripBytes.size() != 0;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ExifData) {
+ ExifData data = (ExifData) obj;
+ if (data.mByteOrder != mByteOrder
+ || !Arrays.equals(data.mThumbnail, mThumbnail)
+ || data.mStripBytes.size() != mStripBytes.size()) return false;
+
+ for (int i = 0; i < mStripBytes.size(); i++) {
+ if (!Arrays.equals(data.mStripBytes.get(i), mStripBytes.get(i))) return false;
+ }
+
+ for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) {
+ if (!Util.equals(data.getIfdData(i), getIfdData(i))) return false;
+ }
+ return true;
+ }
+ return false;
+ }
}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.exif;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class ExifOutputStream extends FilterOutputStream {
+ private static final String TAG = "ExifOutputStream";
+
+ private static final int STATE_SOI = 0;
+ private static final int STATE_APP1 = 1;
+ private static final int STATE_JPEG_DATA = 2;
+
+ private static final short SOI = (short) 0xFFD8;
+ private static final short APP0 = (short) 0xFFE0;
+ private static final short APP1 = (short) 0xFFE1;
+ private static final int EXIF_HEADER = 0x45786966;
+ private static final short TIFF_HEADER = 0x002A;
+ private static final short TIFF_BIG_ENDIAN = 0x4d4d;
+ private static final short TIFF_LITTLE_ENDIAN = 0x4949;
+ private static final short TAG_SIZE = 12;
+ private static final short TIFF_HEADER_SIZE = 8;
+
+ private ExifData mExifData;
+ private int mState;
+ private int mByteToSkip;
+ private int mByteToCopy;
+ private ByteBuffer mBuffer = ByteBuffer.allocate(4);
+
+ public ExifOutputStream(OutputStream ou) {
+ super(ou);
+ }
+
+ public void setExifData(ExifData exifData) {
+ mExifData = exifData;
+ }
+
+ public ExifData getExifData() {
+ return mExifData;
+ }
+
+ private int requestByteToBuffer(int requestByteCount, byte[] buffer
+ , int offset, int length) {
+ int byteNeeded = requestByteCount - mBuffer.position();
+ int byteToRead = length > byteNeeded ? byteNeeded : length;
+ mBuffer.put(buffer, offset, byteToRead);
+ return byteToRead;
+ }
+
+ @Override
+ public void write(byte[] buffer, int offset, int length) throws IOException {
+ while((mByteToSkip > 0 || mByteToCopy > 0 || mState != STATE_JPEG_DATA)
+ && length > 0) {
+ if (mByteToSkip > 0) {
+ int byteToProcess = length > mByteToSkip ? mByteToSkip : length;
+ length -= byteToProcess;
+ mByteToSkip -= byteToProcess;
+ offset += byteToProcess;
+ }
+ if (mByteToCopy > 0) {
+ int byteToProcess = length > mByteToCopy ? mByteToCopy : length;
+ out.write(buffer, offset, byteToProcess);
+ length -= byteToProcess;
+ mByteToCopy -= byteToProcess;
+ offset += byteToProcess;
+ }
+ switch (mState) {
+ case STATE_SOI:
+ int byteRead = requestByteToBuffer(2, buffer, offset, length);
+ offset += byteRead;
+ length -= byteRead;
+ if (mBuffer.position() < 2) return;
+ mBuffer.rewind();
+ assert(mBuffer.getShort() == SOI);
+ out.write(mBuffer.array(), 0 ,2);
+ mState = STATE_APP1;
+ mBuffer.rewind();
+ break;
+ case STATE_APP1:
+ byteRead = requestByteToBuffer(4, buffer, offset, length);
+ offset += byteRead;
+ length -= byteRead;
+ if (mBuffer.position() < 4) return;
+ mBuffer.rewind();
+ if (mBuffer.getShort() == APP0) {
+ out.write(mBuffer.array(), 0 ,4);
+ mByteToCopy = (mBuffer.getShort() & 0xff) - 2;
+ } else if (mBuffer.getShort() == APP1) {
+ writeExifData();
+ mByteToSkip = (mBuffer.getShort() & 0xff) - 2;
+ mState = STATE_JPEG_DATA;
+ } else {
+ writeExifData();
+ out.write(mBuffer.array(), 0, 4);
+ mState = STATE_JPEG_DATA;
+ }
+ mBuffer.rewind();
+ break;
+ }
+ }
+ if (length > 0) {
+ out.write(buffer, offset, length);
+ }
+ }
+
+ @Override
+ public void write(int oneByte) throws IOException {
+ byte[] buf = new byte[] {(byte) (0xff & oneByte)};
+ write(buf);
+ }
+
+ @Override
+ public void write(byte[] buffer) throws IOException {
+ write(buffer, 0, buffer.length);
+ }
+
+ private void writeExifData() throws IOException {
+ createRequiredIfdAndTag();
+ int exifSize = calculateAllOffset();
+ OrderedDataOutputStream dataOutputStream = new OrderedDataOutputStream(out);
+ dataOutputStream.writeShort(APP1);
+ dataOutputStream.writeShort((short) (exifSize + 8));
+ dataOutputStream.writeInt(EXIF_HEADER);
+ dataOutputStream.writeShort((short) 0x0000);
+ if (mExifData.getByteOrder() == ByteOrder.BIG_ENDIAN) {
+ dataOutputStream.writeShort(TIFF_BIG_ENDIAN);
+ } else {
+ dataOutputStream.writeShort(TIFF_LITTLE_ENDIAN);
+ }
+ dataOutputStream.setByteOrder(mExifData.getByteOrder());
+ dataOutputStream.writeShort(TIFF_HEADER);
+ dataOutputStream.writeInt(8);
+ writeAllTag(dataOutputStream);
+ writeThumbnail(dataOutputStream);
+ }
+
+ private void writeThumbnail(OrderedDataOutputStream dataOutputStream) throws IOException {
+ if (mExifData.hasCompressedThumbnail()) {
+ dataOutputStream.write(mExifData.getCompressedThumbnail());
+ } else if (mExifData.hasUncompressedStrip()) {
+ for (int i = 0; i < mExifData.getStripCount(); i++) {
+ dataOutputStream.write(mExifData.getStrip(i));
+ }
+ }
+ }
+
+ private void writeAllTag(OrderedDataOutputStream dataOutputStream) throws IOException {
+ writeIfd(mExifData.getIfdData(IfdId.TYPE_IFD_0), dataOutputStream);
+ writeIfd(mExifData.getIfdData(IfdId.TYPE_IFD_EXIF), dataOutputStream);
+ IfdData interoperabilityIfd = mExifData.getIfdData(IfdId.TYPE_IFD_INTEROPERABILITY);
+ if (interoperabilityIfd != null) {
+ writeIfd(interoperabilityIfd, dataOutputStream);
+ }
+ IfdData gpsIfd = mExifData.getIfdData(IfdId.TYPE_IFD_GPS);
+ if (gpsIfd != null) {
+ writeIfd(gpsIfd, dataOutputStream);
+ }
+ IfdData ifd1 = mExifData.getIfdData(IfdId.TYPE_IFD_1);
+ if (ifd1 != null) {
+ writeIfd(mExifData.getIfdData(IfdId.TYPE_IFD_1), dataOutputStream);
+ }
+ }
+
+ private void writeIfd(IfdData ifd, OrderedDataOutputStream dataOutputStream)
+ throws IOException {
+ ExifTag[] tags = ifd.getAllTags(new ExifTag[] {});
+ dataOutputStream.writeShort((short) tags.length);
+ for (ExifTag tag: tags) {
+ dataOutputStream.writeShort(tag.getTagId());
+ dataOutputStream.writeShort(tag.getDataType());
+ dataOutputStream.writeInt(tag.getComponentCount());
+ if (tag.getDataSize() > 4) {
+ dataOutputStream.writeInt(tag.getOffset());
+ } else {
+ writeTagValue(tag, dataOutputStream);
+ for (int i = 0; i < 4 - tag.getDataSize(); i++) {
+ dataOutputStream.write(0);
+ }
+ }
+ }
+ dataOutputStream.writeInt(ifd.getOffsetToNextIfd());
+ for (ExifTag tag: tags) {
+ if (tag.getDataSize() > 4) {
+ writeTagValue(tag, dataOutputStream);
+ }
+ }
+ }
+
+ private void writeTagValue(ExifTag tag, OrderedDataOutputStream dataOutputStream)
+ throws IOException {
+ switch (tag.getDataType()) {
+ case ExifTag.TYPE_ASCII:
+ dataOutputStream.write(tag.getString().getBytes());
+ int remain = tag.getComponentCount() - tag.getString().getBytes().length;
+ for (int i = 0; i < remain; i++) {
+ dataOutputStream.write(0);
+ }
+ break;
+ case ExifTag.TYPE_INT:
+ for (int i = 0; i < tag.getComponentCount(); i++) {
+ dataOutputStream.writeInt(tag.getInt(i));
+ }
+ break;
+ case ExifTag.TYPE_RATIONAL:
+ case ExifTag.TYPE_UNSIGNED_RATIONAL:
+ for (int i = 0; i < tag.getComponentCount(); i++) {
+ dataOutputStream.writeRational(tag.getRational(i));
+ }
+ break;
+ case ExifTag.TYPE_UNDEFINED:
+ case ExifTag.TYPE_UNSIGNED_BYTE:
+ byte[] buf = new byte[tag.getComponentCount()];
+ tag.getBytes(buf);
+ dataOutputStream.write(buf);
+ break;
+ case ExifTag.TYPE_UNSIGNED_INT:
+ for (int i = 0; i < tag.getComponentCount(); i++) {
+ dataOutputStream.writeInt((int) tag.getUnsignedInt(i));
+ }
+ break;
+ case ExifTag.TYPE_UNSIGNED_SHORT:
+ for (int i = 0; i < tag.getComponentCount(); i++) {
+ dataOutputStream.writeShort((short) tag.getUnsignedShort(i));
+ }
+ break;
+ }
+ }
+
+ private int calculateOffsetOfIfd(IfdData ifd, int offset) {
+ offset += 2 + ifd.getTagCount() * TAG_SIZE + 4;
+ ExifTag[] tags = ifd.getAllTags(new ExifTag[] {});
+ for(ExifTag tag: tags) {
+ if (tag.getDataSize() > 4) {
+ tag.setOffset(offset);
+ offset += tag.getDataSize();
+ }
+ }
+ return offset;
+ }
+
+ private void createRequiredIfdAndTag() {
+ // IFD0 is required for all file
+ IfdData ifd0 = mExifData.getIfdData(IfdId.TYPE_IFD_0);
+ if (ifd0 == null) {
+ ifd0 = new IfdData(IfdId.TYPE_IFD_0);
+ mExifData.addIfdData(ifd0);
+ }
+ ExifTag exifOffsetTag = new ExifTag(ExifTag.TIFF_TAG.TAG_EXIF_IFD
+ , ExifTag.TYPE_UNSIGNED_INT, 1, IfdId.TYPE_IFD_0);
+ ifd0.setTag(exifOffsetTag);
+
+ // Exif IFD is required for all file.
+ IfdData exifIfd = mExifData.getIfdData(IfdId.TYPE_IFD_EXIF);
+ if (exifIfd == null) {
+ exifIfd = new IfdData(IfdId.TYPE_IFD_EXIF);
+ mExifData.addIfdData(exifIfd);
+ }
+
+ // GPS IFD
+ IfdData gpsIfd = mExifData.getIfdData(IfdId.TYPE_IFD_GPS);
+ if (gpsIfd != null) {
+ ExifTag gpsOffsetTag = new ExifTag(ExifTag.TIFF_TAG.TAG_GPS_IFD,
+ ExifTag.TYPE_UNSIGNED_INT, 1, IfdId.TYPE_IFD_0);
+ ifd0.setTag(gpsOffsetTag);
+ }
+
+ // Interoperability IFD
+ IfdData interIfd = mExifData.getIfdData(IfdId.TYPE_IFD_INTEROPERABILITY);
+ if (interIfd != null) {
+ ExifTag interOffsetTag = new ExifTag(ExifTag.EXIF_TAG.TAG_INTEROPERABILITY_IFD,
+ ExifTag.TYPE_UNSIGNED_INT, 1, IfdId.TYPE_IFD_EXIF);
+ exifIfd.setTag(interOffsetTag);
+ }
+
+ IfdData ifd1 = mExifData.getIfdData(IfdId.TYPE_IFD_1);
+
+ // thumbnail
+ if (mExifData.hasCompressedThumbnail()) {
+ if (ifd1 == null) {
+ ifd1 = new IfdData(IfdId.TYPE_IFD_1);
+ mExifData.addIfdData(ifd1);
+ }
+ ExifTag offsetTag = new ExifTag(ExifTag.TIFF_TAG.TAG_JPEG_INTERCHANGE_FORMAT,
+ ExifTag.TYPE_UNSIGNED_INT, 1, IfdId.TYPE_IFD_1);
+ ifd1.setTag(offsetTag);
+ ExifTag lengthTag = new ExifTag(ExifTag.TIFF_TAG.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
+ ExifTag.TYPE_UNSIGNED_INT, 1, IfdId.TYPE_IFD_1);
+ lengthTag.setValue(mExifData.getCompressedThumbnail().length);
+ ifd1.setTag(lengthTag);
+ } else if (mExifData.hasUncompressedStrip()){
+ if (ifd1 == null) {
+ ifd1 = new IfdData(IfdId.TYPE_IFD_1);
+ mExifData.addIfdData(ifd1);
+ }
+ int stripCount = mExifData.getStripCount();
+ ExifTag offsetTag = new ExifTag(ExifTag.TIFF_TAG.TAG_STRIP_OFFSETS,
+ ExifTag.TYPE_UNSIGNED_INT, stripCount, IfdId.TYPE_IFD_1);
+ ExifTag lengthTag = new ExifTag(ExifTag.TIFF_TAG.TAG_STRIP_BYTE_COUNTS,
+ ExifTag.TYPE_UNSIGNED_INT, stripCount, IfdId.TYPE_IFD_1);
+ long[] lengths = new long[stripCount];
+ for (int i = 0; i < mExifData.getStripCount(); i++) {
+ lengths[i] = mExifData.getStrip(i).length;
+ }
+ lengthTag.setValue(lengths);
+ ifd1.setTag(offsetTag);
+ ifd1.setTag(lengthTag);
+ }
+ }
+
+ private int calculateAllOffset() {
+ int offset = TIFF_HEADER_SIZE;
+ IfdData ifd0 = mExifData.getIfdData(IfdId.TYPE_IFD_0);
+ offset = calculateOffsetOfIfd(ifd0, offset);
+ ifd0.getTag(ExifTag.TIFF_TAG.TAG_EXIF_IFD).setValue(offset);
+
+ IfdData exifIfd = mExifData.getIfdData(IfdId.TYPE_IFD_EXIF);
+ offset = calculateOffsetOfIfd(exifIfd, offset);
+
+ IfdData interIfd = mExifData.getIfdData(IfdId.TYPE_IFD_INTEROPERABILITY);
+ if (interIfd != null) {
+ exifIfd.getTag(ExifTag.EXIF_TAG.TAG_INTEROPERABILITY_IFD).setValue(offset);
+ offset = calculateOffsetOfIfd(interIfd, offset);
+ }
+
+ IfdData gpsIfd = mExifData.getIfdData(IfdId.TYPE_IFD_GPS);
+ if (gpsIfd != null) {
+ ifd0.getTag(ExifTag.TIFF_TAG.TAG_GPS_IFD).setValue(offset);
+ offset = calculateOffsetOfIfd(gpsIfd, offset);
+ }
+
+ IfdData ifd1 = mExifData.getIfdData(IfdId.TYPE_IFD_1);
+ if (ifd1 != null) {
+ ifd0.setOffsetToNextIfd(offset);
+ offset = calculateOffsetOfIfd(ifd1, offset);
+ }
+
+ // thumbnail
+ if (mExifData.hasCompressedThumbnail()) {
+ ifd1.getTag(ExifTag.TIFF_TAG.TAG_JPEG_INTERCHANGE_FORMAT).setValue(offset);
+ offset += mExifData.getCompressedThumbnail().length;
+ } else if (mExifData.hasUncompressedStrip()){
+ int stripCount = mExifData.getStripCount();
+ long[] offsets = new long[stripCount];
+ for (int i = 0; i < mExifData.getStripCount(); i++) {
+ offsets[i] = offset;
+ offset += mExifData.getStrip(i).length;
+ }
+ ifd1.getTag(ExifTag.TIFF_TAG.TAG_STRIP_OFFSETS).setValue(offsets);
+ }
+ return offset;
+ }
+}
\ No newline at end of file
*/
public int getCompressedImageSize() {
if (mJpegSizeTag == null) return 0;
- return (int) mJpegSizeTag.getUnsignedInt();
+ return (int) mJpegSizeTag.getUnsignedInt(0);
}
private void skipTo(int offset) throws IOException {
"Number of component is larger then Integer.MAX_VALUE");
}
ExifTag tag = new ExifTag(tagId, dataFormat, (int) numOfComp, mIfdType);
- if (tag.getDataSize() > 4) {
+ int dataSize = tag.getDataSize();
+ if (dataSize > 4) {
long offset = mTiffStream.readUnsignedInt();
if (offset > Integer.MAX_VALUE) {
throw new ExifInvalidFormatException(
tag.setOffset((int) offset);
} else {
readFullTagValue(tag);
- mTiffStream.skip(4 - tag.getDataSize());
+ mTiffStream.skip(4 - dataSize);
}
return tag;
}
case ExifTag.TIFF_TAG.TAG_EXIF_IFD:
if (isIfdRequested(IfdId.TYPE_IFD_EXIF)
|| isIfdRequested(IfdId.TYPE_IFD_INTEROPERABILITY)) {
- registerIfd(IfdId.TYPE_IFD_EXIF, tag.getUnsignedInt());
+ registerIfd(IfdId.TYPE_IFD_EXIF, tag.getUnsignedInt(0));
}
break;
case ExifTag.TIFF_TAG.TAG_GPS_IFD:
if (isIfdRequested(IfdId.TYPE_IFD_GPS)) {
- registerIfd(IfdId.TYPE_IFD_GPS, tag.getUnsignedInt());
+ registerIfd(IfdId.TYPE_IFD_GPS, tag.getUnsignedInt(0));
}
break;
case ExifTag.EXIF_TAG.TAG_INTEROPERABILITY_IFD:
if (isIfdRequested(IfdId.TYPE_IFD_INTEROPERABILITY)) {
- registerIfd(IfdId.TYPE_IFD_INTEROPERABILITY, tag.getUnsignedInt());
+ registerIfd(IfdId.TYPE_IFD_INTEROPERABILITY, tag.getUnsignedInt(0));
}
break;
case ExifTag.TIFF_TAG.TAG_JPEG_INTERCHANGE_FORMAT:
if (isThumbnailRequested()) {
- registerCompressedImage(tag.getUnsignedInt());
+ registerCompressedImage(tag.getUnsignedInt(0));
}
break;
case ExifTag.TIFF_TAG.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH:
package com.android.gallery3d.exif;
import java.lang.reflect.Array;
+import java.util.Arrays;
/**
* This class stores information of an EXIF tag.
}
public static interface GPS_TAG {
- public static final short GPS_VERSION_ID = 0;
- public static final short GPS_LATITUDE_REF = 1;
- public static final short GPS_LATITUDE = 2;
- public static final short GPS_LONGITUDE_REF = 3;
- public static final short GPS_LONGITUDE = 4;
- public static final short GPS_ALTITUDE_REF = 5;
- public static final short GPS_ALTITUDE = 6;
- public static final short GPS_TIME_STAMP = 7;
- public static final short GPS_SATTELLITES = 8;
- public static final short GPS_STATUS = 9;
- public static final short GPS_MEASURE_MODE = 10;
- public static final short GPS_DOP = 11;
- public static final short GPS_SPEED_REF = 12;
- public static final short GPS_SPEED = 13;
- public static final short GPS_TRACK_REF = 14;
- public static final short GPS_TRACK = 15;
- public static final short GPS_IMG_DIRECTION_REF = 16;
- public static final short GPS_IMG_DIRECTION = 17;
- public static final short GPS_MAP_DATUM = 18;
- public static final short GPS_DEST_LATITUDE_REF = 19;
- public static final short GPS_DEST_LATITUDE = 20;
- public static final short GPS_DEST_LONGITUDE_REF = 21;
- public static final short GPS_DEST_LONGITUDE = 22;
- public static final short GPS_DEST_BEARING_REF = 23;
- public static final short GPS_DEST_BEARING = 24;
- public static final short GPS_DEST_DISTANCE_REF = 25;
- public static final short GPS_DEST_DISTANCE = 26;
- public static final short GPS_PROCESSING_METHOD = 27;
- public static final short GPS_AREA_INFORMATION = 28;
- public static final short GPS_DATA_STAMP = 29;
- public static final short GPS_DIFFERENTIAL = 30;
+ public static final short TAG_GPS_VERSION_ID = 0;
+ public static final short TAG_GPS_LATITUDE_REF = 1;
+ public static final short TAG_GPS_LATITUDE = 2;
+ public static final short TAG_GPS_LONGITUDE_REF = 3;
+ public static final short TAG_GPS_LONGITUDE = 4;
+ public static final short TAG_GPS_ALTITUDE_REF = 5;
+ public static final short TAG_GPS_ALTITUDE = 6;
+ public static final short TAG_GPS_TIME_STAMP = 7;
+ public static final short TAG_GPS_SATTELLITES = 8;
+ public static final short TAG_GPS_STATUS = 9;
+ public static final short TAG_GPS_MEASURE_MODE = 10;
+ public static final short TAG_GPS_DOP = 11;
+ public static final short TAG_GPS_SPEED_REF = 12;
+ public static final short TAG_GPS_SPEED = 13;
+ public static final short TAG_GPS_TRACK_REF = 14;
+ public static final short TAG_GPS_TRACK = 15;
+ public static final short TAG_GPS_IMG_DIRECTION_REF = 16;
+ public static final short TAG_GPS_IMG_DIRECTION = 17;
+ public static final short TAG_GPS_MAP_DATUM = 18;
+ public static final short TAG_GPS_DEST_LATITUDE_REF = 19;
+ public static final short TAG_GPS_DEST_LATITUDE = 20;
+ public static final short TAG_GPS_DEST_LONGITUDE_REF = 21;
+ public static final short TAG_GPS_DEST_LONGITUDE = 22;
+ public static final short TAG_GPS_DEST_BEARING_REF = 23;
+ public static final short TAG_GPS_DEST_BEARING = 24;
+ public static final short TAG_GPS_DEST_DISTANCE_REF = 25;
+ public static final short TAG_GPS_DEST_DISTANCE = 26;
+ public static final short TAG_GPS_PROCESSING_METHOD = 27;
+ public static final short TAG_GPS_AREA_INFORMATION = 28;
+ public static final short TAG_GPS_DATA_STAMP = 29;
+ public static final short TAG_GPS_DIFFERENTIAL = 30;
public static final String GPS_REF_NORTH = "N";
public static final String GPS_REF_SOUTH = "S";
private final short mTagId;
private final short mDataType;
- private final int mComponentCount;
private final int mIfd;
+ private int mComponentCount;
private Object mValue;
private int mOffset;
}
/**
- * Sets the value of this tag. This is useful when we want to modify the tags and write it back
- * to the JPEG file
+ * Sets integer values into this tag. This is useful when we want to modify the tags
+ * and write it back to the JPEG file. The component count will be set to the length.
*/
- public void setValue(Object object) {
- if (object.getClass().isArray()) {
- assert(mComponentCount == Array.getLength(object));
- mValue = object;
- } else if (object instanceof String) {
- assert(mComponentCount == ((String) object).length() + 1);
- mValue = object;
- } else {
- // Wrap object with an array because user may try to get object by get method with
- // index 0 when size = 1
- // e.g. getShort(0)
- assert(mComponentCount == 1);
- Object array = Array.newInstance(object.getClass(), 1);
- Array.set(array, 0, object);
- mValue = array;
+ public void setValue(int[] value) {
+ long[] data = new long[value.length];
+ for (int i = 0; i < value.length; i++) {
+ data[i] = value[i];
}
+ mValue = data;
+ mComponentCount = value.length;
}
- public short getShort(int index) {
- return (Short) Array.get(mValue, index);
+ /**
+ * Sets integer value into this tag. This is useful when we want to modify the tags
+ * and write it back to the JPEG file. The component count will be set to 1.
+ */
+ public void setValue(int value) {
+ mValue = new long[] {value};
+ mComponentCount = 1;
}
- public short getShort() {
- return (Short) Array.get(mValue, 0);
+ /**
+ * Sets short values into this tag. This is useful when we want to modify the tags
+ * and write it back to the JPEG file. The component count will be set to the length.
+ */
+ public void setValue(short[] value) {
+ long[] data = new long[value.length];
+ for (int i = 0; i < value.length; i++) {
+ data[i] = value[i];
+ }
+ mValue = data;
+ mComponentCount = value.length;
}
- public int getUnsignedShort(int index) {
- return (Integer) Array.get(mValue, index);
+ /**
+ * Sets short value into this tag. This is useful when we want to modify the tags
+ * and write it back to the JPEG file. The component count will be set to 1.
+ */
+ public void setValue(short value) {
+ mValue = new long[] {value};
+ mComponentCount = 1;
}
- public int getUnsignedShort() {
- return (Integer) Array.get(mValue, 0);
+ /**
+ * Sets long values into this tag. This is useful when we want to modify the tags
+ * and write it back to the JPEG file. The component count will be set to the length.
+ */
+ public void setValue(long[] value) {
+ long[] data = new long[value.length];
+ System.arraycopy(value, 0, data, 0, value.length);
+ mValue = data;
+ mComponentCount = value.length;
}
- public int getInt(int index) {
- return (Integer) Array.get(mValue, index);
+ /**
+ * Sets long value into this tag. This is useful when we want to modify the tags
+ * and write it back to the JPEG file. The component count will be set to 1.
+ */
+ public void setValue(long value) {
+ mValue = new long[] {value};
+ mComponentCount = 1;
}
- public int getInt() {
- return (Integer) Array.get(mValue, 0);
+ /**
+ * Sets String value into this tag. This is useful when we want to modify the tags
+ * and write it back to the JPEG file. The component count will be set to
+ * value.length() + 1.
+ */
+ public void setValue(String value) {
+ mComponentCount = value.length() + 1;
+ mValue = value;
}
- public long getUnsignedInt(int index) {
- return (Long) Array.get(mValue, index);
+ /**
+ * Sets Rational values into this tag. This is useful when we want to modify the tags
+ * and write it back to the JPEG file. The component count will be set to the length.
+ */
+ public void setValue(Rational[] value) {
+ mValue = new Rational[value.length];
+ System.arraycopy(value, 0, mValue, 0, value.length);
+ mComponentCount = value.length;
}
- public long getUnsignedInt() {
- return (Long) Array.get(mValue, 0);
+ /**
+ * Sets Rational value into this tag. This is useful when we want to modify the tags
+ * and write it back to the JPEG file. The component count will be set to 1.
+ */
+ public void setValue(Rational value) {
+ mValue = new Rational[] {value};
+ mComponentCount = 1;
}
- public String getString() {
- return (String) mValue;
+ /**
+ * Sets byte values into this tag. This is useful when we want to modify the tags
+ * and write it back to the JPEG file. The component count will be set to the length.
+ */
+ public void setValue(byte[] value, int offset, int length) {
+ long[] data = new long[length];
+ for (int i = 0; i < length; i++) {
+ data[i] = value[i + offset];
+ }
+ mValue = data;
+ mComponentCount = length;
}
- public Rational getRational(int index) {
- return ((Rational[]) mValue)[index];
+ /**
+ * Sets the byte array as the value of this tag.
+ * This is equivalent to setValue(value, 0, value.length).
+ */
+ public void setValue(byte[] value) {
+ setValue(value, 0, value.length);
}
- public Rational getRational() {
- return ((Rational[]) mValue)[0];
+ public short getShort(int index) {
+ if (mValue instanceof long[]) {
+ return (short) (((long[]) mValue) [index]);
+ } else {
+ throw new RuntimeException("There is no numerical value in this tag");
+ }
}
- public int getBytes(byte[] buf) {
- return getBytes(buf, 0, buf.length);
+ public int getUnsignedShort(int index) {
+ if (mValue instanceof long[]) {
+ return (int) (((long[]) mValue) [index]);
+ } else {
+ throw new RuntimeException("There is no numerical value in this tag");
+ }
+ }
+
+ public int getInt(int index) {
+ if (mValue instanceof long[]) {
+ return (int) (((long[]) mValue) [index]);
+ } else {
+ throw new RuntimeException("There is no numerical value in this tag");
+ }
+ }
+
+ public long getUnsignedInt(int index) {
+ if (mValue instanceof long[]) {
+ return ((long[]) mValue) [index];
+ } else {
+ throw new RuntimeException("There is no numerical value in this tag");
+ }
+ }
+
+ public String getString() {
+ return (String) mValue;
}
- public int getBytes(byte[] buf, int offset, int length) {
- byte[] data = (byte[]) mValue;
- if (data.length < length + offset) {
- System.arraycopy(data, offset, buf, 0, data.length - offset);
- return data.length - offset;
+ public Rational getRational(int index) {
+ Object value = Array.get(mValue, index);
+ if (value instanceof Rational) {
+ return (Rational) value;
} else {
- System.arraycopy(data, offset, buf, 0, length);
- return length;
+ throw new RuntimeException("There is no Rational value in this tag");
+ }
+ }
+
+ public void getBytes(byte[] buf) {
+ getBytes(buf, 0, buf.length);
+ }
+
+ public void getBytes(byte[] buf, int offset, int length) {
+ if (!(mValue instanceof long[])) {
+ throw new RuntimeException("There is no byte value in this tag");
+ }
+ long[] data = (long[]) mValue;
+ for(int i = 0; i < length; i++) {
+ buf[offset + i] = (byte) data[i];
}
}
case ExifTag.TYPE_UNSIGNED_BYTE:
byte buf[] = new byte[getComponentCount()];
getBytes(buf);
- for(int i = 0; i < getComponentCount(); i++) {
+ for(int i = 0, n = getComponentCount(); i < n; i++) {
if(i != 0) sbuilder.append(" ");
sbuilder.append(String.format("%02x", buf[i]));
}
sbuilder.append(getString().trim());
break;
case ExifTag.TYPE_UNSIGNED_INT:
- for(int i = 0; i < getComponentCount(); i++) {
+ for(int i = 0, n = getComponentCount(); i < n; i++) {
if(i != 0) sbuilder.append(" ");
sbuilder.append(getUnsignedInt(i));
}
break;
case ExifTag.TYPE_RATIONAL:
case ExifTag.TYPE_UNSIGNED_RATIONAL:
- for(int i = 0; i < getComponentCount(); i++) {
+ for(int i = 0, n = getComponentCount(); i < n; i++) {
Rational r = getRational(i);
if(i != 0) sbuilder.append(" ");
sbuilder.append(r.getNominator()).append("/").append(r.getDenominator());
}
break;
case ExifTag.TYPE_UNSIGNED_SHORT:
- for(int i = 0; i < getComponentCount(); i++) {
+ for(int i = 0, n = getComponentCount(); i < n; i++) {
if(i != 0) sbuilder.append(" ");
sbuilder.append(getUnsignedShort(i));
}
break;
case ExifTag.TYPE_INT:
- for(int i = 0; i < getComponentCount(); i++) {
+ for(int i = 0, n = getComponentCount(); i < n; i++) {
if(i != 0) sbuilder.append(" ");
sbuilder.append(getInt(i));
}
}
return sbuilder.toString();
}
+
+ /**
+ * Returns true if the ID is one of the following: {@link TIFF_TAG#TAG_EXIF_IFD},
+ * {@link TIFF_TAG#TAG_GPS_IFD}, {@link TIFF_TAG#TAG_JPEG_INTERCHANGE_FORMAT},
+ * {@link TIFF_TAG#TAG_STRIP_OFFSETS}, {@link EXIF_TAG#TAG_INTEROPERABILITY_IFD}
+ */
+ public static boolean isOffsetTag(short tagId) {
+ return tagId == ExifTag.TIFF_TAG.TAG_EXIF_IFD
+ || tagId == ExifTag.TIFF_TAG.TAG_GPS_IFD
+ || tagId == ExifTag.TIFF_TAG.TAG_JPEG_INTERCHANGE_FORMAT
+ || tagId == ExifTag.TIFF_TAG.TAG_STRIP_OFFSETS
+ || tagId == ExifTag.EXIF_TAG.TAG_INTEROPERABILITY_IFD;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ExifTag) {
+ ExifTag tag = (ExifTag) obj;
+ boolean isArray = mValue != null && mValue.getClass().isArray();
+ if (mValue != null) {
+ if (mValue instanceof long[]) {
+ if (!(tag.mValue instanceof long[])) return false;
+ return Arrays.equals((long[]) mValue, (long[]) tag.mValue);
+ } else if (mValue instanceof Rational[]) {
+ if (!(tag.mValue instanceof Rational[])) return false;
+ return Arrays.equals((Rational[]) mValue, (Rational[]) tag.mValue);
+ } else {
+ return mValue.equals(tag.mValue);
+ }
+ } else {
+ return tag.mValue == null;
+ }
+ }
+ return false;
+ }
}
\ No newline at end of file
public void setTag(ExifTag tag) {
mExifTags.put(tag.getTagId(), tag);
}
+
+ /**
+ * Gets the tags count in the IFD.
+ */
+ public int getTagCount() {
+ return mExifTags.size();
+ }
+
/**
* Sets the offset of next IFD.
*/
int getOffsetToNextIfd() {
return mOffsetToNextIfd;
}
+
+ /**
+ * Returns true if all tags in this two IFDs are equal. Note that tags of IFDs offset or
+ * thumbnail offset will be ignored.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof IfdData) {
+ IfdData data = (IfdData) obj;
+ if (data.getId() == mIfdId && data.getTagCount() == getTagCount()) {
+ ExifTag[] tags = data.getAllTags(new ExifTag[0]);
+ for (ExifTag tag: tags) {
+ if (ExifTag.isOffsetTag(tag.getTagId())) continue;
+ ExifTag tag2 = mExifTags.get(tag.getTagId());
+ if (!tag.equals(tag2)) return false;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.exif;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class OrderedDataOutputStream extends FilterOutputStream {
+ private final ByteBuffer mByteBuffer = ByteBuffer.allocate(4);
+
+ public OrderedDataOutputStream(OutputStream out) {
+ super(out);
+ }
+
+ public void setByteOrder(ByteOrder order) {
+ mByteBuffer.order(order);
+ }
+
+ public void writeShort(short value) throws IOException {
+ mByteBuffer.rewind();
+ mByteBuffer.putShort(value);
+ out.write(mByteBuffer.array(), 0, 2);
+ }
+
+ public void writeInt(int value) throws IOException {
+ mByteBuffer.rewind();
+ mByteBuffer.putInt(value);
+ out.write(mByteBuffer.array());
+ }
+
+ public void writeRational(Rational rational) throws IOException {
+ writeInt((int) rational.getNominator());
+ writeInt((int) rational.getDenominator());
+ }
+}
public long getDenominator() {
return mDenominator;
}
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Rational) {
+ Rational data = (Rational) obj;
+ return mNominator == data.mNominator && mDenominator == data.mDenominator;
+ }
+ return false;
+ }
}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.exif;
+
+import java.io.Closeable;
+
+class Util {
+ public static boolean equals(Object a, Object b) {
+ return (a == b) || (a == null ? false : a.equals(b));
+ }
+
+ public static void closeSilently(Closeable c) {
+ if (c == null) return;
+ try {
+ c.close();
+ } catch (Throwable t) {
+ // do nothing
+ }
+ }
+}
private Future<?> mTask;
// wait the operation to finish when we want to stop it.
private boolean mWaitOnStop;
- private Intent mShareIntent;
private final AbstractGalleryActivity mActivity;
private final SelectionManager mSelectionManager;
Intent intent = getIntentBySingleSelectedPath(Intent.ACTION_ATTACH_DATA)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra("mimeType", intent.getType());
- Activity activity = (Activity) mActivity;
+ Activity activity = mActivity;
activity.startActivity(Intent.createChooser(
intent, activity.getString(R.string.set_as)));
return;
ArrayList<Path> ids = mSelectionManager.getSelected(false);
stopTaskAndDismissDialog();
- Activity activity = (Activity) mActivity;
+ Activity activity = mActivity;
mDialog = createProgressDialog(activity, title, ids.size());
if (showDialog) {
mDialog.show();
double latlng[] = new double[2];
item.getLatLong(latlng);
if (GalleryUtils.isValidLocation(latlng[0], latlng[1])) {
- GalleryUtils.showOnMap((Context) mActivity, latlng[0], latlng[1]);
+ GalleryUtils.showOnMap(mActivity, latlng[0], latlng[1]);
}
break;
}
private static final int ROTATE_FACTOR = 4;
private EdgeAnimation mAnimationLeft = new EdgeAnimation();
private EdgeAnimation mAnimationRight = new EdgeAnimation();
- private int mWidth, mHeight;
+ private int mWidth;
private float[] mMatrix = new float[16];
public void overScroll(float distance) {
public void setSize(int width, int height) {
mWidth = width;
- mHeight = height;
}
public float[] getTransform(Rect rect, float scrollX) {
import android.content.Context;
import android.graphics.Color;
import android.graphics.Matrix;
-import android.graphics.Point;
import android.graphics.Rect;
import android.os.Build;
import android.os.Message;
private Listener mListener;
private Model mModel;
- private StringTexture mLoadingText;
private StringTexture mNoThumbnailText;
private TileImageView mTileView;
private EdgeView mEdgeView;
private SynchronizedHandler mHandler;
- private Point mImageCenter = new Point();
private boolean mCancelExtraScalingPending;
private boolean mFilmMode = false;
private int mDisplayRotation = 0;
hideUndoBar();
}
});
- mLoadingText = StringTexture.newInstance(
- context.getString(R.string.loading),
- DEFAULT_TEXT_SIZE, Color.WHITE);
mNoThumbnailText = StringTexture.newInstance(
context.getString(R.string.no_thumbnail),
DEFAULT_TEXT_SIZE, Color.WHITE);
mPositionController = new PositionController(context,
new PositionController.Listener() {
- public void invalidate() {
- PhotoView.this.invalidate();
- }
- public boolean isHoldingDown() {
- return (mHolding & HOLD_TOUCH_DOWN) != 0;
- }
- public boolean isHoldingDelete() {
- return (mHolding & HOLD_DELETE) != 0;
- }
- public void onPull(int offset, int direction) {
- mEdgeView.onPull(offset, direction);
- }
- public void onRelease() {
- mEdgeView.onRelease();
- }
- public void onAbsorb(int velocity, int direction) {
- mEdgeView.onAbsorb(velocity, direction);
- }
- });
+
+ @Override
+ public void invalidate() {
+ PhotoView.this.invalidate();
+ }
+
+ @Override
+ public boolean isHoldingDown() {
+ return (mHolding & HOLD_TOUCH_DOWN) != 0;
+ }
+
+ @Override
+ public boolean isHoldingDelete() {
+ return (mHolding & HOLD_DELETE) != 0;
+ }
+
+ @Override
+ public void onPull(int offset, int direction) {
+ mEdgeView.onPull(offset, direction);
+ }
+
+ @Override
+ public void onRelease() {
+ mEdgeView.onRelease();
+ }
+
+ @Override
+ public void onAbsorb(int velocity, int direction) {
+ mEdgeView.onAbsorb(velocity, direction);
+ }
+ });
mVideoPlayIcon = new ResourceTexture(context, R.drawable.ic_control_play);
for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; i++) {
if (i == 0) {
default: throw new AssertionError(message.what);
}
}
- };
+ }
////////////////////////////////////////////////////////////////////////////
// Data/Image change notifications
private int mLoadingState = Model.LOADING_INIT;
private Size mSize = new Size();
private boolean mWasCameraCenter;
- public void FullPicture(TileImageView tileView) {
- mTileView = tileView;
- }
@Override
public void reload() {
import com.android.gallery3d.app.PhotoPage;
import com.android.gallery3d.common.OverScroller;
import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.ui.PhotoView.Size;
import com.android.gallery3d.util.GalleryUtils;
import com.android.gallery3d.util.RangeArray;
import com.android.gallery3d.util.RangeIntArray;
-import com.android.gallery3d.ui.PhotoView.Size;
class PositionController {
private static final String TAG = "PositionController";
//dumpState();
}
+ @SuppressWarnings("unused")
private void dumpState() {
for (int i = -BOX_MAX; i < BOX_MAX; i++) {
Log.d(TAG, "Gap " + i + ": " + mGaps.get(i).mCurrentGap);
g.mAnimationStartTime = NO_ANIMATION;
}
+ @SuppressWarnings("unused")
private void debugMoveBox(int fromIndex[]) {
StringBuilder s = new StringBuilder("moveBox:");
for (int i = 0; i < fromIndex.length; i++) {
public static float[] intColorToFloatARGBArray(int from) {
return new float[] {
- (float) Color.alpha(from) / 255f,
- (float) Color.red(from) / 255f,
- (float) Color.green(from) / 255f,
- (float) Color.blue(from) / 255f
+ Color.alpha(from) / 255f,
+ Color.red(from) / 255f,
+ Color.green(from) / 255f,
+ Color.blue(from) / 255f
};
}
--- /dev/null
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.exif;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.test.InstrumentationTestCase;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class ExifOutputStreamTest extends InstrumentationTestCase {
+
+ private final int mImageResourceId;
+
+ public ExifOutputStreamTest(int imageResourceId, int xmlReourceId) {
+ mImageResourceId = imageResourceId;
+ }
+
+ public void testExifOutputStream() throws IOException, ExifInvalidFormatException {
+ File file = File.createTempFile("exif_test", ".jpg");
+ InputStream imageInputStream = null;
+ InputStream exifInputStream = null;
+ FileInputStream reDecodeInputStream = null;
+ FileInputStream reParseInputStream = null;
+ try {
+ // Read the image
+ imageInputStream = getInstrumentation()
+ .getContext().getResources().openRawResource(mImageResourceId);
+ Bitmap bmp = BitmapFactory.decodeStream(imageInputStream);
+
+ // Read exif data
+ exifInputStream = getInstrumentation()
+ .getContext().getResources().openRawResource(mImageResourceId);
+ ExifData exifData = new ExifReader().read(exifInputStream);
+
+ // Encode the image with the exif data
+ FileOutputStream outputStream = new FileOutputStream(file);
+ ExifOutputStream exifOutputStream = new ExifOutputStream(outputStream);
+ exifOutputStream.setExifData(exifData);
+ bmp.compress(Bitmap.CompressFormat.JPEG, 100, exifOutputStream);
+ exifOutputStream.close();
+
+ // Re-decode the temp file and check the data.
+ reDecodeInputStream = new FileInputStream(file);
+ Bitmap decodedBmp = BitmapFactory.decodeStream(reDecodeInputStream);
+ assertNotNull(decodedBmp);
+
+ // Re-parse the temp file the check EXIF tag
+ reParseInputStream = new FileInputStream(file);
+ ExifData reExifData = new ExifReader().read(reParseInputStream);
+ assertEquals(exifData, reExifData);
+ } finally {
+ Util.closeSilently(imageInputStream);
+ Util.closeSilently(exifInputStream);
+ Util.closeSilently(reDecodeInputStream);
+ Util.closeSilently(reParseInputStream);
+ }
+ }
+}
\ No newline at end of file
case ExifParser.EVENT_NEW_TAG:
ExifTag tag = parser.getTag();
if (tag.getTagId() == ExifTag.TIFF_TAG.TAG_COMPRESSION) {
- if (tag.getUnsignedShort() == ExifTag.TIFF_TAG.COMPRESSION_JPEG) {
+ if (tag.getUnsignedShort(0) == ExifTag.TIFF_TAG.COMPRESSION_JPEG) {
mIsContainCompressedImage = true;
}
}
private void checkThumbnail(ExifData exifData) {
IfdData ifd1 = exifData.getIfdData(IfdId.TYPE_IFD_1);
if (ifd1 != null) {
- if (ifd1.getTag(ExifTag.TIFF_TAG.TAG_COMPRESSION).getUnsignedShort() ==
+ if (ifd1.getTag(ExifTag.TIFF_TAG.TAG_COMPRESSION).getUnsignedShort(0) ==
ExifTag.TIFF_TAG.COMPRESSION_JPEG) {
assertTrue(exifData.hasCompressedThumbnail());
byte[] thumbnail = exifData.getCompressedThumbnail();
int planarType = ExifTag.TIFF_TAG.PLANAR_CONFIGURATION_CHUNKY;
ExifTag planarTag = ifd1.getTag(ExifTag.TIFF_TAG.TAG_PLANAR_CONFIGURATION);
if (planarTag != null) {
- planarType = planarTag.getUnsignedShort();
+ planarType = planarTag.getUnsignedShort(0);
}
ExifTag heightTag = ifd1.getTag(ExifTag.TIFF_TAG.TAG_IMAGE_HEIGHT);
assertTrue(stripCount == (imageLength + rowsPerStrip - 1) / rowsPerStrip);
} else {
ExifTag samplePerPixelTag = ifd1.getTag(ExifTag.TIFF_TAG.TAG_SAMPLES_PER_PIXEL);
- int samplePerPixel = samplePerPixelTag.getUnsignedShort();
+ int samplePerPixel = samplePerPixelTag.getUnsignedShort(0);
assertTrue(stripCount ==
(imageLength + rowsPerStrip - 1) / rowsPerStrip * samplePerPixel);
}
private int getUnsignedIntOrShort(ExifTag tag) {
if (tag.getDataType() == ExifTag.TYPE_UNSIGNED_SHORT) {
- return tag.getUnsignedShort();
+ return tag.getUnsignedShort(0);
} else {
- return (int) tag.getUnsignedInt();
+ return (int) tag.getUnsignedInt(0);
}
}
TestSuite suite = new InstrumentationTestSuite(this);
getAllTestFromTestCase(ExifParserTest.class, suite);
getAllTestFromTestCase(ExifReaderTest.class, suite);
+ getAllTestFromTestCase(ExifOutputStreamTest.class, suite);
return suite;
}