mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-29 05:43:55 +01:00
Fixes #945 Check image coordinates for direct Nearby uploads in locations that the user is not currently in (#2099)
* Add getGeolocation method to geolocation from file path * Add geolocation check to receiveDirect method checks, means it will be checked durimg nearby direct uploads * Create method body for geolocation and nearby place coordinate comparaison, this method will be filled on consequent commits * Add a method to find location missmatch * app/src/main/java/fr/free/nrw/commons/utils/ImageUtils.java * Add if check to upload activity to detect pictures with wrong location, and save it to shared prefs * Do not edit wikidata item if picture has wrong location info * Add one more bitwise operand to possible warning reasons for wrong location case * Add a bitwise variable for wrong locatio case * Share nearby place location just like wikidataEntityId, so that we can compare * Implement check image geolocation is different method by comparing nearby location and file EXIF geolocation * Add Javadocs * Remove logs * Fix all taken on wrong phrases as taken at * Fix typo on logs * Simplify if logic * Fix string issues
This commit is contained in:
parent
6754ce121c
commit
718ad3a12c
15 changed files with 161 additions and 54 deletions
|
|
@ -9,6 +9,7 @@ import android.graphics.Rect;
|
|||
import android.net.Uri;
|
||||
import android.support.annotation.IntDef;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import com.facebook.common.executors.CallerThreadExecutor;
|
||||
import com.facebook.common.references.CloseableReference;
|
||||
|
|
@ -25,6 +26,7 @@ import java.lang.annotation.Retention;
|
|||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
|
|
@ -36,6 +38,7 @@ public class ImageUtils {
|
|||
public static final int IMAGE_DARK = 1;
|
||||
public static final int IMAGE_BLURRY = 1 << 1;
|
||||
public static final int IMAGE_DUPLICATE = 1 << 2;
|
||||
public static final int IMAGE_GEOLOCATION_DIFFERENT = 1 << 3;
|
||||
public static final int IMAGE_OK = 0;
|
||||
public static final int IMAGE_KEEP = -1;
|
||||
public static final int IMAGE_WAIT = -2;
|
||||
|
|
@ -54,7 +57,8 @@ public class ImageUtils {
|
|||
IMAGE_WAIT,
|
||||
EMPTY_TITLE,
|
||||
FILE_NAME_EXISTS,
|
||||
NO_CATEGORY_SELECTED
|
||||
NO_CATEGORY_SELECTED,
|
||||
IMAGE_GEOLOCATION_DIFFERENT
|
||||
}
|
||||
)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
|
|
@ -93,17 +97,30 @@ public class ImageUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Pulls the pixels into an array and then runs through it while checking the brightness of each pixel.
|
||||
* The calculation of brightness of each pixel is done by extracting the RGB constituents of the pixel
|
||||
* and then applying the formula to calculate its "Luminance".
|
||||
* Pixels with luminance greater than 40% are considered to be bright pixels while the ones with luminance
|
||||
* greater than 26% but less than 40% are considered to be pixels with medium brightness. The rest are
|
||||
* dark pixels.
|
||||
* If the number of bright pixels is more than 2.5% or the number of pixels with medium brightness is
|
||||
* more than 30% of the total number of pixels then the image is considered to be OK else dark.
|
||||
* @param bitmap The bitmap that needs to be checked.
|
||||
* @return true if bitmap is dark or null, false if bitmap is bright
|
||||
* @param geolocationOfFileString Geolocation of image. If geotag doesn't exists, then this will be an empty string
|
||||
* @param wikidataItemLocationString Location of wikidata item will be edited after upload
|
||||
* @return false if image is neither dark nor blurry or if the input bitmapRegionDecoder provided is null
|
||||
* true if geolocation of the image and wikidata item are different
|
||||
*/
|
||||
public static boolean checkImageGeolocationIsDifferent(String geolocationOfFileString, String wikidataItemLocationString) {
|
||||
Timber.d("Comparing geolocation of file with nearby place location");
|
||||
if (geolocationOfFileString == null || geolocationOfFileString == "") { // Means that geolocation for this image is not given
|
||||
return false; // Since we don't know geolocation of file, we choose letting upload
|
||||
}
|
||||
|
||||
String[] geolocationOfFile = geolocationOfFileString.split("\\|");
|
||||
String[] wikidataItemLocation = wikidataItemLocationString.split("/");
|
||||
|
||||
Double distance = LengthUtils.computeDistanceBetween(
|
||||
new LatLng(Double.parseDouble(geolocationOfFile[0]),Double.parseDouble(geolocationOfFile[1]),0)
|
||||
, new LatLng(Double.parseDouble(wikidataItemLocation[0]), Double.parseDouble(wikidataItemLocation[1]),0));
|
||||
if ( distance >= 1000 ) {// Distance is more than 1 km, means that geolocation is wrong
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean checkIfImageIsDark(Bitmap bitmap) {
|
||||
if (bitmap == null) {
|
||||
Timber.e("Expected bitmap was null");
|
||||
|
|
@ -206,24 +223,37 @@ public class ImageUtils {
|
|||
}
|
||||
|
||||
public static String getErrorMessageForResult(Context context, @Result int result) {
|
||||
String errorMessage;
|
||||
if (result == ImageUtils.IMAGE_DARK)
|
||||
errorMessage = context.getString(R.string.upload_image_problem_dark);
|
||||
else if (result == ImageUtils.IMAGE_BLURRY)
|
||||
errorMessage = context.getString(R.string.upload_image_problem_blurry);
|
||||
else if (result == ImageUtils.IMAGE_DUPLICATE)
|
||||
errorMessage = context.getString(R.string.upload_image_problem_duplicate);
|
||||
else if (result == (ImageUtils.IMAGE_DARK|ImageUtils.IMAGE_BLURRY))
|
||||
errorMessage = context.getString(R.string.upload_image_problem_dark_blurry);
|
||||
else if (result == (ImageUtils.IMAGE_DARK|ImageUtils.IMAGE_DUPLICATE))
|
||||
errorMessage = context.getString(R.string.upload_image_problem_dark_duplicate);
|
||||
else if (result == (ImageUtils.IMAGE_BLURRY|ImageUtils.IMAGE_DUPLICATE))
|
||||
errorMessage = context.getString(R.string.upload_image_problem_blurry_duplicate);
|
||||
else if (result == (ImageUtils.IMAGE_DARK|ImageUtils.IMAGE_BLURRY|ImageUtils.IMAGE_DUPLICATE))
|
||||
errorMessage = context.getString(R.string.upload_image_problem_dark_blurry_duplicate);
|
||||
else
|
||||
return "";
|
||||
/**
|
||||
* Result variable is a result of an or operation of all possbile problems. Ie. if result
|
||||
* is 0001 means IMAGE_DARK, if result is 1100 IMAGE_DUPLICATE and IMAGE_GEOLOCATION_DIFFERENT
|
||||
*/
|
||||
StringBuilder errorMessage = new StringBuilder();
|
||||
if (((IMAGE_DARK | IMAGE_GEOLOCATION_DIFFERENT | IMAGE_BLURRY | IMAGE_DUPLICATE) & result) == 0 ) {
|
||||
Timber.d("No issues to warn user is found");
|
||||
} else {
|
||||
Timber.d("Issues found to warn user");
|
||||
|
||||
return errorMessage;
|
||||
errorMessage.append(context.getResources().getString(R.string.upload_problem_exist));
|
||||
|
||||
if ((IMAGE_DARK & result) != 0 ) { // We are checking image dark bit to see if that bit is set or not
|
||||
errorMessage.append(context.getResources().getString(R.string.upload_problem_image_dark));
|
||||
}
|
||||
|
||||
if ((IMAGE_BLURRY & result) != 0 ) {
|
||||
errorMessage.append(context.getResources().getString(R.string.upload_image_problem_blurry));
|
||||
}
|
||||
|
||||
if ((IMAGE_DUPLICATE & result) != 0 ) {
|
||||
errorMessage.append(context.getResources().getString(R.string.upload_problem_image_duplicate));
|
||||
}
|
||||
|
||||
if ((IMAGE_GEOLOCATION_DIFFERENT & result) != 0 ) {
|
||||
errorMessage.append(context.getResources().getString(R.string.upload_problem_different_geolocation));
|
||||
}
|
||||
|
||||
errorMessage.append(context.getResources().getString(R.string.upload_problem_do_you_continue));
|
||||
}
|
||||
|
||||
return errorMessage.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
25
app/src/main/java/fr/free/nrw/commons/utils/PlaceUtils.java
Normal file
25
app/src/main/java/fr/free/nrw/commons/utils/PlaceUtils.java
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
package fr.free.nrw.commons.utils;
|
||||
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
|
||||
public class PlaceUtils {
|
||||
|
||||
/**
|
||||
* Converts our defined LatLng to string, to put as String
|
||||
* @param latLng latlang will be converted to string
|
||||
* @return latitude + "/" + longitude
|
||||
*/
|
||||
public static String latLangToString(LatLng latLng) {
|
||||
return latLng.getLatitude()+"/"+latLng.getLongitude();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts latitude + "/" + longitude string to commons LatLng
|
||||
* @param latLngString latitude + "/" + longitude string
|
||||
* @return commons LatLng
|
||||
*/
|
||||
public static LatLng stringToLatLng(String latLngString) {
|
||||
String[] parts = latLngString.split("/");
|
||||
return new LatLng(Double.parseDouble(parts[0]), Double.parseDouble(parts[1]), 0);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue