mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
show emojis on map
This commit is contained in:
@@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.components.emoji;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
@@ -31,7 +32,7 @@ import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
class EmojiProvider {
|
||||
public class EmojiProvider {
|
||||
|
||||
private static final String TAG = EmojiProvider.class.getSimpleName();
|
||||
private static volatile EmojiProvider instance = null;
|
||||
@@ -111,6 +112,19 @@ class EmojiProvider {
|
||||
return getEmojiDrawable(drawInfo, false);
|
||||
}
|
||||
|
||||
public boolean isEmoji(CharSequence emoji) {
|
||||
return emojiTree.getEmoji(emoji, 0, emoji.length()) != null;
|
||||
}
|
||||
|
||||
public @Nullable Bitmap getEmojiBitmap(CharSequence emoji, boolean background) {
|
||||
EmojiDrawInfo drawInfo = emojiTree.getEmoji(emoji, 0, emoji.length());
|
||||
EmojiDrawable drawable = ((EmojiDrawable) getEmojiDrawable(drawInfo, background));
|
||||
if (drawable != null) {
|
||||
return drawable.getEmojiBitmap();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected @Nullable Drawable getEmojiDrawable(@Nullable EmojiDrawInfo drawInfo, boolean background) {
|
||||
if (drawInfo == null) {
|
||||
return null;
|
||||
@@ -158,6 +172,26 @@ class EmojiProvider {
|
||||
this.intrinsicHeight = EMOJI_RAW_HEIGHT * decodeScale;
|
||||
}
|
||||
|
||||
private Bitmap getEmojiBitmap() {
|
||||
Bitmap singleEmoji = Bitmap.createBitmap((int) intrinsicWidth/2, (int) intrinsicHeight/2, Bitmap.Config.ARGB_8888);
|
||||
|
||||
final int row = info.getIndex() / EMOJI_PER_ROW;
|
||||
final int rowIndex = info.getIndex() % EMOJI_PER_ROW;
|
||||
|
||||
Rect desRect = new Rect(0, 0, (int) intrinsicWidth, (int) intrinsicWidth);
|
||||
Rect srcRect = new Rect((int)(rowIndex * intrinsicWidth),
|
||||
(int)(row * intrinsicHeight + row * verticalPad)+1,
|
||||
(int)(((rowIndex + 1) * intrinsicWidth)-1),
|
||||
(int)((row + 1) * intrinsicHeight + row * verticalPad)-1);
|
||||
|
||||
Canvas canvas = new Canvas(singleEmoji);
|
||||
canvas.scale(0.5f, 0.5f);
|
||||
canvas.drawBitmap(bmp, srcRect, desRect, paint);
|
||||
|
||||
return singleEmoji;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void draw(@NonNull Canvas canvas) {
|
||||
if (bmp == null) {
|
||||
|
||||
@@ -7,10 +7,13 @@ import com.b44t.messenger.DcContext;
|
||||
import com.mapbox.geojson.Feature;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
|
||||
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiProvider;
|
||||
import org.thoughtcrime.securesms.map.model.MapSource;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import static org.thoughtcrime.securesms.map.MapDataManager.TIMESTAMP_NOW;
|
||||
@@ -20,10 +23,10 @@ import static org.thoughtcrime.securesms.map.MapDataManager.TIME_FRAME;
|
||||
* Created by cyberta on 15.04.19.
|
||||
*/
|
||||
|
||||
public class DataCollectionTask extends AsyncTask<Void, Void, Void> {
|
||||
public class DataCollectionTask extends AsyncTask<Void, Void, Set<String>> {
|
||||
|
||||
public interface DataCollectionCallback {
|
||||
void onDataCollectionFinished();
|
||||
void onDataCollectionFinished(Set<String> emojiCodepoints);
|
||||
}
|
||||
|
||||
private static final String TAG = DataCollectionTask.class.getSimpleName();
|
||||
@@ -37,6 +40,7 @@ public class DataCollectionTask extends AsyncTask<Void, Void, Void> {
|
||||
private final LatLngBounds.Builder boundingBuilder;
|
||||
private final DcContext dcContext;
|
||||
private final DataCollectionCallback callback;
|
||||
private final EmojiProvider emojiProvider;
|
||||
|
||||
public DataCollectionTask(DcContext context,
|
||||
int chatId,
|
||||
@@ -45,6 +49,7 @@ public class DataCollectionTask extends AsyncTask<Void, Void, Void> {
|
||||
ConcurrentHashMap featureCollections,
|
||||
ConcurrentHashMap<Integer, Feature> lastPositions,
|
||||
LatLngBounds.Builder boundingBuilder,
|
||||
EmojiProvider emojiProvider,
|
||||
DataCollectionCallback callback) {
|
||||
this.chatId = chatId;
|
||||
this.contactMapSources = contactMapSources;
|
||||
@@ -54,6 +59,7 @@ public class DataCollectionTask extends AsyncTask<Void, Void, Void> {
|
||||
this.dcContext = context;
|
||||
this.callback = callback;
|
||||
this.contactIds = contactIds;
|
||||
this.emojiProvider = emojiProvider;
|
||||
instances.add(this);
|
||||
}
|
||||
|
||||
@@ -64,29 +70,32 @@ public class DataCollectionTask extends AsyncTask<Void, Void, Void> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
protected Set<String> doInBackground(Void... voids) {
|
||||
Log.d(TAG, "performance test - collect Data start");
|
||||
HashSet<String> emojiCodePoints = new HashSet<>();
|
||||
DataCollector dataCollector = new DataCollector(dcContext,
|
||||
contactMapSources,
|
||||
featureCollections,
|
||||
lastPositions,
|
||||
boundingBuilder);
|
||||
contactMapSources,
|
||||
featureCollections,
|
||||
lastPositions,
|
||||
emojiCodePoints,
|
||||
emojiProvider,
|
||||
boundingBuilder);
|
||||
for (int contactId : contactIds) {
|
||||
dataCollector.updateSource(chatId,
|
||||
contactId,
|
||||
System.currentTimeMillis() - TIME_FRAME,
|
||||
TIMESTAMP_NOW);
|
||||
contactId,
|
||||
System.currentTimeMillis() - TIME_FRAME,
|
||||
TIMESTAMP_NOW);
|
||||
if (this.isCancelled()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return emojiCodePoints;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void value) {
|
||||
protected void onPostExecute(Set<String> strings) {
|
||||
if (!this.isCancelled()) {
|
||||
callback.onDataCollectionFinished();
|
||||
callback.onDataCollectionFinished(strings);
|
||||
}
|
||||
instances.remove(this);
|
||||
Log.d(TAG, "performance test - collect Data finished");
|
||||
|
||||
@@ -11,14 +11,17 @@ import com.mapbox.geojson.Point;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
|
||||
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiProvider;
|
||||
import org.thoughtcrime.securesms.map.model.MapSource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import static org.thoughtcrime.securesms.map.MapDataManager.ACCURACY;
|
||||
import static org.thoughtcrime.securesms.map.MapDataManager.CONTACT_ID;
|
||||
import static org.thoughtcrime.securesms.map.MapDataManager.IS_EMOJI_CHAR;
|
||||
import static org.thoughtcrime.securesms.map.MapDataManager.IS_POI;
|
||||
import static org.thoughtcrime.securesms.map.MapDataManager.LAST_LOCATION;
|
||||
import static org.thoughtcrime.securesms.map.MapDataManager.LAST_POSITION_ICON;
|
||||
@@ -41,18 +44,24 @@ public class DataCollector {
|
||||
private ConcurrentHashMap<Integer, MapSource> contactMapSources;
|
||||
private ConcurrentHashMap<String, LinkedList<Feature>> featureCollections;
|
||||
private ConcurrentHashMap<Integer, Feature> lastPositions;
|
||||
private Set<String> emojiCodePoints;
|
||||
private LatLngBounds.Builder boundingBuilder;
|
||||
private EmojiProvider emojiProvider;
|
||||
|
||||
public DataCollector(DcContext dcContext,
|
||||
ConcurrentHashMap<Integer, MapSource> contactMapSources,
|
||||
ConcurrentHashMap<String, LinkedList<Feature>> featureCollections,
|
||||
ConcurrentHashMap<Integer, Feature> lastPositions,
|
||||
Set<String> emojiCodePoints,
|
||||
EmojiProvider emojiProvider,
|
||||
LatLngBounds.Builder boundingBuilder) {
|
||||
this.dcContext = dcContext;
|
||||
this.contactMapSources = contactMapSources;
|
||||
this.featureCollections = featureCollections;
|
||||
this.lastPositions = lastPositions;
|
||||
this.boundingBuilder = boundingBuilder;
|
||||
this.emojiCodePoints = emojiCodePoints;
|
||||
this.emojiProvider = emojiProvider;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +94,7 @@ public class DataCollector {
|
||||
"";
|
||||
boolean isPoi = locations.isIndependent(i);
|
||||
int messageId = locations.getMsgId(i);
|
||||
boolean isEmojiChar = !codepointChar.isEmpty() && emojiProvider.isEmoji(codepointChar);
|
||||
|
||||
Feature pointFeature = Feature.fromGeometry(point, new JsonObject(), String.valueOf(locations.getLocationId(i)));
|
||||
pointFeature.addBooleanProperty(MARKER_SELECTED, false);
|
||||
@@ -94,9 +104,17 @@ public class DataCollector {
|
||||
pointFeature.addNumberProperty(MESSAGE_ID, messageId);
|
||||
pointFeature.addNumberProperty(ACCURACY, locations.getAccuracy(i));
|
||||
pointFeature.addStringProperty(MARKER_CHAR, codepointChar);
|
||||
pointFeature.addStringProperty(MARKER_ICON, isPoi ?
|
||||
contactMapMetadata.getMarkerPoi() :
|
||||
contactMapMetadata.getMarkerIcon());
|
||||
pointFeature.addBooleanProperty(IS_EMOJI_CHAR, isEmojiChar);
|
||||
if (isPoi && isEmojiChar) {
|
||||
//we save emoji bitmaps in mapboxstyle with the codepoint as the key
|
||||
pointFeature.addStringProperty(MARKER_ICON, codepointChar);
|
||||
emojiCodePoints.add(codepointChar);
|
||||
} else if (isPoi) {
|
||||
pointFeature.addStringProperty(MARKER_ICON, contactMapMetadata.getMarkerPoi());
|
||||
} else {
|
||||
pointFeature.addStringProperty(MARKER_ICON, contactMapMetadata.getMarkerIcon());
|
||||
}
|
||||
|
||||
pointFeature.addBooleanProperty(IS_POI, isPoi);
|
||||
if (isPoi && codepointChar.length() == 0 && messageId != 0) {
|
||||
//has a long poi label
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package org.thoughtcrime.securesms.map;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiProvider;
|
||||
import org.thoughtcrime.securesms.util.Pair;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public class EmojiBitmapGenerationTask extends AsyncTask<String, Pair<String, Bitmap>, Void> {
|
||||
|
||||
public interface EmojiBitmapGenerationCallback {
|
||||
void onEmojiBitmapCreated(String codePoint, Bitmap emoji);
|
||||
}
|
||||
WeakReference<EmojiBitmapGenerationCallback> callbackWeakReference;
|
||||
WeakReference<EmojiProvider> emojiProviderWeakReference;
|
||||
|
||||
public EmojiBitmapGenerationTask(EmojiBitmapGenerationCallback callback, EmojiProvider emojiProvider) {
|
||||
callbackWeakReference = new WeakReference<>(callback);
|
||||
emojiProviderWeakReference = new WeakReference<>(emojiProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(String... codePoints) {
|
||||
for (String codePoint : codePoints) {
|
||||
EmojiProvider emojiProvider = emojiProviderWeakReference.get();
|
||||
if (emojiProvider == null) {
|
||||
return null;
|
||||
}
|
||||
Bitmap emoji = emojiProvider.getEmojiBitmap(codePoint, true);
|
||||
publishProgress(new Pair<>(codePoint, emoji));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProgressUpdate(Pair<String, Bitmap>... values) {
|
||||
super.onProgressUpdate(values);
|
||||
EmojiBitmapGenerationCallback callback = callbackWeakReference.get();
|
||||
if (callback != null) {
|
||||
callback.onEmojiBitmapCreated(values[0].first(), values[0].second());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void aVoid) {
|
||||
super.onPostExecute(aVoid);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCancelled() {
|
||||
super.onCancelled();
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,10 @@ package org.thoughtcrime.securesms.map;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.b44t.messenger.DcEvent;
|
||||
import com.b44t.messenger.DcEventCenter;
|
||||
import com.mapbox.android.core.permissions.PermissionsManager;
|
||||
@@ -23,28 +24,33 @@ import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
|
||||
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiProvider;
|
||||
import org.thoughtcrime.securesms.connect.ApplicationDcContext;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.map.DataCollectionTask.DataCollectionCallback;
|
||||
import org.thoughtcrime.securesms.map.EmojiBitmapGenerationTask.EmojiBitmapGenerationCallback;
|
||||
import org.thoughtcrime.securesms.map.GenerateInfoWindowTask.GenerateInfoWindowCallback;
|
||||
import org.thoughtcrime.securesms.map.model.FilterProvider;
|
||||
import org.thoughtcrime.securesms.map.model.MapSource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import static com.b44t.messenger.DcContext.DC_EVENT_LOCATION_CHANGED;
|
||||
import static com.b44t.messenger.DcContext.DC_GCL_ADD_SELF;
|
||||
import static com.mapbox.mapboxsdk.location.modes.RenderMode.COMPASS;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.all;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.eq;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.has;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.length;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.eq;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.neq;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.not;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.switchCase;
|
||||
@@ -81,7 +87,10 @@ import static org.thoughtcrime.securesms.util.BitmapUtil.generateColoredBitmap;
|
||||
* Created by cyberta on 07.03.19.
|
||||
*/
|
||||
|
||||
public class MapDataManager implements DcEventCenter.DcEventDelegate, GenerateInfoWindowCallback, DataCollectionCallback {
|
||||
public class MapDataManager implements DcEventCenter.DcEventDelegate,
|
||||
GenerateInfoWindowCallback,
|
||||
DataCollectionCallback,
|
||||
EmojiBitmapGenerationCallback {
|
||||
public static final String MARKER_SELECTED = "MARKER_SELECTED";
|
||||
public static final String LAST_LOCATION = "LAST_LOCATION";
|
||||
public static final String CONTACT_ID = "CONTACT_ID";
|
||||
@@ -90,6 +99,7 @@ public class MapDataManager implements DcEventCenter.DcEventDelegate, GenerateIn
|
||||
public static final String MESSAGE_ID = "MESSAGE_ID";
|
||||
public static final String ACCURACY = "ACCURACY";
|
||||
public static final String MARKER_CHAR = "MARKER_CHAR";
|
||||
public static final String IS_EMOJI_CHAR = "IS_EMOJI_CHAR";
|
||||
public static final String POI_LONG_DESCRIPTION = "POI_LONG_DESCRIPTION";
|
||||
public static final String MARKER_ICON = "MARKER_ICON";
|
||||
public static final String IS_POI = "IS_POI";
|
||||
@@ -109,6 +119,7 @@ public class MapDataManager implements DcEventCenter.DcEventDelegate, GenerateIn
|
||||
private ConcurrentHashMap<Integer, MapSource> contactMapSources = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<String, LinkedList<Feature>> featureCollections = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<Integer, Feature> lastPositions = new ConcurrentHashMap<>();
|
||||
private Set<String> emojiCodePoints = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
private FilterProvider filterProvider = new FilterProvider();
|
||||
private Feature selectedFeature;
|
||||
private int chatId;
|
||||
@@ -119,6 +130,7 @@ public class MapDataManager implements DcEventCenter.DcEventDelegate, GenerateIn
|
||||
private boolean isInitial = true;
|
||||
private boolean showTraces = false;
|
||||
private LocationComponent locationComponent;
|
||||
private EmojiProvider emojiProvider;
|
||||
|
||||
public interface MapDataState {
|
||||
void onDataInitialized(LatLngBounds bounds);
|
||||
@@ -133,6 +145,7 @@ public class MapDataManager implements DcEventCenter.DcEventDelegate, GenerateIn
|
||||
boundingBuilder = new LatLngBounds.Builder();
|
||||
this.callback = updateCallback;
|
||||
this.locationComponent = locationComponent;
|
||||
emojiProvider = EmojiProvider.getInstance(context);
|
||||
|
||||
initInfoWindowLayer();
|
||||
initLastPositionLayer();
|
||||
@@ -189,16 +202,21 @@ public class MapDataManager implements DcEventCenter.DcEventDelegate, GenerateIn
|
||||
Log.d(TAG, "updateEvent in MapDataManager called. eventId: " + eventId);
|
||||
int contactId = event.getData1Int();
|
||||
if (contactMapSources.containsKey(contactId)) {
|
||||
HashSet<String> emojiCodePoints = new HashSet<>();
|
||||
DataCollector collector = new DataCollector(dcContext,
|
||||
contactMapSources,
|
||||
featureCollections,
|
||||
lastPositions, null);
|
||||
contactMapSources,
|
||||
featureCollections,
|
||||
lastPositions,
|
||||
emojiCodePoints,
|
||||
emojiProvider,
|
||||
null
|
||||
);
|
||||
collector.updateSource(chatId,
|
||||
contactId,
|
||||
System.currentTimeMillis() - TIME_FRAME,
|
||||
TIMESTAMP_NOW);
|
||||
|
||||
refreshSource(contactId);
|
||||
handleEmojiCodepoints(emojiCodePoints);
|
||||
}
|
||||
Log.d(TAG, "updateEvent in MapDataManager called. finished: " + eventId);
|
||||
}
|
||||
@@ -260,7 +278,13 @@ public class MapDataManager implements DcEventCenter.DcEventDelegate, GenerateIn
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDataCollectionFinished() {
|
||||
public void onEmojiBitmapCreated(String codePoint, Bitmap emoji) {
|
||||
mapboxStyle.addImage(codePoint, emoji);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDataCollectionFinished(Set <String> emojiCodePoints) {
|
||||
handleEmojiCodepoints(emojiCodePoints);
|
||||
for (MapSource source : contactMapSources.values()) {
|
||||
initContactBasedLayers(source);
|
||||
refreshSource(source.getContactId());
|
||||
@@ -279,6 +303,16 @@ public class MapDataManager implements DcEventCenter.DcEventDelegate, GenerateIn
|
||||
}
|
||||
}
|
||||
|
||||
public void handleEmojiCodepoints(Set<String> emojiCodePoints) {
|
||||
// generate only new emoji bitmaps, so check the diff
|
||||
emojiCodePoints.removeAll(this.emojiCodePoints);
|
||||
if (!emojiCodePoints.isEmpty()) {
|
||||
EmojiBitmapGenerationTask task = new EmojiBitmapGenerationTask(this, emojiProvider);
|
||||
task.execute(emojiCodePoints.toArray(new String[0]));
|
||||
this.emojiCodePoints.addAll(emojiCodePoints);
|
||||
}
|
||||
}
|
||||
|
||||
public void filterRange(long startTimestamp, long endTimestamp) {
|
||||
int[] contactIds = getContactIds(chatId);
|
||||
filterProvider.setRangeFilter(startTimestamp, endTimestamp);
|
||||
@@ -511,7 +545,9 @@ public class MapDataManager implements DcEventCenter.DcEventDelegate, GenerateIn
|
||||
contactMapSources,
|
||||
featureCollections,
|
||||
lastPositions,
|
||||
|
||||
boundingBuilder,
|
||||
emojiProvider,
|
||||
this).execute();
|
||||
}
|
||||
|
||||
@@ -523,6 +559,7 @@ public class MapDataManager implements DcEventCenter.DcEventDelegate, GenerateIn
|
||||
featureCollections,
|
||||
lastPositions,
|
||||
boundingBuilder,
|
||||
emojiProvider,
|
||||
this).execute();
|
||||
}
|
||||
|
||||
|
||||
@@ -410,4 +410,18 @@ public class BitmapUtil {
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public static Bitmap scaleDown(Bitmap realImage, float maxImageSize,
|
||||
boolean filter) {
|
||||
float ratio = Math.min(
|
||||
(float) maxImageSize / realImage.getWidth(),
|
||||
(float) maxImageSize / realImage.getHeight());
|
||||
int width = Math.round((float) ratio * realImage.getWidth());
|
||||
int height = Math.round((float) ratio * realImage.getHeight());
|
||||
|
||||
Bitmap newBitmap = Bitmap.createScaledBitmap(realImage, width,
|
||||
height, filter);
|
||||
return newBitmap;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user