Add image search
This commit is contained in:
1 parent
311185825e
commit
231e463605
19 files changed
+854
-65
No files matched your search
@@ -113,4 +113,20 @@ public class AppConfig {
|
||||
public static File createExternalTempFile() {
|
||||
return FileUtils.createTempFile(getExternalTempDir(), null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static File getTempDir() {
|
||||
File dir = sContext.getCacheDir();
|
||||
File file;
|
||||
if (null != dir && FileUtils.ensureDirectory(file = new File(dir, TEMP))) {
|
||||
return file;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static File createTempFile() {
|
||||
return FileUtils.createTempFile(getTempDir(), null);
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@ import com.hippo.network.StatusCodeException;
|
||||
import com.hippo.okhttp.CookieDB;
|
||||
import com.hippo.scene.SceneApplication;
|
||||
import com.hippo.text.Html;
|
||||
import com.hippo.util.BitmapUtils;
|
||||
import com.hippo.util.ReadableTime;
|
||||
import com.hippo.yorozuya.FileUtils;
|
||||
import com.hippo.yorozuya.SimpleHandler;
|
||||
@@ -97,6 +98,7 @@ public class EhApplication extends SceneApplication implements Thread.UncaughtEx
|
||||
SpiderDen.initialize(this);
|
||||
EhDB.initialize(this);
|
||||
EhEngine.initialize();
|
||||
BitmapUtils.initialize(this);
|
||||
|
||||
if (EhDB.needMerge()) {
|
||||
EhDB.mergeOldDB(this);
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.hippo.ehviewer.client.exception.CancelledException;
|
||||
import com.hippo.yorozuya.PriorityThreadFactory;
|
||||
import com.hippo.yorozuya.SimpleHandler;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
@@ -57,6 +58,7 @@ public class EhClient {
|
||||
public static final int METHOD_GET_WHATS_HOT = 13;
|
||||
public static final int METHOD_GET_PROFILE = 14;
|
||||
public static final int METHOD_VOTE_COMMENT = 15;
|
||||
public static final int METHOD_IMAGE_SEARCH = 16;
|
||||
|
||||
private final ThreadPoolExecutor mRequestThreadPool;
|
||||
private final OkHttpClient mOkHttpClient;
|
||||
@@ -180,6 +182,8 @@ public class EhClient {
|
||||
return EhEngine.getProfile(this, mOkHttpClient);
|
||||
case METHOD_VOTE_COMMENT:
|
||||
return EhEngine.voteComment(this, mOkHttpClient, (Long) params[0], (String) params[1], (Long) params[2], (String) params[3], (Long) params[4], (Integer) params[5]);
|
||||
case METHOD_IMAGE_SEARCH:
|
||||
return EhEngine.imageSearch(this, mOkHttpClient, (File) params[0], (Boolean) params[1], (Boolean) params[2], (Boolean) params[3]);
|
||||
default:
|
||||
return new IllegalStateException("Can't detect method " + mMethod);
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ import okhttp3.Call;
|
||||
import okhttp3.FormBody;
|
||||
import okhttp3.Headers;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.MultipartBody;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
@@ -77,7 +78,8 @@ public class EhEngine {
|
||||
private static final String SAD_PANDA_TYPE = "image/gif";
|
||||
private static final String SAD_PANDA_LENGTH = "9615";
|
||||
|
||||
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
|
||||
public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");
|
||||
private static final MediaType MEDIA_TYPE_JPEG = MediaType.parse("image/jpeg");
|
||||
|
||||
public static EhFilter sEhFilter;
|
||||
|
||||
@@ -260,7 +262,7 @@ public class EhEngine {
|
||||
String url = EhUrl.getApiUrl();
|
||||
Log.d(TAG, url);
|
||||
Request request = new EhRequestBuilder(url)
|
||||
.post(RequestBody.create(JSON, json.toString()))
|
||||
.post(RequestBody.create(MEDIA_TYPE_JSON, json.toString()))
|
||||
.build();
|
||||
Call call = okHttpClient.newCall(request);
|
||||
|
||||
@@ -342,7 +344,7 @@ public class EhEngine {
|
||||
json.put("gid", gid);
|
||||
json.put("token", token);
|
||||
json.put("rating", (int) Math.ceil(rating * 2));
|
||||
final RequestBody requestBody = RequestBody.create(JSON, json.toString());
|
||||
final RequestBody requestBody = RequestBody.create(MEDIA_TYPE_JSON, json.toString());
|
||||
String url = EhUrl.getApiUrl();
|
||||
Log.d(TAG, url);
|
||||
Request request = new EhRequestBuilder(url, task.getEhConfig())
|
||||
@@ -404,7 +406,7 @@ public class EhEngine {
|
||||
.put("method", "gtoken")
|
||||
.put("pagelist", new JSONArray().put(
|
||||
new JSONArray().put(gid).put(gtoken).put(page + 1)));
|
||||
final RequestBody requestBody = RequestBody.create(JSON, json.toString());
|
||||
final RequestBody requestBody = RequestBody.create(MEDIA_TYPE_JSON, json.toString());
|
||||
String url = EhUrl.getApiUrl();
|
||||
Log.d(TAG, url);
|
||||
Request request = new EhRequestBuilder(url, task.getEhConfig())
|
||||
@@ -682,7 +684,7 @@ public class EhEngine {
|
||||
json.put("token", token);
|
||||
json.put("comment_id", commentId);
|
||||
json.put("comment_vote", commentVote);
|
||||
final RequestBody requestBody = RequestBody.create(JSON, json.toString());
|
||||
final RequestBody requestBody = RequestBody.create(MEDIA_TYPE_JSON, json.toString());
|
||||
String url = EhUrl.getApiUrl();
|
||||
Log.d(TAG, url);
|
||||
Request request = new EhRequestBuilder(url, task.getEhConfig())
|
||||
@@ -707,4 +709,94 @@ public class EhEngine {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param image Must be jpeg
|
||||
*/
|
||||
public static GalleryListParser.Result imageSearch(EhClient.Task task, OkHttpClient okHttpClient,
|
||||
File image, boolean uss, boolean osc, boolean se) throws Exception {
|
||||
MultipartBody.Builder builder = new MultipartBody.Builder();
|
||||
builder.setType(MultipartBody.FORM);
|
||||
builder.addPart(
|
||||
Headers.of("Content-Disposition", "form-data; name=\"sfile\"; filename=\"a.jpg\""),
|
||||
RequestBody.create(MEDIA_TYPE_JPEG, image)
|
||||
);
|
||||
if (uss) {
|
||||
builder.addPart(
|
||||
Headers.of("Content-Disposition", "form-data; name=\"fs_similar\""),
|
||||
RequestBody.create(null, "on")
|
||||
);
|
||||
}
|
||||
if (osc) {
|
||||
builder.addPart(
|
||||
Headers.of("Content-Disposition", "form-data; name=\"fs_covers\""),
|
||||
RequestBody.create(null, "on")
|
||||
);
|
||||
}
|
||||
if (se) {
|
||||
builder.addPart(
|
||||
Headers.of("Content-Disposition", "form-data; name=\"fs_exp\""),
|
||||
RequestBody.create(null, "on")
|
||||
);
|
||||
}
|
||||
builder.addPart(
|
||||
Headers.of("Content-Disposition", "form-data; name=\"f_sfile\""),
|
||||
RequestBody.create(null, "File Search")
|
||||
);
|
||||
String url = EhUrl.getImageSearchUrl();
|
||||
Log.d(TAG, url);
|
||||
Request request = new EhRequestBuilder(url, task.getEhConfig())
|
||||
.post(builder.build())
|
||||
.build();
|
||||
Call call = okHttpClient.newCall(request);
|
||||
|
||||
// Put call
|
||||
task.setCall(call);
|
||||
|
||||
String body = null;
|
||||
Headers headers = null;
|
||||
GalleryListParser.Result result;
|
||||
int code = -1;
|
||||
try {
|
||||
Response response = call.execute();
|
||||
|
||||
Log.d(TAG, "" + response.request().url().toString());
|
||||
|
||||
code = response.code();
|
||||
headers = response.headers();
|
||||
body = response.body().string();
|
||||
result = GalleryListParser.parse(body);
|
||||
} catch (Exception e) {
|
||||
throwException(call, code, headers, body, e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
// Filter title and uploader
|
||||
List<GalleryInfo> list = result.galleryInfoList;
|
||||
for (int i = 0, n = list.size(); i < n; i++) {
|
||||
GalleryInfo info = list.get(i);
|
||||
if (!sEhFilter.filterTitle(info) || !sEhFilter.filterUploader(info)) {
|
||||
list.remove(i);
|
||||
i--;
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
if (list.size() > 0 && (Settings.getShowJpnTitle() || sEhFilter.needCallApi())) {
|
||||
// Fill by api
|
||||
fillGalleryListByApi(task, okHttpClient, list);
|
||||
|
||||
// Filter tag
|
||||
for (int i = 0, n = list.size(); i < n; i++) {
|
||||
GalleryInfo info = list.get(i);
|
||||
if (!sEhFilter.filterTag(info) || !sEhFilter.filterTagNamespace(info)) {
|
||||
list.remove(i);
|
||||
i--;
|
||||
n--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.hippo.ehviewer.client;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.hippo.ehviewer.Settings;
|
||||
import com.hippo.network.UrlBuilder;
|
||||
|
||||
@@ -99,4 +101,15 @@ public class EhUrl {
|
||||
public static String getTagDefinitionUrl(String tag) {
|
||||
return "https://ehwiki.org/wiki/" + tag.replace(' ', '_');
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static String getImageSearchUrl() {
|
||||
switch (Settings.getGallerySite()) {
|
||||
default:
|
||||
case SITE_G:
|
||||
return "http://ul.e-hentai.org/image_lookup.php";
|
||||
case SITE_EX:
|
||||
return "http://ul.exhentai.org/image_lookup.php";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,6 +62,11 @@ public class ListUrlBuilder implements Cloneable, Parcelable {
|
||||
private int mAdvanceSearch = -1;
|
||||
private int mMinRating = -1;
|
||||
|
||||
private String mImagePath;
|
||||
private boolean mUseSimilarityScan;
|
||||
private boolean mOnlySearchCovers;
|
||||
private boolean mShowExpunged;
|
||||
|
||||
/**
|
||||
* Make this ListUrlBuilder point to homepage
|
||||
*/
|
||||
@@ -72,6 +77,10 @@ public class ListUrlBuilder implements Cloneable, Parcelable {
|
||||
mKeyword = null;
|
||||
mAdvanceSearch = -1;
|
||||
mMinRating = -1;
|
||||
mImagePath = null;
|
||||
mUseSimilarityScan = false;
|
||||
mOnlySearchCovers = false;
|
||||
mShowExpunged = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -132,6 +141,38 @@ public class ListUrlBuilder implements Cloneable, Parcelable {
|
||||
mMinRating = minRating;
|
||||
}
|
||||
|
||||
public String getImagePath() {
|
||||
return mImagePath;
|
||||
}
|
||||
|
||||
public void setImagePath(String imagePath) {
|
||||
mImagePath = imagePath;
|
||||
}
|
||||
|
||||
public boolean isUseSimilarityScan() {
|
||||
return mUseSimilarityScan;
|
||||
}
|
||||
|
||||
public void setUseSimilarityScan(boolean useSimilarityScan) {
|
||||
mUseSimilarityScan = useSimilarityScan;
|
||||
}
|
||||
|
||||
public boolean isOnlySearchCovers() {
|
||||
return mOnlySearchCovers;
|
||||
}
|
||||
|
||||
public void setOnlySearchCovers(boolean onlySearchCovers) {
|
||||
mOnlySearchCovers = onlySearchCovers;
|
||||
}
|
||||
|
||||
public boolean isShowExpunged() {
|
||||
return mShowExpunged;
|
||||
}
|
||||
|
||||
public void setShowExpunged(boolean showExpunged) {
|
||||
mShowExpunged = showExpunged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make them the same
|
||||
* @param lub The template
|
||||
@@ -143,6 +184,10 @@ public class ListUrlBuilder implements Cloneable, Parcelable {
|
||||
mKeyword = lub.mKeyword;
|
||||
mAdvanceSearch = lub.mAdvanceSearch;
|
||||
mMinRating = lub.mMinRating;
|
||||
mImagePath = lub.mImagePath;
|
||||
mUseSimilarityScan = lub.mUseSimilarityScan;
|
||||
mOnlySearchCovers = lub.mOnlySearchCovers;
|
||||
mShowExpunged = lub.mShowExpunged;
|
||||
}
|
||||
|
||||
public void set(QuickSearch q) {
|
||||
@@ -413,6 +458,8 @@ public class ListUrlBuilder implements Cloneable, Parcelable {
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
case MODE_IMAGE_SEARCH:
|
||||
return EhUrl.getImageSearchUrl();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -429,22 +476,30 @@ public class ListUrlBuilder implements Cloneable, Parcelable {
|
||||
dest.writeString(this.mKeyword);
|
||||
dest.writeInt(this.mAdvanceSearch);
|
||||
dest.writeInt(this.mMinRating);
|
||||
dest.writeString(this.mImagePath);
|
||||
dest.writeByte(mUseSimilarityScan ? (byte) 1 : (byte) 0);
|
||||
dest.writeByte(mOnlySearchCovers ? (byte) 1 : (byte) 0);
|
||||
dest.writeByte(mShowExpunged ? (byte) 1 : (byte) 0);
|
||||
}
|
||||
|
||||
public ListUrlBuilder() {}
|
||||
public ListUrlBuilder() {
|
||||
}
|
||||
|
||||
@SuppressWarnings("WrongConstant")
|
||||
protected ListUrlBuilder(Parcel in) {
|
||||
mMode = in.readInt();
|
||||
mPageIndex = in.readInt();
|
||||
mCategory = in.readInt();
|
||||
mKeyword = in.readString();
|
||||
mAdvanceSearch = in.readInt();
|
||||
mMinRating = in.readInt();
|
||||
this.mMode = in.readInt();
|
||||
this.mPageIndex = in.readInt();
|
||||
this.mCategory = in.readInt();
|
||||
this.mKeyword = in.readString();
|
||||
this.mAdvanceSearch = in.readInt();
|
||||
this.mMinRating = in.readInt();
|
||||
this.mImagePath = in.readString();
|
||||
this.mUseSimilarityScan = in.readByte() != 0;
|
||||
this.mOnlySearchCovers = in.readByte() != 0;
|
||||
this.mShowExpunged = in.readByte() != 0;
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<ListUrlBuilder> CREATOR = new Parcelable.Creator<ListUrlBuilder>() {
|
||||
|
||||
public static final Creator<ListUrlBuilder> CREATOR = new Creator<ListUrlBuilder>() {
|
||||
@Override
|
||||
public ListUrlBuilder createFromParcel(Parcel source) {
|
||||
return new ListUrlBuilder(source);
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.animation.Animator;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -68,6 +69,7 @@ import com.hippo.ehviewer.client.EhUrl;
|
||||
import com.hippo.ehviewer.client.EhUtils;
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.client.data.ListUrlBuilder;
|
||||
import com.hippo.ehviewer.client.exception.EhException;
|
||||
import com.hippo.ehviewer.client.parser.GalleryListParser;
|
||||
import com.hippo.ehviewer.dao.QuickSearch;
|
||||
import com.hippo.ehviewer.ui.CommonOperations;
|
||||
@@ -90,6 +92,7 @@ import com.hippo.yorozuya.MathUtils;
|
||||
import com.hippo.yorozuya.SimpleAnimatorListener;
|
||||
import com.hippo.yorozuya.ViewUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.List;
|
||||
@@ -106,6 +109,8 @@ public final class GalleryListScene extends BaseScene
|
||||
|
||||
private static final int BACK_PRESSED_INTERVAL = 2000;
|
||||
|
||||
public final static int REQUEST_CODE_SELECT_IMAGE = 0;
|
||||
|
||||
public final static String KEY_ACTION = "action";
|
||||
public final static String ACTION_HOMEPAGE = "action_homepage";
|
||||
public final static String ACTION_WHATS_HOT = "action_whats_hot";
|
||||
@@ -1111,7 +1116,12 @@ public final class GalleryListScene extends BaseScene
|
||||
startScene(new Announcer(GalleryDetailScene.class).setArgs(args));
|
||||
return;
|
||||
} else {
|
||||
mSearchLayout.formatListUrlBuilder(mUrlBuilder, query);
|
||||
try {
|
||||
mSearchLayout.formatListUrlBuilder(mUrlBuilder, query);
|
||||
} catch (EhException e) {
|
||||
showTip(e.getMessage(), LENGTH_LONG);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mUrlBuilder.reset();
|
||||
@@ -1177,6 +1187,15 @@ public final class GalleryListScene extends BaseScene
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectImage() {
|
||||
Intent intent = new Intent();
|
||||
intent.setType("image/*");
|
||||
intent.setAction(Intent.ACTION_GET_CONTENT);
|
||||
startActivityForResult(Intent.createChooser(intent,
|
||||
getString(R.string.select_image)), REQUEST_CODE_SELECT_IMAGE);
|
||||
}
|
||||
|
||||
// SearchBarMover.Helper
|
||||
@Override
|
||||
public boolean isValidView(RecyclerView recyclerView) {
|
||||
@@ -1207,6 +1226,17 @@ public final class GalleryListScene extends BaseScene
|
||||
scene.startScene(new Announcer(GalleryListScene.class).setArgs(args));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (REQUEST_CODE_SELECT_IMAGE == requestCode) {
|
||||
if (Activity.RESULT_OK == resultCode && null != mSearchLayout && null != data) {
|
||||
mSearchLayout.setImageUri(data.getData());
|
||||
}
|
||||
} else {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
private class GalleryListAdapter extends GalleryAdapter {
|
||||
|
||||
public GalleryListAdapter(@NonNull LayoutInflater inflater,
|
||||
@@ -1243,6 +1273,14 @@ public final class GalleryListScene extends BaseScene
|
||||
activity.getStageId(), getTag(), taskId));
|
||||
request.setArgs();
|
||||
mClient.execute(request);
|
||||
} else if (ListUrlBuilder.MODE_IMAGE_SEARCH == mUrlBuilder.getMode()) {
|
||||
EhRequest request = new EhRequest();
|
||||
request.setMethod(EhClient.METHOD_IMAGE_SEARCH);
|
||||
request.setCallback(new GetGalleryListListener(getContext(),
|
||||
activity.getStageId(), getTag(), taskId));
|
||||
request.setArgs(new File(mUrlBuilder.getImagePath()), mUrlBuilder.isUseSimilarityScan(),
|
||||
mUrlBuilder.isOnlySearchCovers(), mUrlBuilder.isShowExpunged());
|
||||
mClient.execute(request);
|
||||
} else {
|
||||
String url = mUrlBuilder.build();
|
||||
EhRequest request = new EhRequest();
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.AbsSavedState;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.hippo.ehviewer.AppConfig;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.client.data.ListUrlBuilder;
|
||||
import com.hippo.ehviewer.client.exception.EhException;
|
||||
import com.hippo.io.UniFileInputStreamPipe;
|
||||
import com.hippo.unifile.UniFile;
|
||||
import com.hippo.util.BitmapUtils;
|
||||
import com.hippo.yorozuya.IOUtils;
|
||||
import com.hippo.yorozuya.ViewUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public final class ImageSearchLayout extends LinearLayout implements View.OnClickListener {
|
||||
|
||||
private static final String TAG = ImageSearchLayout.class.getSimpleName();
|
||||
|
||||
private ImageView mPreview;
|
||||
private View mSelectImage;
|
||||
private CheckBox mSearchUSS;
|
||||
private CheckBox mSearchOSC;
|
||||
private CheckBox mSearchSE;
|
||||
|
||||
private Helper mHelper;
|
||||
|
||||
@Nullable
|
||||
private String mImagePath;
|
||||
|
||||
public ImageSearchLayout(Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public ImageSearchLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public ImageSearchLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void init(Context context) {
|
||||
setOrientation(VERTICAL);
|
||||
setDividerDrawable(context.getResources().getDrawable(R.drawable.spacer_keyline));
|
||||
setShowDividers(SHOW_DIVIDER_MIDDLE);
|
||||
LayoutInflater.from(context).inflate(R.layout.widget_image_search, this);
|
||||
|
||||
mPreview = (ImageView) ViewUtils.$$(this, R.id.preview);
|
||||
mSelectImage = ViewUtils.$$(this, R.id.select_image);
|
||||
mSearchUSS = (CheckBox) ViewUtils.$$(this, R.id.search_uss);
|
||||
mSearchOSC = (CheckBox) ViewUtils.$$(this, R.id.search_osc);
|
||||
mSearchSE = (CheckBox) ViewUtils.$$(this, R.id.search_se);
|
||||
|
||||
mSelectImage.setOnClickListener(this);
|
||||
}
|
||||
|
||||
public void setHelper(Helper helper) {
|
||||
mHelper = helper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v == mSelectImage) {
|
||||
if (null != mHelper) {
|
||||
mHelper.onSelectImage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setImageUri(@Nullable Uri imageUri) {
|
||||
if (null == imageUri) {
|
||||
return;
|
||||
}
|
||||
|
||||
Context context = getContext();
|
||||
UniFile file = UniFile.fromUri(context, imageUri);
|
||||
try {
|
||||
int maxSize = context.getResources().getDimensionPixelOffset(R.dimen.image_search_max_size);
|
||||
Bitmap bitmap = BitmapUtils.decodeStream(new UniFileInputStreamPipe(file), maxSize, maxSize);
|
||||
if (null == bitmap) {
|
||||
return;
|
||||
}
|
||||
File temp = AppConfig.createTempFile();
|
||||
if (null == temp) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO ehentai image search is bad when I'm writing this line.
|
||||
// Re-compress image will make image search failed.
|
||||
OutputStream os = null;
|
||||
try {
|
||||
os = new FileOutputStream(temp);
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, os);
|
||||
mImagePath = temp.getPath();
|
||||
mPreview.setImageBitmap(bitmap);
|
||||
mPreview.setVisibility(VISIBLE);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
IOUtils.closeQuietly(os);
|
||||
}
|
||||
} catch (OutOfMemoryError e) {
|
||||
Log.e(TAG, "Out of memory");
|
||||
}
|
||||
}
|
||||
|
||||
private void setImagePath(@Nullable String imagePath) {
|
||||
if (null == imagePath) {
|
||||
return;
|
||||
}
|
||||
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = new FileInputStream(imagePath);
|
||||
Bitmap bitmap = BitmapFactory.decodeStream(is);
|
||||
if (null == bitmap) {
|
||||
return;
|
||||
}
|
||||
mImagePath = imagePath;
|
||||
mPreview.setImageBitmap(bitmap);
|
||||
mPreview.setVisibility(VISIBLE);
|
||||
} catch (FileNotFoundException e) {
|
||||
// Ignore
|
||||
} finally {
|
||||
IOUtils.closeQuietly(is);
|
||||
}
|
||||
}
|
||||
|
||||
public void formatListUrlBuilder(ListUrlBuilder builder) throws EhException {
|
||||
if (null == mImagePath) {
|
||||
throw new EhException(getContext().getString(R.string.select_image_first));
|
||||
}
|
||||
|
||||
builder.setImagePath(mImagePath);
|
||||
builder.setUseSimilarityScan(mSearchUSS.isChecked());
|
||||
builder.setOnlySearchCovers(mSearchOSC.isChecked());
|
||||
builder.setShowExpunged(mSearchSE.isChecked());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Parcelable onSaveInstanceState() {
|
||||
Parcelable superState = super.onSaveInstanceState();
|
||||
SavedState ss = new SavedState(superState);
|
||||
ss.imagePath = mImagePath;
|
||||
return ss;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Parcelable state) {
|
||||
SavedState ss = (SavedState) state;
|
||||
super.onRestoreInstanceState(ss.getSuperState());
|
||||
setImagePath(ss.imagePath);
|
||||
}
|
||||
|
||||
private static class SavedState extends AbsSavedState {
|
||||
|
||||
String imagePath;
|
||||
|
||||
/**
|
||||
* Constructor called from {@link ImageSearchLayout#onSaveInstanceState()}
|
||||
*/
|
||||
protected SavedState(Parcelable superState) {
|
||||
super(superState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor called from {@link #CREATOR}
|
||||
*/
|
||||
protected SavedState(Parcel source) {
|
||||
super(source);
|
||||
imagePath = source.readString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
super.writeToParcel(out, flags);
|
||||
out.writeString(imagePath);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<SavedState> CREATOR
|
||||
= new Parcelable.Creator<SavedState>() {
|
||||
@Override
|
||||
public SavedState createFromParcel(Parcel in) {
|
||||
return new SavedState(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavedState[] newArray(int size) {
|
||||
return new SavedState[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public interface Helper {
|
||||
void onSelectImage();
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,10 @@
|
||||
|
||||
package com.hippo.ehviewer.widget;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.IntDef;
|
||||
@@ -39,6 +41,7 @@ import android.widget.TextView;
|
||||
import com.hippo.easyrecyclerview.EasyRecyclerView;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.client.data.ListUrlBuilder;
|
||||
import com.hippo.ehviewer.client.exception.EhException;
|
||||
import com.hippo.rippleold.RippleSalon;
|
||||
import com.hippo.widget.RadioGridGroup;
|
||||
import com.hippo.yorozuya.ViewUtils;
|
||||
@@ -47,9 +50,9 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnCheckedChangeListener,
|
||||
View.OnClickListener {
|
||||
View.OnClickListener, ImageSearchLayout.Helper {
|
||||
|
||||
@IntDef({SEARCH_MODE_NORMAL, SEARCH_MODE_IMAGE, SEARCH_MODE_SPECIFY})
|
||||
@IntDef({SEARCH_MODE_NORMAL, SEARCH_MODE_IMAGE})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
private @interface SearchMode {}
|
||||
|
||||
@@ -59,22 +62,19 @@ public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnC
|
||||
|
||||
public static final int SEARCH_MODE_NORMAL = 0;
|
||||
public static final int SEARCH_MODE_IMAGE = 1;
|
||||
public static final int SEARCH_MODE_SPECIFY = 2;
|
||||
|
||||
private static final int ITEM_TYPE_NORMAL = 0;
|
||||
private static final int ITEM_TYPE_NORMAL_ADVANCE = 1;
|
||||
private static final int ITEM_TYPE_IMAGE = 2;
|
||||
private static final int ITEM_TYPE_SPECIFY = 3;
|
||||
private static final int ITEM_TYPE_ACTION = 4;
|
||||
private static final int ITEM_TYPE_ACTION = 3;
|
||||
|
||||
private static final int[] SEARCH_ITEM_COUNT_ARRAY = {
|
||||
3, 2, 2
|
||||
3, 2
|
||||
};
|
||||
|
||||
private static final int[][] SEARCH_ITEM_TYPE = {
|
||||
{ITEM_TYPE_NORMAL, ITEM_TYPE_NORMAL_ADVANCE, ITEM_TYPE_ACTION}, // SEARCH_MODE_NORMAL
|
||||
{ITEM_TYPE_IMAGE, ITEM_TYPE_ACTION}, // SEARCH_MODE_IMAGE
|
||||
{ITEM_TYPE_SPECIFY, ITEM_TYPE_ACTION} // SEARCH_MODE_SPECIFY
|
||||
};
|
||||
|
||||
private LayoutInflater mInflater;
|
||||
@@ -86,13 +86,15 @@ public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnC
|
||||
private CategoryTable mCategoryTable;
|
||||
private RadioGridGroup mNormalSearchMode;
|
||||
private ImageView mNormalSearchModeHelp;
|
||||
private View mSearchTagHelp;
|
||||
private SwitchCompat mEnableAdvanceSwitch;
|
||||
|
||||
private View mAdvanceView;
|
||||
private AdvanceSearchTable mTableAdvanceSearch;
|
||||
|
||||
private ImageSearchLayout mImageView;
|
||||
|
||||
private View mActionView;
|
||||
private TextView mAction;
|
||||
|
||||
private LinearLayoutManager mLayoutManager;
|
||||
private SearchAdapter mAdapter;
|
||||
@@ -109,26 +111,23 @@ public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnC
|
||||
init(context);
|
||||
}
|
||||
|
||||
@SuppressLint("InflateParams")
|
||||
private void init(Context context) {
|
||||
Resources resources = context.getResources();
|
||||
mInflater = LayoutInflater.from(context);
|
||||
|
||||
mLayoutManager = new LinearLayoutManager(context);
|
||||
mAdapter = new SearchAdapter();
|
||||
//mAnimator = new SearchItemAnimator(this);
|
||||
setLayoutManager(mLayoutManager);
|
||||
setAdapter(mAdapter);
|
||||
setHasFixedSize(true);
|
||||
setClipToPadding(false);
|
||||
//setItemAnimator(mAnimator);
|
||||
int paddingH = resources.getDimensionPixelOffset(R.dimen.list_content_margin_h);
|
||||
int paddingV = resources.getDimensionPixelOffset(R.dimen.list_content_margin_v);
|
||||
setPadding(paddingV, paddingH, paddingV, paddingH);
|
||||
|
||||
FrameLayout frameLayout = new FrameLayout(context);
|
||||
|
||||
// Create normal view
|
||||
View normalView = mInflater.inflate(R.layout.search_normal, frameLayout, false);
|
||||
View normalView = mInflater.inflate(R.layout.search_normal, null);
|
||||
mNormalView = normalView;
|
||||
mCategoryTable = (CategoryTable) normalView.findViewById(R.id.search_category_table);
|
||||
mNormalSearchMode = (RadioGridGroup) normalView.findViewById(R.id.normal_search_mode);
|
||||
@@ -140,11 +139,17 @@ public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnC
|
||||
mEnableAdvanceSwitch.setSwitchPadding(resources.getDimensionPixelSize(R.dimen.switch_padding));
|
||||
|
||||
// Create advance view
|
||||
mAdvanceView = mInflater.inflate(R.layout.search_advance, frameLayout, false);
|
||||
mAdvanceView = mInflater.inflate(R.layout.search_advance, null);
|
||||
mTableAdvanceSearch = (AdvanceSearchTable) mAdvanceView.findViewById(R.id.search_advance_search_table);
|
||||
|
||||
// Create image view
|
||||
mImageView = (ImageSearchLayout) mInflater.inflate(R.layout.search_image, null);
|
||||
mImageView.setHelper(this);
|
||||
|
||||
// Create action view
|
||||
mActionView = new View(context);// TODO mInflater.inflate(R.layout.search_action, frameLayout, false);
|
||||
mActionView = mInflater.inflate(R.layout.search_action, null);
|
||||
mAction = (TextView) mActionView.findViewById(R.id.action);
|
||||
mAction.setOnClickListener(this);
|
||||
}
|
||||
|
||||
public void setHelper(Helper helper) {
|
||||
@@ -155,12 +160,24 @@ public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnC
|
||||
mLayoutManager.scrollToPositionWithOffset(0, 0);
|
||||
}
|
||||
|
||||
public void setImageUri(Uri imageUri) {
|
||||
mImageView.setImageUri(imageUri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectImage() {
|
||||
if (mHelper != null) {
|
||||
mHelper.onSelectImage();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatchSaveInstanceState(@NonNull SparseArray<Parcelable> container) {
|
||||
super.dispatchSaveInstanceState(container);
|
||||
|
||||
mNormalView.saveHierarchyState(container);
|
||||
mAdvanceView.saveHierarchyState(container);
|
||||
mImageView.saveHierarchyState(container);
|
||||
mActionView.saveHierarchyState(container);
|
||||
}
|
||||
|
||||
@@ -170,6 +187,7 @@ public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnC
|
||||
|
||||
mNormalView.restoreHierarchyState(container);
|
||||
mAdvanceView.restoreHierarchyState(container);
|
||||
mImageView.restoreHierarchyState(container);
|
||||
mActionView.restoreHierarchyState(container);
|
||||
}
|
||||
|
||||
@@ -214,29 +232,35 @@ public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnC
|
||||
return R.id.search_specify_gallery == mNormalSearchMode.getCheckedRadioButtonId();
|
||||
}
|
||||
|
||||
// TODO image search
|
||||
public void formatListUrlBuilder(ListUrlBuilder urlBuilder, String query) {
|
||||
public void formatListUrlBuilder(ListUrlBuilder urlBuilder, String query) throws EhException {
|
||||
urlBuilder.reset();
|
||||
|
||||
int nsMode = mNormalSearchMode.getCheckedRadioButtonId();
|
||||
switch (nsMode) {
|
||||
default:
|
||||
case R.id.search_normal_search:
|
||||
urlBuilder.setMode(ListUrlBuilder.MODE_NORMAL);
|
||||
switch (mSearchMode) {
|
||||
case SEARCH_MODE_NORMAL:
|
||||
int nsMode = mNormalSearchMode.getCheckedRadioButtonId();
|
||||
switch (nsMode) {
|
||||
default:
|
||||
case R.id.search_normal_search:
|
||||
urlBuilder.setMode(ListUrlBuilder.MODE_NORMAL);
|
||||
break;
|
||||
case R.id.search_specify_uploader:
|
||||
urlBuilder.setMode(ListUrlBuilder.MODE_UPLOADER);
|
||||
break;
|
||||
case R.id.search_specify_tag:
|
||||
urlBuilder.setMode(ListUrlBuilder.MODE_TAG);
|
||||
break;
|
||||
}
|
||||
urlBuilder.setKeyword(query);
|
||||
urlBuilder.setCategory(mCategoryTable.getCategory());
|
||||
if (mEnableAdvance) {
|
||||
urlBuilder.setAdvanceSearch(mTableAdvanceSearch.getAdvanceSearch());
|
||||
urlBuilder.setMinRating(mTableAdvanceSearch.getMinRating());
|
||||
}
|
||||
break;
|
||||
case R.id.search_specify_uploader:
|
||||
urlBuilder.setMode(ListUrlBuilder.MODE_UPLOADER);
|
||||
case SEARCH_MODE_IMAGE:
|
||||
urlBuilder.setMode(ListUrlBuilder.MODE_IMAGE_SEARCH);
|
||||
mImageView.formatListUrlBuilder(urlBuilder);
|
||||
break;
|
||||
case R.id.search_specify_tag:
|
||||
urlBuilder.setMode(ListUrlBuilder.MODE_TAG);
|
||||
break;
|
||||
}
|
||||
|
||||
urlBuilder.setKeyword(query);
|
||||
urlBuilder.setCategory(mCategoryTable.getCategory());
|
||||
if (mEnableAdvance) {
|
||||
urlBuilder.setAdvanceSearch(mTableAdvanceSearch.getAdvanceSearch());
|
||||
urlBuilder.setMinRating(mTableAdvanceSearch.getMinRating());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,7 +287,7 @@ public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnC
|
||||
int oldItemCount = mAdapter.getItemCount();
|
||||
|
||||
mSearchMode++;
|
||||
if (mSearchMode > SEARCH_MODE_SPECIFY) {
|
||||
if (mSearchMode > SEARCH_MODE_IMAGE) {
|
||||
mSearchMode = SEARCH_MODE_NORMAL;
|
||||
}
|
||||
|
||||
@@ -272,6 +296,19 @@ public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnC
|
||||
mAdapter.notifyItemRangeRemoved(0, oldItemCount - 1);
|
||||
mAdapter.notifyItemRangeInserted(0, newItemCount - 1);
|
||||
|
||||
// Update action text
|
||||
int resId;
|
||||
switch (mSearchMode) {
|
||||
default:
|
||||
case SEARCH_MODE_NORMAL:
|
||||
resId = R.string.image_search;
|
||||
break;
|
||||
case SEARCH_MODE_IMAGE:
|
||||
resId = R.string.keyword_search;
|
||||
break;
|
||||
}
|
||||
mAction.setText(resId);
|
||||
|
||||
if (mHelper != null) {
|
||||
mHelper.onChangeSearchMode();
|
||||
}
|
||||
@@ -283,6 +320,8 @@ public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnC
|
||||
new AlertDialog.Builder(getContext())
|
||||
.setMessage(R.string.search_tip)
|
||||
.show();
|
||||
} else if (mAction == v) {
|
||||
toggleSearchMode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,6 +360,17 @@ public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnC
|
||||
mActionView.setLayoutParams(new RecyclerView.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
int resId;
|
||||
switch (mSearchMode) {
|
||||
default:
|
||||
case SEARCH_MODE_NORMAL:
|
||||
resId = R.string.image_search;
|
||||
break;
|
||||
case SEARCH_MODE_IMAGE:
|
||||
resId = R.string.keyword_search;
|
||||
break;
|
||||
}
|
||||
mAction.setText(resId);
|
||||
view = mActionView;
|
||||
} else {
|
||||
view = mInflater.inflate(R.layout.search_category, parent, false);
|
||||
@@ -337,6 +387,11 @@ public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnC
|
||||
ViewUtils.removeFromParent(mAdvanceView);
|
||||
content.addView(mAdvanceView);
|
||||
break;
|
||||
case ITEM_TYPE_IMAGE:
|
||||
title.setText(R.string.search_image);
|
||||
ViewUtils.removeFromParent(mImageView);
|
||||
content.addView(mImageView);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,5 +406,6 @@ public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnC
|
||||
|
||||
public interface Helper {
|
||||
void onChangeSearchMode();
|
||||
void onSelectImage();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.util;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.hippo.yorozuya.MathUtils;
|
||||
import com.hippo.yorozuya.io.InputStreamPipe;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class BitmapUtils {
|
||||
|
||||
public static Context sContext;
|
||||
|
||||
public static void initialize(Context context) {
|
||||
sContext = context.getApplicationContext();
|
||||
}
|
||||
|
||||
public static long availableMemory() {
|
||||
final Runtime runtime = Runtime.getRuntime();
|
||||
final long used = runtime.totalMemory() - runtime.freeMemory();
|
||||
|
||||
final ActivityManager activityManager = (ActivityManager) sContext.
|
||||
getSystemService(Context.ACTIVITY_SERVICE);
|
||||
final long total = activityManager.getMemoryClass() * 1024 * 1024;
|
||||
|
||||
return total - used;
|
||||
}
|
||||
|
||||
public static Bitmap decodeStream(@NonNull InputStreamPipe isp, int maxWidth, int maxHeight,
|
||||
int pixels, boolean checkMemory, boolean justCalc, int[] sampleSize) {
|
||||
try {
|
||||
isp.obtain();
|
||||
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inJustDecodeBounds = true;
|
||||
BitmapFactory.decodeStream(isp.open(), null, options);
|
||||
isp.close();
|
||||
|
||||
int width = options.outWidth;
|
||||
int height = options.outHeight;
|
||||
if (width <= 0 || height <= 0) {
|
||||
if (sampleSize != null && sampleSize.length >= 1) {
|
||||
sampleSize[0] = -1;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
int scaleW = 1;
|
||||
int scaleH = 1;
|
||||
int scaleP = 1;
|
||||
int scaleM = 1;
|
||||
if (maxWidth > 0 && width > maxWidth) {
|
||||
scaleW = MathUtils.ceilDivide(width, maxWidth);
|
||||
}
|
||||
if (maxHeight > 0 && height > maxHeight) {
|
||||
scaleH = MathUtils.ceilDivide(height, maxHeight);
|
||||
}
|
||||
if (pixels > 0 && width * height > pixels) {
|
||||
scaleP = (int) Math.ceil(Math.sqrt(width * height / (float) pixels));
|
||||
}
|
||||
if (checkMemory) {
|
||||
long m = availableMemory() - 5 * 1024 * 1024; // Leave 5m
|
||||
if (m < 0) {
|
||||
if (sampleSize != null && sampleSize.length >= 1) {
|
||||
sampleSize[0] = -1;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (width * height * 3 > m) {
|
||||
scaleM = (int) Math.ceil(Math.sqrt(width * height * 3 / (float) m));
|
||||
}
|
||||
}
|
||||
options.inSampleSize = MathUtils.nextPowerOf2(MathUtils.max(scaleW, scaleH, scaleP, scaleM, 1));
|
||||
if (sampleSize != null && sampleSize.length >= 1) {
|
||||
sampleSize[0] = options.inSampleSize;
|
||||
}
|
||||
|
||||
options.inJustDecodeBounds = false;
|
||||
|
||||
if (justCalc) {
|
||||
return null;
|
||||
} else {
|
||||
try {
|
||||
return BitmapFactory.decodeStream(isp.open(), null, options);
|
||||
} catch (OutOfMemoryError e) {
|
||||
if (sampleSize != null && sampleSize.length >= 1) {
|
||||
sampleSize[0] = -1;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (sampleSize != null && sampleSize.length >= 1) {
|
||||
sampleSize[0] = -1;
|
||||
}
|
||||
return null;
|
||||
} finally {
|
||||
isp.close();
|
||||
isp.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null or the bitmap
|
||||
*/
|
||||
public static Bitmap decodeStream(@NonNull InputStreamPipe isp, int maxWidth, int maxHeight) {
|
||||
return decodeStream(isp, maxWidth, maxHeight, -1, false, false, null);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user