/* * 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); if (null == file) { return; } 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(); } }