2 * Copyright (C) 2013 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.gallery3d.filtershow.ui;
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 android.support.v4.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;
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;
42 import java.io.ByteArrayOutputStream;
45 public class ExportDialog extends DialogFragment implements View.OnClickListener,
46 SeekBar.OnSeekBarChangeListener {
51 TextView mEstimatedSize;
54 int mExportHeight = 0;
57 Rect mCompressedBounds;
58 float mExportCompressionMargin = 1.1f;
61 boolean mEditing = false;
63 int mUpdateDelay = 1000;
64 Runnable mUpdateRunnable = new Runnable() {
67 updateCompressionFactor();
72 private class Watcher implements TextWatcher {
73 private EditText mEditText;
74 Watcher(EditText text) {
79 public void beforeTextChanged(CharSequence s, int start, int count, int after) {
83 public void onTextChanged(CharSequence s, int start, int before, int count) {
87 public void afterTextChanged(Editable s) {
88 textChanged(mEditText);
93 public View onCreateView(LayoutInflater inflater, ViewGroup container,
94 Bundle savedInstanceState) {
95 mHandler = new Handler(getActivity().getMainLooper());
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);
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));
120 view.findViewById(R.id.cancel).setOnClickListener(this);
121 view.findViewById(R.id.done).setOnClickListener(this);
122 getDialog().setTitle(R.string.export_flattened);
124 updateCompressionFactor();
130 public void onStopTrackingTouch(SeekBar arg0) {
135 public void onStartTrackingTouch(SeekBar arg0) {
140 public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
141 mSeekVal.setText(mSliderLabel + arg1);
142 mQuality = mSeekBar.getProgress();
143 scheduleUpdateCompressionFactor();
146 private void scheduleUpdateCompressionFactor() {
147 mHandler.removeCallbacks(mUpdateRunnable);
148 mHandler.postDelayed(mUpdateRunnable, mUpdateDelay);
152 public void onClick(View v) {
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);
171 public void updateCompressionFactor() {
172 Bitmap bitmap = MasterImage.getImage().getFilteredImage();
173 if (bitmap == null) {
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());
182 public void updateSize() {
183 if (mCompressedBounds == null) {
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);
200 private void textChanged(EditText text) {
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);
217 width = (int) Math.ceil(mRatio);
218 mWidthText.setText("" + width);
220 height = (int) (width / mRatio);
222 mHeightText.setText("" + height);
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);
235 mHeightText.setText("" + height);
237 width = (int) (height * mRatio);
239 mWidthText.setText("" + width);
242 mExportWidth = width;
243 mExportHeight = height;