• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.gallery3d.filtershow.ui;
18 
19 import android.content.Intent;
20 import android.graphics.Bitmap;
21 import android.graphics.Rect;
22 import android.net.Uri;
23 import android.os.Bundle;
24 import android.os.Handler;
25 import androidx.fragment.app.DialogFragment;
26 import android.text.Editable;
27 import android.text.TextWatcher;
28 import android.view.LayoutInflater;
29 import android.view.View;
30 import android.view.ViewGroup;
31 import android.widget.EditText;
32 import android.widget.SeekBar;
33 import android.widget.TextView;
34 
35 import com.android.gallery3d.R;
36 import com.android.gallery3d.filtershow.FilterShowActivity;
37 import com.android.gallery3d.filtershow.imageshow.MasterImage;
38 import com.android.gallery3d.filtershow.pipeline.ImagePreset;
39 import com.android.gallery3d.filtershow.pipeline.ProcessingService;
40 import com.android.gallery3d.filtershow.tools.SaveImage;
41 
42 import java.io.ByteArrayOutputStream;
43 import java.io.File;
44 
45 public class ExportDialog extends DialogFragment implements View.OnClickListener,
46         SeekBar.OnSeekBarChangeListener {
47     SeekBar mSeekBar;
48     TextView mSeekVal;
49     EditText mWidthText;
50     EditText mHeightText;
51     TextView mEstimatedSize;
52     int mQuality = 95;
53     int mExportWidth = 0;
54     int mExportHeight = 0;
55     Rect mOriginalBounds;
56     int mCompressedSize;
57     Rect mCompressedBounds;
58     float mExportCompressionMargin = 1.1f;
59     float mRatio;
60     String mSliderLabel;
61     boolean mEditing = false;
62     Handler mHandler;
63     int mUpdateDelay = 1000;
64     Runnable mUpdateRunnable = new Runnable() {
65         @Override
66         public void run() {
67             updateCompressionFactor();
68             updateSize();
69         }
70     };
71 
72     private class Watcher implements TextWatcher {
73         private EditText mEditText;
Watcher(EditText text)74         Watcher(EditText text) {
75             mEditText = text;
76         }
77 
78         @Override
beforeTextChanged(CharSequence s, int start, int count, int after)79         public void beforeTextChanged(CharSequence s, int start, int count, int after) {
80         }
81 
82         @Override
onTextChanged(CharSequence s, int start, int before, int count)83         public void onTextChanged(CharSequence s, int start, int before, int count) {
84         }
85 
86         @Override
afterTextChanged(Editable s)87         public void afterTextChanged(Editable s) {
88             textChanged(mEditText);
89         }
90     }
91 
92     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)93     public View onCreateView(LayoutInflater inflater, ViewGroup container,
94             Bundle savedInstanceState) {
95         mHandler = new Handler(getActivity().getMainLooper());
96 
97         View view = inflater.inflate(R.layout.filtershow_export_dialog, container);
98         mSeekBar = (SeekBar) view.findViewById(R.id.qualitySeekBar);
99         mSeekVal = (TextView) view.findViewById(R.id.qualityTextView);
100         mSliderLabel = getString(R.string.quality) + ": ";
101         mSeekBar.setProgress(mQuality);
102         mSeekVal.setText(mSliderLabel + mSeekBar.getProgress());
103         mSeekBar.setOnSeekBarChangeListener(this);
104         mWidthText = (EditText) view.findViewById(R.id.editableWidth);
105         mHeightText = (EditText) view.findViewById(R.id.editableHeight);
106         mEstimatedSize = (TextView) view.findViewById(R.id.estimadedSize);
107 
108         mOriginalBounds = MasterImage.getImage().getOriginalBounds();
109         ImagePreset preset = MasterImage.getImage().getPreset();
110         mOriginalBounds = preset.finalGeometryRect(mOriginalBounds.width(),
111                 mOriginalBounds.height());
112         mRatio = mOriginalBounds.width() / (float) mOriginalBounds.height();
113         mWidthText.setText("" + mOriginalBounds.width());
114         mHeightText.setText("" + mOriginalBounds.height());
115         mExportWidth = mOriginalBounds.width();
116         mExportHeight = mOriginalBounds.height();
117         mWidthText.addTextChangedListener(new Watcher(mWidthText));
118         mHeightText.addTextChangedListener(new Watcher(mHeightText));
119 
120         view.findViewById(R.id.cancel).setOnClickListener(this);
121         view.findViewById(R.id.done).setOnClickListener(this);
122         getDialog().setTitle(R.string.export_flattened);
123 
124         updateCompressionFactor();
125         updateSize();
126         return view;
127     }
128 
129     @Override
onStopTrackingTouch(SeekBar arg0)130     public void onStopTrackingTouch(SeekBar arg0) {
131         // Do nothing
132     }
133 
134     @Override
onStartTrackingTouch(SeekBar arg0)135     public void onStartTrackingTouch(SeekBar arg0) {
136         // Do nothing
137     }
138 
139     @Override
onProgressChanged(SeekBar arg0, int arg1, boolean arg2)140     public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
141         mSeekVal.setText(mSliderLabel + arg1);
142         mQuality = mSeekBar.getProgress();
143         scheduleUpdateCompressionFactor();
144     }
145 
scheduleUpdateCompressionFactor()146     private void scheduleUpdateCompressionFactor() {
147         mHandler.removeCallbacks(mUpdateRunnable);
148         mHandler.postDelayed(mUpdateRunnable, mUpdateDelay);
149     }
150 
151     @Override
onClick(View v)152     public void onClick(View v) {
153         switch (v.getId()) {
154             case R.id.cancel:
155                 dismiss();
156                 break;
157             case R.id.done:
158                 FilterShowActivity activity = (FilterShowActivity) getActivity();
159                 Uri sourceUri = MasterImage.getImage().getUri();
160                 File dest = SaveImage.getNewFile(activity,  activity.getSelectedImageUri());
161                 float scaleFactor = mExportWidth / (float) mOriginalBounds.width();
162                 Intent processIntent = ProcessingService.getSaveIntent(activity, MasterImage
163                         .getImage().getPreset(), dest, activity.getSelectedImageUri(), sourceUri,
164                         true, mSeekBar.getProgress(), scaleFactor, false);
165                 activity.startService(processIntent);
166                 dismiss();
167                 break;
168         }
169     }
170 
updateCompressionFactor()171     public void updateCompressionFactor() {
172         Bitmap bitmap = MasterImage.getImage().getFilteredImage();
173         if (bitmap == null) {
174             return;
175         }
176         ByteArrayOutputStream out = new ByteArrayOutputStream();
177         bitmap.compress(Bitmap.CompressFormat.JPEG, mQuality, out);
178         mCompressedSize = out.size();
179         mCompressedBounds = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
180     }
181 
updateSize()182     public void updateSize() {
183         if (mCompressedBounds == null) {
184             return;
185         }
186         // This is a rough estimate of the final save size. There's some loose correlation
187         // between a compressed jpeg and a larger version of it in function of the image
188         // area. Not a perfect estimate by far.
189         float originalArea = mCompressedBounds.width() * mCompressedBounds.height();
190         float newArea = mExportWidth * mExportHeight;
191         float factor = originalArea / (float) mCompressedSize;
192         float compressedSize = newArea / factor;
193         compressedSize *= mExportCompressionMargin;
194         float size = compressedSize / 1024.f / 1024.f;
195         size = ((int) (size * 100)) / 100f;
196         String estimatedSize = "" + size + " Mb";
197         mEstimatedSize.setText(estimatedSize);
198     }
199 
textChanged(EditText text)200     private void textChanged(EditText text) {
201         if (mEditing) {
202             return;
203         }
204         mEditing = true;
205         int width = 1;
206         int height = 1;
207         if (text.getId() == R.id.editableWidth) {
208             if (mWidthText.getText() != null) {
209                 String value = String.valueOf(mWidthText.getText());
210                 if (value.length() > 0) {
211                     width = Integer.parseInt(value);
212                     if (width > mOriginalBounds.width()) {
213                         width = mOriginalBounds.width();
214                         mWidthText.setText("" + width);
215                     }
216                     if (width <= 0) {
217                         width = (int) Math.ceil(mRatio);
218                         mWidthText.setText("" + width);
219                     }
220                     height = (int) (width / mRatio);
221                 }
222                 mHeightText.setText("" + height);
223             }
224         } else if (text.getId() == R.id.editableHeight) {
225             if (mHeightText.getText() != null) {
226                 String value = String.valueOf(mHeightText.getText());
227                 if (value.length() > 0) {
228                     height = Integer.parseInt(value);
229                     if (height > mOriginalBounds.height()) {
230                         height = mOriginalBounds.height();
231                         mHeightText.setText("" + height);
232                     }
233                     if (height <= 0) {
234                         height = 1;
235                         mHeightText.setText("" + height);
236                     }
237                     width = (int) (height * mRatio);
238                 }
239                 mWidthText.setText("" + width);
240             }
241         }
242         mExportWidth = width;
243         mExportHeight = height;
244         updateSize();
245         mEditing = false;
246     }
247 
248 }
249