Skip to content

Commit

Permalink
Copied PupilAndIrisDetector to Android project
Browse files Browse the repository at this point in the history
  • Loading branch information
jeisfeld committed Feb 26, 2016
1 parent 0da75bd commit b515d9e
Show file tree
Hide file tree
Showing 9 changed files with 1,255 additions and 250 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import de.jeisfeld.augendiagnoselib.util.imagefile.JpegMetadata;
import de.jeisfeld.augendiagnoselib.util.imagefile.JpegSynchronizationUtil;
import de.jeisfeld.augendiagnoselib.util.imagefile.MediaStoreUtil;
import de.jeisfeld.augendiagnoselib.util.imagefile.PupilAndIrisDetector;

import static de.jeisfeld.augendiagnoselib.activities.CameraActivity.Action.CANCEL_AND_VIEW_IMAGES;
import static de.jeisfeld.augendiagnoselib.activities.CameraActivity.Action.CHECK_PHOTO;
Expand Down Expand Up @@ -412,6 +413,7 @@ public void onClick(final View v) {

if (mLeftEyeFile == null) {
setAction(TAKE_PHOTO, LEFT);
PupilAndIrisDetector.determineAndStoreIrisPosition(mRightEyeFile.getAbsolutePath());
}
else {
setAction(FINISH_CAMERA, null);
Expand All @@ -428,6 +430,7 @@ public void onClick(final View v) {

if (mRightEyeFile == null) {
setAction(TAKE_PHOTO, RIGHT);
PupilAndIrisDetector.determineAndStoreIrisPosition(mLeftEyeFile.getAbsolutePath());
}
else {
setAction(FINISH_CAMERA, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import de.jeisfeld.augendiagnoselib.util.imagefile.ImageUtil;
import de.jeisfeld.augendiagnoselib.util.imagefile.JpegMetadataUtil;
import de.jeisfeld.augendiagnoselib.util.imagefile.MediaStoreUtil;
import de.jeisfeld.augendiagnoselib.util.imagefile.PupilAndIrisDetector;

/**
* Activity to display a pair of new eye photos, choose a name and a date for them, and shift them into the
Expand Down Expand Up @@ -432,6 +433,9 @@ private void updateImages(final boolean updateDate) {
mEditDate.setText(DateUtil.getDisplayDate(mPictureDate));
mEditDate.invalidate();
}

PupilAndIrisDetector.determineAndStoreIrisPosition(mPhotoRight.getAbsolutePath());
PupilAndIrisDetector.determineAndStoreIrisPosition(mPhotoLeft.getAbsolutePath());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

import de.jeisfeld.augendiagnoselib.Application;
import de.jeisfeld.augendiagnoselib.R;
import de.jeisfeld.augendiagnoselib.fragments.DisplayImageFragment.OverlayStatus;
import de.jeisfeld.augendiagnoselib.util.PreferenceUtil;
import de.jeisfeld.augendiagnoselib.util.imagefile.EyePhoto;
import de.jeisfeld.augendiagnoselib.util.imagefile.EyePhoto.RightLeft;
Expand Down Expand Up @@ -261,7 +262,7 @@ public OverlayPinchImageView(final Context context) {
* Standard constructor to be implemented for all views.
*
* @param context The Context the view is running in, through which it can access the current theme, resources, etc.
* @param attrs The attributes of the XML tag that is inflating the view.
* @param attrs The attributes of the XML tag that is inflating the view.
* @see android.view.View#View(Context, AttributeSet)
*/
public OverlayPinchImageView(final Context context, final AttributeSet attrs) {
Expand All @@ -271,10 +272,10 @@ public OverlayPinchImageView(final Context context, final AttributeSet attrs) {
/**
* Standard constructor to be implemented for all views.
*
* @param context The Context the view is running in, through which it can access the current theme, resources, etc.
* @param attrs The attributes of the XML tag that is inflating the view.
* @param context The Context the view is running in, through which it can access the current theme, resources, etc.
* @param attrs The attributes of the XML tag that is inflating the view.
* @param defStyle An attribute in the current theme that contains a reference to a style resource that supplies default
* values for the view. Can be 0 to not look for defaults.
* values for the view. Can be 0 to not look for defaults.
* @see android.view.View#View(Context, AttributeSet, int)
*/
public OverlayPinchImageView(final Context context, final AttributeSet attrs, final int defStyle) {
Expand All @@ -293,8 +294,8 @@ public final EyePhoto getEyePhoto() {
/**
* Fill with an image, initializing from metadata.
*
* @param pathName The pathname of the image
* @param activity The triggering activity (required for bitmap caching)
* @param pathName The pathname of the image
* @param activity The triggering activity (required for bitmap caching)
* @param cacheIndex A unique index of the view in the activity
*/
@Override
Expand Down Expand Up @@ -336,7 +337,8 @@ public void run() {
mOverlayScaleFactor = mMetadata.getOverlayScaleFactor()
* Math.max(mBitmap.getHeight(), mBitmap.getWidth()) / OVERLAY_SIZE;

boolean shouldBeLocked = !mMetadata.hasFlag(JpegMetadata.FLAG_OVERLAY_SET_BY_CAMERA_ACTIVITY);
boolean shouldBeLocked = !mMetadata.hasFlag(JpegMetadata.FLAG_OVERLAY_SET_BY_CAMERA_ACTIVITY)
&& !mMetadata.hasFlag(JpegMetadata.FLAG_OVERLAY_POSITION_DETERMINED_AUTOMATICALLY);
lockOverlay(shouldBeLocked, false);
if (mGuiElementUpdater != null) {
mGuiElementUpdater.setLockChecked(shouldBeLocked);
Expand Down Expand Up @@ -405,8 +407,9 @@ public void run() {
refresh(HIGH);
showFullResolutionSnapshot(true);
// Update lock status - required in the case that orientation change happened while loading image.
if (mMetadata != null && mMetadata.hasOverlayPosition() && mGuiElementUpdater != null
&& !mMetadata.hasFlag(JpegMetadata.FLAG_OVERLAY_SET_BY_CAMERA_ACTIVITY)) {
if (mMetadata != null && mMetadata.hasOverlayPosition() && mGuiElementUpdater != null // BOOLEAN_EXPRESSION_COMPLEXITY
&& !mMetadata.hasFlag(JpegMetadata.FLAG_OVERLAY_SET_BY_CAMERA_ACTIVITY)
&& !mMetadata.hasFlag(JpegMetadata.FLAG_OVERLAY_POSITION_DETERMINED_AUTOMATICALLY)) {
mGuiElementUpdater.setLockChecked(true);
}
}
Expand Down Expand Up @@ -564,7 +567,7 @@ private List<Integer> getOverlayPositions() {
* Get information if the view can handle overlays.
*
* @return true if the view can handle overlays. This is possible only if the right/left position of the eye photo
* is defined.
* is defined.
*/
public final boolean canHandleOverlays() {
return mEyePhoto != null && mEyePhoto.getRightLeft() != null;
Expand All @@ -573,7 +576,7 @@ public final boolean canHandleOverlays() {
/**
* Trigger one overlay either for activation or for deactivation.
*
* @param position number of the overlay
* @param position number of the overlay
* @param pinchMode the way in which pinching should be done. ALL indicates that the overlay should not be shown.
*/
public final void triggerOverlay(final int position, final PinchMode pinchMode) {
Expand All @@ -591,7 +594,7 @@ public final void triggerOverlay(final int position, final PinchMode pinchMode)
/**
* Switch the lock status of the overlays.
*
* @param lock the target lock status
* @param lock the target lock status
* @param store a flag indicating if the lock status should be stored.
*/
public final void lockOverlay(final boolean lock, final boolean store) {
Expand Down Expand Up @@ -619,6 +622,58 @@ public final void lockOverlay(final boolean lock, final boolean store) {
updatePinchMode();
}

/**
* Change the positioning of the image dependent on the overlay setup phase.
*
* @param overlayStatus The overlay status.
* @param circleRadius The relative circle radius (compared to min view dimension)
*/
public final void updatePosition(final OverlayStatus overlayStatus, final float circleRadius) {
switch (overlayStatus) {
case GUIDE_IRIS:
if (!mMetadata.hasOverlayPosition()) {
return;
}
mOverlayX = mMetadata.getXCenter();
mOverlayY = mMetadata.getYCenter();
mOverlayScaleFactor = mMetadata.getOverlayScaleFactor() * Math.max(mBitmap.getHeight(), mBitmap.getWidth()) / OVERLAY_SIZE;

mPosX = mOverlayX;
mPosY = mOverlayY;

float bitmapPixelDiameter = mOverlayScaleFactor * OVERLAY_SIZE * OVERLAY_CIRCLE_RATIO;
mScaleFactor = Math.min(getWidth(), getHeight()) * 2 * circleRadius / bitmapPixelDiameter;
mLastScaleFactor = mScaleFactor;
showNormalResolution();
refresh();
break;
case GUIDE_PUPIL:
if (mMetadata.getPupilSize() == null || mMetadata.getPupilSize() == 0) {
return;
}
mPupilOverlayX = mMetadata.getPupilXOffset();
mPupilOverlayY = mMetadata.getPupilYOffset();
mPupilOverlayScaleFactor = mMetadata.getPupilSize();

float overlaySizeOnBitmap = OVERLAY_CIRCLE_RATIO * mMetadata.getOverlayScaleFactor() * Math.max(mBitmap.getHeight(), mBitmap.getWidth());
mPosX = mPupilOverlayX * overlaySizeOnBitmap / mBitmap.getWidth() + mOverlayX;
mPosY = mPupilOverlayY * overlaySizeOnBitmap / mBitmap.getHeight() + mOverlayY;

float bitmapPixelDiameter2 = mPupilOverlayScaleFactor * overlaySizeOnBitmap;
mScaleFactor = Math.min(getWidth(), getHeight()) * 2 * circleRadius / bitmapPixelDiameter2;
mLastScaleFactor = mScaleFactor;
showNormalResolution();
refresh();
break;
case ALLOWED:
mInitialized = false;
doInitialScaling();
break;
default:
break;
}
}

/**
* Set the overlay position, so that it matches a centered circle.
*
Expand All @@ -640,6 +695,7 @@ public final void storePupilPosition() {
mMetadata.setPupilSize(mPupilOverlayScaleFactor);
mMetadata.setPupilXOffset(mPupilOverlayX);
mMetadata.setPupilYOffset(mPupilOverlayY);
mMetadata.removeFlag(JpegMetadata.FLAG_OVERLAY_POSITION_DETERMINED_AUTOMATICALLY);

mEyePhoto.storeImageMetadata(mMetadata);
resetOverlayCache();
Expand Down Expand Up @@ -799,17 +855,17 @@ private Drawable getOverlayDrawable(final int position) {
* Create a drawable from a black image drawable, having a changed colour.
*
* @param sourceDrawable The black image drawable
* @param color The target color
* @param origPupilSize The pupil size (relative to iris) in the original overlay bitmap.
* @param destPupilSize The pupil size (relative to iris) in the target overlay bitmap.
* @param pupilOffsetX The relative x offset of the pupil center
* @param pupilOffsetY The relative y offset of the pupil center
* @param color The target color
* @param origPupilSize The pupil size (relative to iris) in the original overlay bitmap.
* @param destPupilSize The pupil size (relative to iris) in the target overlay bitmap.
* @param pupilOffsetX The relative x offset of the pupil center
* @param pupilOffsetY The relative y offset of the pupil center
* @return The modified drawable, with the intended color.
*/
@NonNull
private Drawable getModifiedDrawable(@NonNull final Drawable sourceDrawable, @Nullable final Integer color,
final float origPupilSize, @Nullable final Float destPupilSize,
final Float pupilOffsetX, final Float pupilOffsetY) {
final float origPupilSize, @Nullable final Float destPupilSize,
final Float pupilOffsetX, final Float pupilOffsetY) {
Bitmap bitmap = ((BitmapDrawable) sourceDrawable).getBitmap();
Bitmap colouredBitmap = color == null ? bitmap : ImageUtil.changeBitmapColor(bitmap, color);

Expand Down Expand Up @@ -1138,8 +1194,8 @@ protected final void finishPointerMove(final MotionEvent ev) {
/**
* Update contrast and brightness of a bitmap.
*
* @param bmp input bitmap
* @param contrast 0..infinity - 1 is default
* @param bmp input bitmap
* @param contrast 0..infinity - 1 is default
* @param brightness -1..1 - 0 is default
* @return new bitmap
*/
Expand Down Expand Up @@ -1674,7 +1730,7 @@ private void setBitmapFullResolution(final Bitmap bitmapFullResolution) {
/**
* Get the retainFragment - search it by the index. If not found, create a new one.
*
* @param fm The fragment manager handling this fragment.
* @param fm The fragment manager handling this fragment.
* @param index The index of the view (required in case of multiple PinchImageViews to be retained).
* @return the retainFragment.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import de.jeisfeld.augendiagnoselib.util.SystemUtil;
import de.jeisfeld.augendiagnoselib.util.imagefile.EyePhoto.RightLeft;
import de.jeisfeld.augendiagnoselib.util.imagefile.JpegMetadataUtil;
import de.jeisfeld.augendiagnoselib.util.imagefile.PupilAndIrisDetector;

/**
* Variant of DisplayOneFragment that includes overlay handling.
Expand Down Expand Up @@ -598,6 +599,10 @@ private void drawOverlayCircle() {
ImageView overlayView = (ImageView) getView().findViewById(R.id.circleOverlay);
TextView textViewGuide = (TextView) getView().findViewById(R.id.textViewGuide);

mImageView.updatePosition(mOverlayStatus, mOverlayStatus == OverlayStatus.GUIDE_IRIS
? (float) CIRCLE_RADIUS_IRIS / CIRCLE_BITMAP_SIZE
: (float) CIRCLE_RADIUS_PUPIL / CIRCLE_BITMAP_SIZE);

if (mOverlayStatus != OverlayStatus.GUIDE_IRIS && mOverlayStatus != OverlayStatus.GUIDE_PUPIL) {
overlayView.setVisibility(View.GONE);
textViewGuide.setVisibility(View.GONE);
Expand Down Expand Up @@ -1074,6 +1079,8 @@ public final void initializeImages() {
}
else {
mImageView.setImage(mFile, getActivity(), mImageIndex);

PupilAndIrisDetector.determineAndStoreIrisPosition(mFile);
}

if (mImageView.getEyePhoto().getRightLeft() == null && mRightLeft != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,14 +217,19 @@ public static boolean deleteFile(@NonNull final File file) {
*/
public static boolean moveFile(@NonNull final File source, @NonNull final File target) {
// First try the normal rename.
if (source.renameTo(target)) {
return true;
boolean success = source.renameTo(target);

if (!success) {
success = copyFile(source, target);
if (success) {
success = deleteFile(source);
}
}

boolean success = copyFile(source, target);
if (success) {
success = deleteFile(source);
PupilAndIrisDetector.notifyFileRename(source.getAbsolutePath(), target.getAbsolutePath());
}

return success;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,27 +217,39 @@ public static Bitmap getImageBitmap(@NonNull final byte[] data, final int maxSiz
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = getBitmapFactor(data, maxSize);
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
bitmap = resizeBitmap(bitmap, maxSize, false);
}

if (bitmap.getWidth() == 0 || bitmap.getHeight() == 0) {
return bitmap;
}
return bitmap;
}

if (bitmap.getWidth() > maxSize || bitmap.getHeight() > maxSize) {
// Only if bitmap is bigger than maxSize, then resize it
if (bitmap.getWidth() > bitmap.getHeight()) {
int targetWidth = maxSize;
int targetHeight = bitmap.getHeight() * maxSize / bitmap.getWidth();
bitmap = Bitmap.createScaledBitmap(bitmap, targetWidth, targetHeight, false);
}
else {
int targetWidth = bitmap.getWidth() * maxSize / bitmap.getHeight();
int targetHeight = maxSize;
bitmap = Bitmap.createScaledBitmap(bitmap, targetWidth, targetHeight, false);
}
/**
* Resize a bitmap to the given size.
*
* @param baseBitmap The original bitmap.
* @param targetSize The target size.
* @param allowGrowing flag indicating if the image is allowed to grow.
* @return the resized image.
*/
public static Bitmap resizeBitmap(final Bitmap baseBitmap, final int targetSize, final boolean allowGrowing) {
if (baseBitmap.getWidth() == 0 || baseBitmap.getHeight() == 0) {
return baseBitmap;
}
else if (baseBitmap.getWidth() > targetSize || baseBitmap.getHeight() > targetSize || allowGrowing) {
if (baseBitmap.getWidth() > baseBitmap.getHeight()) {
int targetWidth = targetSize;
int targetHeight = baseBitmap.getHeight() * targetSize / baseBitmap.getWidth();
return Bitmap.createScaledBitmap(baseBitmap, targetWidth, targetHeight, false);
}
else {
int targetWidth = baseBitmap.getWidth() * targetSize / baseBitmap.getHeight();
int targetHeight = targetSize;
return Bitmap.createScaledBitmap(baseBitmap, targetWidth, targetHeight, false);
}
}

return bitmap;
else {
return baseBitmap;
}
}

/**
Expand Down
Loading

0 comments on commit b515d9e

Please sign in to comment.