private void startPlayVideoActivity() {
   IImage image = mAllImages.getImageAt(mCurrentPosition);
   Intent intent = new Intent(Intent.ACTION_VIEW, image.fullSizeImageUri());
   try {
     startActivity(intent);
   } catch (android.content.ActivityNotFoundException ex) {
     Log.e(TAG, "Couldn't view video " + image.fullSizeImageUri(), ex);
   }
 }
  private static ExifInterface getExif(IImage image) {
    if (!JPEG_MIME_TYPE.equals(image.getMimeType())) {
      return null;
    }

    try {
      return new ExifInterface(image.getDataPath());
    } catch (IOException ex) {
      Log.e(TAG, "cannot read exif", ex);
      return null;
    }
  }
 private void startShareMediaActivity(IImage image) {
   boolean isVideo = image instanceof VideoObject;
   Intent intent = new Intent();
   intent.setAction(Intent.ACTION_SEND);
   intent.setType(image.getMimeType());
   intent.putExtra(Intent.EXTRA_STREAM, image.fullSizeImageUri());
   try {
     startActivity(
         Intent.createChooser(intent, getText(isVideo ? R.string.sendVideo : R.string.sendImage)));
   } catch (android.content.ActivityNotFoundException ex) {
     Toast.makeText(
             this,
             isVideo ? R.string.no_way_to_share_image : R.string.no_way_to_share_video,
             Toast.LENGTH_SHORT)
         .show();
   }
 }
 public static long getImageFileSize(IImage image) {
   java.io.InputStream data = image.fullSizeImageData();
   if (data == null) return -1;
   try {
     return data.available();
   } catch (java.io.IOException ex) {
     return -1;
   } finally {
     closeSilently(data);
   }
 }
 public void onClick(View v) {
   switch (v.getId()) {
     case R.id.discard:
       MenuHelper.deletePhoto(this, mDeletePhotoRunnable);
       break;
     case R.id.play:
       startPlayVideoActivity();
       break;
     case R.id.share:
       {
         IImage image = mAllImages.getImageAt(mCurrentPosition);
         if (!MenuHelper.isWhiteListUri(image.fullSizeImageUri())) {
           return;
         }
         startShareMediaActivity(image);
         break;
       }
     case R.id.setas:
       {
         IImage image = mAllImages.getImageAt(mCurrentPosition);
         Intent intent = Util.createSetAsIntent(image);
         try {
           startActivity(Intent.createChooser(intent, getText(R.string.setImage)));
         } catch (android.content.ActivityNotFoundException ex) {
           Toast.makeText(this, R.string.no_way_to_share_video, Toast.LENGTH_SHORT).show();
         }
         break;
       }
     case R.id.next_image:
       moveNextOrPrevious(1);
       break;
     case R.id.prev_image:
       moveNextOrPrevious(-1);
       break;
   }
 }
 private Uri getCurrentUri() {
   if (mAllImages.getCount() == 0) return null;
   IImage image = mAllImages.getImageAt(mCurrentPosition);
   if (image == null) return null;
   return image.fullSizeImageUri();
 }
  void setImage(int pos, boolean showControls) {
    mCurrentPosition = pos;

    Bitmap b = mCache.getBitmap(pos);
    if (b != null) {
      IImage image = mAllImages.getImageAt(pos);
      mImageView.setImageRotateBitmapResetBase(
          new RotateBitmap(b, image.getDegreesRotated()), true);
      updateZoomButtonsEnabled();
    }

    ImageGetterCallback cb =
        new ImageGetterCallback() {
          public void completed() {}

          public boolean wantsThumbnail(int pos, int offset) {
            return !mCache.hasBitmap(pos + offset);
          }

          public boolean wantsFullImage(int pos, int offset) {
            return offset == 0;
          }

          public int fullImageSizeToUse(int pos, int offset) {
            // this number should be bigger so that we can zoom.  we may
            // need to get fancier and read in the fuller size image as the
            // user starts to zoom.
            // Originally the value is set to 480 in order to avoid OOM.
            // Now we set it to 2048 because of using
            // native memory allocation for Bitmaps.
            final int imageViewSize = 2048;
            return imageViewSize;
          }

          public int[] loadOrder() {
            return sOrderAdjacents;
          }

          public void imageLoaded(int pos, int offset, RotateBitmap bitmap, boolean isThumb) {
            // shouldn't get here after onPause()

            // We may get a result from a previous request. Ignore it.
            if (pos != mCurrentPosition) {
              bitmap.recycle();
              return;
            }

            if (isThumb) {
              mCache.put(pos + offset, bitmap.getBitmap());
            }
            if (offset == 0) {
              // isThumb: We always load thumb bitmap first, so we will
              // reset the supp matrix for then thumb bitmap, and keep
              // the supp matrix when the full bitmap is loaded.
              mImageView.setImageRotateBitmapResetBase(bitmap, isThumb);
              updateZoomButtonsEnabled();
            }
          }
        };

    // Could be null if we're stopping a slide show in the course of pausing
    if (mGetter != null) {
      mGetter.setPosition(pos, cb, mAllImages, mHandler);
    }
    updateActionIcons();
    if (showControls) showOnScreenControls();
    scheduleDismissOnScreenControls();
  }
  @Override
  public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (mViewImage.mPaused) return false;

    // Don't respond to arrow keys if trackball scrolling is not enabled
    if (!mEnableTrackballScroll) {
      if ((keyCode >= KeyEvent.KEYCODE_DPAD_UP) && (keyCode <= KeyEvent.KEYCODE_DPAD_RIGHT)) {
        return super.onKeyDown(keyCode, event);
      }
    }

    int current = mViewImage.mCurrentPosition;

    int nextImagePos = -2; // default no next image
    try {
      switch (keyCode) {
        case KeyEvent.KEYCODE_DPAD_CENTER:
          {
            if (mViewImage.isPickIntent()) {
              IImage img = mViewImage.mAllImages.getImageAt(mViewImage.mCurrentPosition);
              mViewImage.setResult(
                  ViewImage.RESULT_OK, new Intent().setData(img.fullSizeImageUri()));
              mViewImage.finish();
            }
            break;
          }
        case KeyEvent.KEYCODE_DPAD_LEFT:
          {
            if (getScale() <= 1F && event.getEventTime() >= mNextChangePositionTime) {
              nextImagePos = current - 1;
              mNextChangePositionTime = event.getEventTime() + 500;
            } else {
              panBy(PAN_RATE, 0);
              center(true, false);
            }
            return true;
          }
        case KeyEvent.KEYCODE_DPAD_RIGHT:
          {
            if (getScale() <= 1F && event.getEventTime() >= mNextChangePositionTime) {
              nextImagePos = current + 1;
              mNextChangePositionTime = event.getEventTime() + 500;
            } else {
              panBy(-PAN_RATE, 0);
              center(true, false);
            }
            return true;
          }
        case KeyEvent.KEYCODE_DPAD_UP:
          {
            panBy(0, PAN_RATE);
            center(false, true);
            return true;
          }
        case KeyEvent.KEYCODE_DPAD_DOWN:
          {
            panBy(0, -PAN_RATE);
            center(false, true);
            return true;
          }
        case KeyEvent.KEYCODE_DEL:
          MenuHelper.deletePhoto(mViewImage, mViewImage.mDeletePhotoRunnable);
          break;
      }
    } finally {
      if (nextImagePos >= 0 && nextImagePos < mViewImage.mAllImages.getCount()) {
        synchronized (mViewImage) {
          mViewImage.setMode(ViewImage.MODE_NORMAL);
          mViewImage.setImage(nextImagePos, true);
        }
      } else if (nextImagePos != -2) {
        center(true, true);
      }
    }

    return super.onKeyDown(keyCode, event);
  }
  @Override
  public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    mContentResolver = getContentResolver();

    setContentView(getContentViewId());

    mImageView = getCropImageView();

    // Work-around for devices incapable of using hardware-accelerated clipPath.
    // (android.view.GLES20Canvas.clipPath)
    //
    // See also:
    // - https://code.google.com/p/android/issues/detail?id=20474
    // - https://github.com/lvillani/android-cropimage/issues/20
    //
    if (Build.VERSION.SDK_INT > 10
        && Build.VERSION.SDK_INT < 16) { // >= Gingerbread && < Jelly Bean
      mImageView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }

    Intent intent = getIntent();
    Bundle extras = intent.getExtras();

    if (extras != null) {
      if (extras.getBoolean("circleCrop", false)) {
        mCircleCrop = true;
        mAspectX = 1;
        mAspectY = 1;
        mOutputFormat = Bitmap.CompressFormat.PNG;
      }
      mSaveUri = (Uri) extras.getParcelable(MediaStore.EXTRA_OUTPUT);
      if (mSaveUri != null) {
        String outputFormatString = extras.getString("outputFormat");
        if (outputFormatString != null) {
          mOutputFormat = Bitmap.CompressFormat.valueOf(outputFormatString);
        }
        mOutputQuality = extras.getInt("outputQuality", 100);
      } else {
        mSetWallpaper = extras.getBoolean("setWallpaper");
      }
      mBitmap = (Bitmap) extras.getParcelable("data");
      mAspectX = extras.getInt("aspectX");
      mAspectY = extras.getInt("aspectY");
      mOutputX = extras.getInt("outputX");
      mOutputY = extras.getInt("outputY");
      mOutlineColor = extras.getInt("outlineColor", HighlightView.DEFAULT_OUTLINE_COLOR);
      mOutlineCircleColor =
          extras.getInt("outlineCircleColor", HighlightView.DEFAULT_OUTLINE_CIRCLE_COLOR);
      mScale = extras.getBoolean("scale", true);
      mScaleUp = extras.getBoolean("scaleUpIfNeeded", true);
      mDoFaceDetection =
          extras.containsKey("noFaceDetection") ? !extras.getBoolean("noFaceDetection") : true;
    }

    if (mBitmap == null) {
      Uri target = intent.getData();
      mAllImages =
          ImageManager.makeImageList(mContentResolver, target, ImageManager.SORT_ASCENDING);
      mImage = mAllImages.getImageForUri(target);
      if (mImage != null) {
        // Don't read in really large bitmaps. Use the (big) thumbnail
        // instead.
        // TODO when saving the resulting bitmap use the
        // decode/crop/encode api so we don't lose any resolution.
        mBitmap = mImage.thumbBitmap(IImage.ROTATE_AS_NEEDED);
      }
    }

    if (mBitmap == null) {
      finish();
      return;
    }

    // Make UI fullscreen.
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

    Button discardButton = getDiscardButton();
    if (discardButton != null) {
      discardButton.setOnClickListener(
          new View.OnClickListener() {
            public void onClick(View v) {
              setResult(RESULT_CANCELED);
              finish();
            }
          });
    }

    Button saveButton = getSaveButton();
    if (saveButton != null) {
      saveButton.setOnClickListener(
          new View.OnClickListener() {
            public void onClick(View v) {
              onSaveClicked();
            }
          });
    }

    startFaceDetection();
  }
  private void saveOutput(Bitmap croppedImage) {
    if (mSaveUri != null) {
      OutputStream outputStream = null;
      try {
        outputStream = mContentResolver.openOutputStream(mSaveUri);
        if (outputStream != null) {
          croppedImage.compress(mOutputFormat, mOutputQuality, outputStream);
        }
      } catch (IOException ex) {
        // TODO: report error to caller
        Log.e(TAG, "Cannot open file: " + mSaveUri, ex);
      } finally {
        Util.closeSilently(outputStream);
      }
      Bundle extras = new Bundle();
      setResult(RESULT_OK, new Intent(mSaveUri.toString()).putExtras(extras));
    } else if (mSetWallpaper) {
      try {
        WallpaperManager.getInstance(this).setBitmap(croppedImage);
        setResult(RESULT_OK);
      } catch (IOException e) {
        Log.e(TAG, "Failed to set wallpaper.", e);
        setResult(RESULT_CANCELED);
      }
    } else {
      Bundle extras = new Bundle();
      extras.putString("rect", mCrop.getCropRect().toString());

      File oldPath = new File(mImage.getDataPath());
      File directory = new File(oldPath.getParent());

      int x = 0;
      String fileName = oldPath.getName();
      fileName = fileName.substring(0, fileName.lastIndexOf("."));

      // Try file-1.jpg, file-2.jpg, ... until we find a filename which
      // does not exist yet.
      while (true) {
        x += 1;
        String candidate = directory.toString() + "/" + fileName + "-" + x + ".jpg";
        boolean exists = (new File(candidate)).exists();
        if (!exists) {
          break;
        }
      }

      try {
        int[] degree = new int[1];
        Uri newUri =
            ImageManager.addImage(
                mContentResolver,
                mImage.getTitle(),
                mImage.getDateTaken(),
                null, // TODO this null is going to cause us to lose
                // the location (gps).
                directory.toString(),
                fileName + "-" + x + ".jpg",
                croppedImage,
                null,
                degree);

        setResult(RESULT_OK, new Intent().setAction(newUri.toString()).putExtras(extras));
      } catch (Exception ex) {
        // basically ignore this or put up
        // some ui saying we failed
        Log.e(TAG, "store image fail, continue anyway", ex);
      }
    }

    final Bitmap b = croppedImage;
    mHandler.post(
        new Runnable() {
          public void run() {
            mImageView.clear();
            b.recycle();
          }
        });

    finish();
  }