BarInsta/app/src/main/java/awais/instagrabber/viewmodels/ImageEditViewModel.java

222 lines
8.0 KiB
Java

package awais.instagrabber.viewmodels;
import android.app.Application;
import android.graphics.RectF;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.documentfile.provider.DocumentFile;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import java.io.File;
import java.time.format.DateTimeFormatter;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import awais.instagrabber.fragments.imageedit.filters.FiltersHelper.FilterType;
import awais.instagrabber.fragments.imageedit.filters.filters.Filter;
import awais.instagrabber.fragments.imageedit.filters.properties.Property;
import awais.instagrabber.models.SavedImageEditState;
import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.DownloadUtils;
import awais.instagrabber.utils.SerializablePair;
import awais.instagrabber.utils.Utils;
import jp.co.cyberagent.android.gpuimage.GPUImage;
import jp.co.cyberagent.android.gpuimage.filter.GPUImageFilter;
import jp.co.cyberagent.android.gpuimage.filter.GPUImageFilterGroup;
public class ImageEditViewModel extends AndroidViewModel {
private static final String CROP = "crop";
private static final String RESULT = "result";
private static final String FILE_FORMAT = "yyyyMMddHHmmssSSS";
private static final String MIME_TYPE = Utils.mimeTypeMap.getMimeTypeFromExtension("jpg");
private static final DateTimeFormatter SIMPLE_DATE_FORMAT = DateTimeFormatter.ofPattern(FILE_FORMAT, Locale.US);
private Uri originalUri;
private SavedImageEditState savedImageEditState;
private final String sessionId;
private final Uri destinationUri;
private final Uri cropDestinationUri;
private final MutableLiveData<Boolean> loading = new MutableLiveData<>(false);
private final MutableLiveData<Uri> resultUri = new MutableLiveData<>(null);
private final MutableLiveData<Tab> currentTab = new MutableLiveData<>(Tab.RESULT);
private final MutableLiveData<Boolean> isCropped = new MutableLiveData<>(false);
private final MutableLiveData<Boolean> isTuned = new MutableLiveData<>(false);
private final MutableLiveData<Boolean> isFiltered = new MutableLiveData<>(false);
private final DocumentFile outputDir;
private List<Filter<? extends GPUImageFilter>> tuningFilters;
private Filter<? extends GPUImageFilter> appliedFilter;
private final DocumentFile destinationFile;
public ImageEditViewModel(final Application application) {
super(application);
sessionId = LocalDateTime.now().format(SIMPLE_DATE_FORMAT);
outputDir = DownloadUtils.getImageEditDir(sessionId, application);
destinationFile = outputDir.createFile(MIME_TYPE, RESULT + ".jpg");
destinationUri = destinationFile.getUri();
cropDestinationUri = outputDir.createFile(MIME_TYPE, CROP + ".jpg").getUri();
}
public String getSessionId() {
return sessionId;
}
public Uri getOriginalUri() {
return originalUri;
}
public void setOriginalUri(final Uri originalUri) {
if (originalUri == null) return;
this.originalUri = originalUri;
savedImageEditState = new SavedImageEditState(sessionId, originalUri.toString());
if (resultUri.getValue() == null) {
resultUri.postValue(originalUri);
}
}
public Uri getDestinationUri() {
return destinationUri;
}
public Uri getCropDestinationUri() {
return cropDestinationUri;
}
public LiveData<Boolean> isLoading() {
return loading;
}
public LiveData<Uri> getResultUri() {
return resultUri;
}
public LiveData<Boolean> isCropped() {
return isCropped;
}
public LiveData<Boolean> isTuned() {
return isTuned;
}
public LiveData<Boolean> isFiltered() {
return isFiltered;
}
public void setResultUri(final Uri uri) {
if (uri == null) return;
resultUri.postValue(uri);
}
public LiveData<Tab> getCurrentTab() {
return currentTab;
}
public void setCurrentTab(final Tab tab) {
if (tab == null) return;
this.currentTab.postValue(tab);
}
public SavedImageEditState getSavedImageEditState() {
return savedImageEditState;
}
public void setCropResult(final float[] imageMatrixValues, final RectF cropRect) {
savedImageEditState.setCropImageMatrixValues(imageMatrixValues);
savedImageEditState.setCropRect(cropRect);
isCropped.postValue(true);
applyFilters();
}
private void applyFilters() {
final GPUImage gpuImage = new GPUImage(getApplication());
if ((tuningFilters != null && !tuningFilters.isEmpty()) || appliedFilter != null) {
AppExecutors.INSTANCE.getTasksThread().submit(() -> {
final List<GPUImageFilter> list = new ArrayList<>();
if (tuningFilters != null) {
for (Filter<? extends GPUImageFilter> tuningFilter : tuningFilters) {
list.add(tuningFilter.getInstance());
}
}
if (appliedFilter != null) {
list.add(appliedFilter.getInstance());
}
gpuImage.setFilter(new GPUImageFilterGroup(list));
final Uri uri = cropDestinationUri != null ? cropDestinationUri : originalUri;
gpuImage.setImage(uri);
gpuImage.saveToPictures(new File(destinationUri.toString()), false, uri1 -> setResultUri(destinationUri));
});
return;
}
setResultUri(cropDestinationUri);
}
public void cancel() {
delete(outputDir);
}
private void delete(@NonNull final DocumentFile file) {
if (file.isDirectory()) {
final DocumentFile[] files = file.listFiles();
if (files != null) {
for (DocumentFile f : files) {
delete(f);
}
}
}
file.delete();
}
public void setAppliedFilters(final List<Filter<?>> tuningFilters, final Filter<?> filter) {
this.tuningFilters = tuningFilters;
this.appliedFilter = filter;
if (savedImageEditState != null) {
final HashMap<FilterType, Map<Integer, Object>> tuningFiltersMap = new HashMap<>();
for (final Filter<?> tuningFilter : tuningFilters) {
final SerializablePair<FilterType, Map<Integer, Object>> filterValuesMap = getFilterValuesMap(tuningFilter);
tuningFiltersMap.put(filterValuesMap.first, filterValuesMap.second);
}
savedImageEditState.setAppliedTuningFilters(tuningFiltersMap);
savedImageEditState.setAppliedFilter(getFilterValuesMap(filter));
}
isTuned.postValue(!tuningFilters.isEmpty());
isFiltered.postValue(filter != null);
setResultUri(destinationUri);
}
private SerializablePair<FilterType, Map<Integer, Object>> getFilterValuesMap(final Filter<?> filter) {
if (filter == null) return null;
final FilterType type = filter.getType();
final Map<Integer, Property<?>> properties = filter.getProperties();
final Map<Integer, Object> propertyValueMap = new HashMap<>();
if (properties != null) {
final Set<Map.Entry<Integer, Property<?>>> entries = properties.entrySet();
for (final Map.Entry<Integer, Property<?>> entry : entries) {
final Integer propId = entry.getKey();
final Property<?> property = entry.getValue();
final Object value = property.getValue();
propertyValueMap.put(propId, value);
}
}
return new SerializablePair<>(type, propertyValueMap);
}
// public File getDestinationFile() {
// return destinationFile;
// }
public enum Tab {
RESULT,
CROP,
TUNE,
FILTERS
}
}