Android Open Source - Android-Image-Edit Viewer






From Project

Back to project page Android-Image-Edit.

License

The source code is released under:

MIT License

If you think the Android project Android-Image-Edit listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.owleyes.moustache;
/*ww  w. j  a v  a2 s  .  c  om*/
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.Sanselan;
import org.apache.sanselan.formats.jpeg.JpegImageMetadata;
import org.apache.sanselan.formats.tiff.TiffImageMetadata;
import org.apache.sanselan.formats.tiff.constants.ExifTagConstants;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Matrix;
import android.media.MediaScannerConnection;
import android.media.MediaScannerConnection.MediaScannerConnectionClient;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.provider.MediaStore;
import android.provider.MediaStore.Images;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;
import android.widget.ToggleButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageView.ScaleType;
import android.widget.RelativeLayout.LayoutParams;

import com.google.ads.AdRequest;
import com.google.ads.AdSize;
import com.google.ads.AdView;

public class Viewer extends Activity implements OnCheckedChangeListener {

    private static final String SEE_WARNING = "warning";

    private static final String PREF_KEY_DELETE = "_to_delete";

    private static final String CHECKED = "ignored_warning";

    public static final int SCALE = 0;

    public static final int ROTATE = 1;

    public static final int MINUS = 2;

    public static final int PLUS = 3;

    /** The list of drawable resource ids. */
    private static final int[] imageList = { R.drawable.one, R.drawable.two, R.drawable.three, R.drawable.four, R.drawable.five, R.drawable.six, R.drawable.seven, R.drawable.eight, R.drawable.nine,
            R.drawable.ten, R.drawable.eleven };

    /** The Linear Layout that contains all other elements. */
    private LinearLayout root_layout;

    /** ViewGroup to which we add moustaches. */
    private LinearLayout mMoustacheGroup;

    /** The picture being viewed. */
    private ImageView mCurrentPicture;

    /** The Horizontal Scrollbar we use to display the images we can add. */
    private FrameLayout mHorizontalScroll;

    /** The RelativeLayout for the Scrollbar. */
    private CustomRelativeLayout mRelative;

    /** The remove button. */
    private ImageView mRemove;

    /** The save button. */
    private Button mSave;

    /** Shared Preferences for this app. */
    private SharedPreferences mPreferences;

    /** The mode. Either Scaling or Rotating. */
    private ToggleButton mMode;

    private static final int MODE_ID = 10;

    /** The minus button or counterclockwise rotate. */
    private Button mMinus;

    private static final int MINUS_ID = 15;

    /** The plus button or clockwise rotate. */
    private Button mPlus;

    private static final int PLUS_ID = 20;

    /** The state of the current Viewer -- either rotate or scale. */
    private int mState;

    /** Handles holding down either the plus or minus buttons. */
    private Handler mHandler;

    /** The Thread to update the image in. */
    private UpdateImage _updateImageTask;

    /** The orientation of the image we are viewing. */
    private int mOrientation;

    /** Changes from rotate to scale mode. */
    private MenuItem switchButton;

    private AdView mAdView;

    private RelativeLayout mControls;

    private static final int REMOVE_ID = 30;

    private static final int SAVE_ID = 25;

    private static final int SCROLL_VIEW_SIZE = 105;

    /**
     * Depending on the orientation, this is the amount of screen space taken up
     * by the options -- the ScrollView and buttons.
     */
    private static final int OPTIONS_SIZE = 170;

    private static final String MY_IDENTIFIER = "Made with Moustache Madness!";
    private static final String MY_AD_ID = "a14f4c7839ee239";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    private void basicInit(int orientation) {
        root_layout = (LinearLayout) findViewById(R.id.root);
        root_layout.setBackgroundColor(15921906);

        mRelative = new CustomRelativeLayout(this);
        mRelative.setBackgroundColor(Color.rgb(242, 242, 242));

        LayoutParams fill = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
        LayoutParams wrap = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        mRelative.setLayoutParams(fill);
        root_layout.addView(mRelative);

        mAdView = new AdView(this, AdSize.BANNER, MY_AD_ID);

        AdRequest request = new AdRequest();
        request.addTestDevice("45A2D3C16C738A08425D22872911765E");
        mAdView.setLayoutParams(wrap);

        mAdView.setMinimumHeight(AdSize.BANNER.getHeight());
        mAdView.setMinimumWidth(AdSize.BANNER.getWidth());
        mAdView.setId(150);
        mRelative.addView(mAdView);
        mAdView.loadAd(request);
        mCurrentPicture = new ImageView(this);

        mCurrentPicture.setScaleType(ScaleType.CENTER_CROP);
        LayoutParams picParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        picParams.addRule(RelativeLayout.BELOW, 150);
        Display d = this.getWindowManager().getDefaultDisplay();
        int widthy = d.getWidth();
        int heighty = d.getHeight();
        if (orientation == Configuration.ORIENTATION_PORTRAIT) {
            picParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
            mCurrentPicture.setMaxHeight(heighty - AdSize.BANNER.getHeight() - OPTIONS_SIZE);
            mCurrentPicture.setMaxWidth(widthy);
        } else {
            mCurrentPicture.setMaxHeight(heighty - AdSize.BANNER.getHeight());
            mCurrentPicture.setMaxWidth(widthy - OPTIONS_SIZE);
        }

        mCurrentPicture.setLayoutParams(picParams);

        mControls = new RelativeLayout(this);

        LayoutParams controlParams = null;
        if (orientation == Configuration.ORIENTATION_PORTRAIT) {
            Log.e("Max height: ", (OPTIONS_SIZE - SCROLL_VIEW_SIZE) + "");
            controlParams = new LayoutParams(LayoutParams.FILL_PARENT, OPTIONS_SIZE - SCROLL_VIEW_SIZE);
            controlParams.bottomMargin = 10;
            controlParams.addRule(RelativeLayout.ABOVE, 1);
        } else {
            controlParams = new LayoutParams(OPTIONS_SIZE - SCROLL_VIEW_SIZE, LayoutParams.FILL_PARENT);
            controlParams.rightMargin = 10;
            // mControls.setOrientation(LinearLayout.VERTICAL);
            controlParams.addRule(RelativeLayout.LEFT_OF, 1);
        }
        // mControls.setPadding(0, 0, 0, -10)
        mControls.setMinimumHeight(55);
        mControls.setLayoutParams(controlParams);
        mRelative.addView(mControls);
        mRelative.addView(mCurrentPicture);
        mRelative.setEditable(mCurrentPicture);
    }

    /**
     * Populates the LienarLayout VG with the image resources from IMAGELIST.
     */
    private void addDraggableImages() {
        int counter = 0;
        mMoustacheGroup.setId(200);
        for (int i : imageList) {
            CustomImageView temp = new CustomImageView(this);
            temp.setImageResource(i);
            temp.setId(counter);
            counter++;
            mMoustacheGroup.addView(temp, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
        }
    }

    /**
     * Adds the image specified by the Uri IMAGEURI to the current view.
     * 
     */
    private void addImage(Uri imageURI) {
        String[] filePathColumn = { MediaStore.Images.Media.DATA, MediaStore.Images.Media.DESCRIPTION };
        Cursor cursor = getContentResolver().query(imageURI, filePathColumn, null, null, null);
        cursor.moveToFirst();

        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        int descInd = cursor.getColumnIndex(filePathColumn[1]);
        if (cursor.getString(descInd) != null && cursor.getString(descInd).equals(MY_IDENTIFIER)) {
            try {
                Bitmap b = android.provider.MediaStore.Images.Media.getBitmap(getContentResolver(), imageURI);
                if (b != null) {
                    mCurrentPicture.setImageBitmap(b);
                    mCurrentPicture.invalidate();
                    return;
                }
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        String filePath = cursor.getString(columnIndex);
        cursor.close();
        mCurrentPicture.setImageBitmap(this.setUpPicture(filePath));

        mCurrentPicture.invalidate();
    }

    /**
     * Called by the constructor to set up the views. Because we need to keep
     * track of a lot of the View elements, its easier for us to inflate each
     * View in the Class rather than in the XML. This is where that happens.
     */
    private void init(LayoutParams removeLP, android.widget.LinearLayout.LayoutParams minusLP, android.widget.LinearLayout.LayoutParams modeLP, android.widget.LinearLayout.LayoutParams plusLP,
            LayoutParams saveLP, boolean portrait) {

        mRemove = new ImageView(this);
        mRemove.setLayoutParams(removeLP);
        mRemove.setImageResource(R.drawable.trash1);
        mRemove.setId(REMOVE_ID);
        mRelative.setTrashIcon(mRemove);
        mRemove.setMaxHeight(Viewer.OPTIONS_SIZE - Viewer.SCROLL_VIEW_SIZE);
        if (portrait) {
            mRemove.setPadding(0, 0, (int) getResources().getDimension(R.dimen.five), 0);
        } else {
            mRemove.setPadding(0, 0, 0, (int) getResources().getDimension(R.dimen.five));
        }
        mRemove.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                mRelative.removeView(mRelative.getSelectedImage());
            }
        });

        mMinus = createButton(R.drawable.minus, minusLP, MINUS_ID);
        mMinus.setText("");
        mMinus.setMaxHeight(Viewer.OPTIONS_SIZE - Viewer.SCROLL_VIEW_SIZE);
        mMinus.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                _updateImageTask.setState(mState, Viewer.MINUS);
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        // if (mState == Viewer.SCALE) {
                        // mMinus.setBackgroundResource(R.drawable.minus2);
                        // } else {
                        // mMinus.setBackgroundResource(R.drawable.ctr_clk2);
                        // }
                        currentTime = System.currentTimeMillis();
                        mHandler.removeCallbacks(_updateImageTask);
                        mHandler.postDelayed(_updateImageTask, 30);
                        return true;
                    case MotionEvent.ACTION_OUTSIDE:
                        // if (mState == Viewer.SCALE) {
                        // mMinus.setBackgroundResource(R.drawable.minus_pressed);
                        // } else {
                        // mMinus.setBackgroundResource(R.drawable.ctr_clk_pressed);
                        // }
                        mHandler.removeCallbacks(_updateImageTask);
                        return true;
                    case MotionEvent.ACTION_UP:
                        // if (mState == Viewer.SCALE) {
                        // mMinus.setBackgroundResource(R.drawable.minus_pressed);
                        // } else {
                        // mMinus.setBackgroundResource(R.drawable.ctr_clk_pressed);
                        // }
                        if (System.currentTimeMillis() - currentTime < 200) {
                            mRelative.handleEvent(mState, -3);
                        }
                        mHandler.removeCallbacks(_updateImageTask);
                        return true;
                }

                return true;
            }

            private long currentTime;
        });

        mPlus = createButton(R.drawable.plus, plusLP, PLUS_ID);
        mPlus.setText("");
        mPlus.setMaxHeight(Viewer.OPTIONS_SIZE - Viewer.SCROLL_VIEW_SIZE);
        mPlus.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                _updateImageTask.setState(mState, Viewer.PLUS);
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        // if (mState == Viewer.SCALE) {
                        // mPlus.setBackgroundResource(R.drawable.plus2);
                        // } else {
                        // mPlus.setBackgroundResource(R.drawable.clk2);
                        // }
                        currentTime = System.currentTimeMillis();
                        mHandler.removeCallbacks(_updateImageTask);
                        mHandler.postDelayed(_updateImageTask, 30);
                        return true;
                    case MotionEvent.ACTION_OUTSIDE:
                        // if (mState == Viewer.SCALE) {
                        // mPlus.setBackgroundResource(R.drawable.plus_pressed);
                        // } else {
                        // mPlus.setBackgroundResource(R.drawable.clk_pressed);
                        // }
                        mHandler.removeCallbacks(_updateImageTask);
                        return true;
                    case MotionEvent.ACTION_UP:
                        // if (mState == Viewer.SCALE) {
                        // mPlus.setBackgroundResource(R.drawable.plus_pressed);
                        // } else {
                        // mPlus.setBackgroundResource(R.drawable.clk_pressed);
                        // }
                        if (System.currentTimeMillis() - currentTime < 200) {
                            mRelative.handleEvent(mState, 3);
                        }
                        mHandler.removeCallbacks(_updateImageTask);
                        return true;
                }
                return true;
            }

            private long currentTime;
        });
        mMode = new ToggleButton(this);
        if (portrait) {
            mMode.setPadding(0, 0, 0, 0);
        }
        mMode.setMaxHeight(Viewer.OPTIONS_SIZE - Viewer.SCROLL_VIEW_SIZE);
        mMode.setLayoutParams(modeLP);
        mMode.setBackgroundResource(R.drawable.rotate_switch);
        mMode.setTextOff("");
        mMode.setTextOn("");
        mMode.setChecked(true);
        mMode.setId(MODE_ID);
        mMode.setOnCheckedChangeListener(this);

        mState = SCALE;

        mSave = new Button(this);
        mSave.setBackgroundResource(R.drawable.save);
        mSave.setLayoutParams(saveLP);
        mSave.setId(SAVE_ID);
        mSave.setMaxHeight(Viewer.OPTIONS_SIZE - Viewer.SCROLL_VIEW_SIZE);
        mSave.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                CustomImageView view = (CustomImageView) mRelative.getSelectedImage();
                mRelative.removeAllSelected();
                mRelative.setDrawingCacheEnabled(true);
                Bitmap b = mRelative.getDrawingCache();
                final Bitmap cropped = Bitmap.createBitmap(b, mCurrentPicture.getLeft(), mCurrentPicture.getTop(), mCurrentPicture.getWidth(), mCurrentPicture.getHeight());
                mRelative.setDragging(view);

                String warning = mPreferences.getString(SEE_WARNING, "not_set");
                if (!warning.equals(CHECKED)) {
                    AlertDialog.Builder alert = new AlertDialog.Builder(Viewer.this);
                    LayoutInflater inflater = Viewer.this.getLayoutInflater();
                    View dialog = inflater.inflate(R.layout.save_location_warning, null);
                    alert.setView(dialog);
                    final CheckBox cb = (CheckBox) dialog.findViewById(R.id.ignore_warning);

                    alert.setNeutralButton("Okay", new Dialog.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            if (cb.isChecked()) {
                                Editor edit = Viewer.this.mPreferences.edit();
                                edit.putString(SEE_WARNING, CHECKED);
                                edit.commit();
                            }
                            if (saveInternal(cropped) != null) {
                                Toast.makeText(Viewer.this, "Saved Successfully", 1000).show();
                            } else {
                                Toast.makeText(Viewer.this, "Save Failed", 1000).show();
                            }
                        }
                    });
                    alert.create().show();
                } else {
                    if (saveInternal(cropped) != null) {
                        Toast.makeText(Viewer.this, "Saved Successfully", 1000).show();
                    } else {
                        Toast.makeText(Viewer.this, "Save Failed", 1000).show();
                    }
                }
                mCurrentPicture.setDrawingCacheEnabled(false);

            }
        });

        mMoustacheGroup = new LinearLayout(this);

        if (portrait) {
            mHorizontalScroll = new CustomHorizontalScrollView(this);
        } else {
            mHorizontalScroll = new CustomScrollView(this);
        }
        mHorizontalScroll.setId(1);
        LayoutParams lp = null;
        if (portrait) {
            lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
            lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        } else {
            lp = new LayoutParams(100, LayoutParams.FILL_PARENT);
            lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
        }
        // mHorizontalScroll.setBackgroundColor(Color.rgb(242, 242, 242));
        mHorizontalScroll.setLayoutParams(lp);
        mRelative.addView(mHorizontalScroll);

        mMoustacheGroup.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
        if (!portrait) {
            mMoustacheGroup.setOrientation(LinearLayout.VERTICAL);
        }
        mHorizontalScroll.addView(mMoustacheGroup);
    }

    private void initPortrait() {
        Resources res = getResources();
        LayoutParams removeLP = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        removeLP.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
        removeLP.leftMargin = (int) res.getDimension(R.dimen.three);

        LinearLayout.LayoutParams minusLP = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        minusLP.rightMargin = (int) res.getDimension(R.dimen.five);

        LinearLayout.LayoutParams plusLP = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        plusLP.leftMargin = (int) res.getDimension(R.dimen.five);

        LinearLayout.LayoutParams modeLP = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);

        LayoutParams saveLP = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        saveLP.rightMargin = (int) res.getDimension(R.dimen.three);
        saveLP.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);

        LinearLayout layout = new LinearLayout(this);
        LayoutParams layoutLP = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        layoutLP.addRule(RelativeLayout.CENTER_HORIZONTAL);
        layout.setLayoutParams(layoutLP);

        init(removeLP, minusLP, modeLP, plusLP, saveLP, true);

        layout.addView(mMinus);
        layout.addView(mMode);
        layout.addView(mPlus);
        mControls.addView(mRemove);
        mControls.addView(layout);

        mControls.addView(mSave);
    }

    private void initLandscape() {
        Resources res = getResources();
        LayoutParams removeLP = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        // removeLP.rightMargin = (int) res.getDimension(R.dimen.two);
        removeLP.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);

        LinearLayout.LayoutParams minusLP = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        minusLP.topMargin = (int) res.getDimensionPixelOffset(R.dimen.five);

        LinearLayout.LayoutParams plusLP = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        plusLP.bottomMargin = (int) res.getDimensionPixelOffset(R.dimen.five);

        LinearLayout.LayoutParams modeLP = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);

        LayoutParams saveLP = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        saveLP.addRule(RelativeLayout.ALIGN_PARENT_TOP);

        LinearLayout layout = new LinearLayout(this);
        LayoutParams layoutLP = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        layoutLP.addRule(RelativeLayout.CENTER_VERTICAL);
        layout.setLayoutParams(layoutLP);
        layout.setOrientation(LinearLayout.VERTICAL);

        init(removeLP, minusLP, modeLP, plusLP, saveLP, false);

        layout.addView(mPlus);
        layout.addView(mMode);
        layout.addView(mMinus);

        mControls.addView(mRemove);
        mControls.addView(layout);
        mControls.addView(mSave);

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mCurrentPicture = null;
        mMoustacheGroup = null;
    }

    @Override
    protected void onResume() {
        super.onResume();

        mHandler = new Handler();

        mPreferences = this.getSharedPreferences(Main.PREFS_FILE, 0);
        setContentView(R.layout.nothing);

        // Inflate all the views.
        int orientation = getResources().getConfiguration().orientation;
        basicInit(orientation);
        if (orientation == Configuration.ORIENTATION_PORTRAIT) {
            initPortrait();

        } else {
            initLandscape();
        }

        Intent intent = getIntent();
        Uri imageURI = null;
        Log.e("URI:", intent.getData() + "");
        if (intent.getAction() != null && intent.getAction().equals(Intent.ACTION_SEND)) {
            Bundle extras = intent.getExtras();
            if (extras.containsKey(Intent.EXTRA_STREAM)) {
                imageURI = (Uri) extras.getParcelable(Intent.EXTRA_STREAM);
            }
        } else if (intent.getAction() != null && intent.getAction().equals(Intent.ACTION_VIEW)) {
            imageURI = intent.getData();
        } else {
            imageURI = (Uri) intent.getParcelableExtra("image");
        }

        addImage(imageURI);

        addDraggableImages();

        _updateImageTask = new UpdateImage(mRelative, mHandler);

        /*
         * Set<String> strings = new HashSet<String>(); strings =
         * mPreferences.getStringSet(PREF_KEY_DELETE, strings); if
         * (!strings.isEmpty()) { Iterator<String> itr = strings.iterator();
         * while (itr.hasNext()) { new File(itr.next()).delete(); } }
         */
    }

    /**
     * This function takes a filepath as a parameter and returns the
     * corresponding image, correctly scaled and rotated (if necessary)
     * 
     * @param filePath
     *            The filepath of the image
     * @return the scaled and rotated bitmap
     */
    private Bitmap setUpPicture(String filePath) {

        int w = 512;
        int h = 384; // size that does not lead to OutOfMemoryException on Nexus
        // One
        Bitmap b = BitmapFactory.decodeFile(filePath);

        // Hack to determine whether the image is rotated
        boolean rotated = b.getWidth() > b.getHeight();

        Bitmap resultBmp = null;

        // If not rotated, just scale it
        int degree;
        if ((mOrientation = degreeRotated(filePath)) == 0) {
            resultBmp = Bitmap.createScaledBitmap(b, w, h, true);
            b.recycle();
            b = null;
            // If rotated, scale it by switching width and height and then
            // rotated it
        } else {
            Bitmap scaledBmp = Bitmap.createScaledBitmap(b, w, h, true);
            b.recycle();
            b = null;
            Matrix mat = new Matrix();
            mat.postRotate(mOrientation);
            resultBmp = Bitmap.createBitmap(scaledBmp, 0, 0, w, h, mat, true);

            // Release image resources
            scaledBmp.recycle();
            scaledBmp = null;
        }
        return resultBmp;
    }

    /**
     * RETURNS the number of degrees the image specified by FILEPATH is rotate
     * (i.e. what degree rotation the phone was at while taking the picture.
     * 
     */
    private int degreeRotated(String filePath) {
        try {
            JpegImageMetadata meta = ((JpegImageMetadata) Sanselan.getMetadata(new File(filePath)));
            TiffImageMetadata data = null;
            if (meta != null) {
                data = meta.getExif();
            }
            int orientation = 0;
            if (data != null) {
                orientation = data.findField(ExifTagConstants.EXIF_TAG_ORIENTATION).getIntValue();
            } else {
                String[] projection = { Images.ImageColumns.ORIENTATION };
                Cursor c = getContentResolver().query(Uri.fromFile(new File(filePath)), projection, null, null, null);

                if (c != null && c.moveToFirst()) {
                    orientation = c.getInt(0);
                }
            }
            switch (orientation) {
                case 6:
                    return 90;
                case 8:
                    return 270;
                default:
                    return 0;

            }
            /*
             * } catch (JpegProcessingException e1) { e1.printStackTrace(); }
             * catch (MetadataException e) { e.printStackTrace(); }
             */} catch (ImageReadException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return 0;
    }

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        if (isChecked) {
            /* Scale mode */
            mMinus.setBackgroundResource(R.drawable.minus);
            mPlus.setBackgroundResource(R.drawable.plus);
            mMode.setBackgroundResource(R.drawable.rotate_switch);
            mState = SCALE;
        } else {
            /* Rotate mode */
            mMinus.setBackgroundResource(R.drawable.ctr_clk);
            mPlus.setBackgroundResource(R.drawable.clk);
            mMode.setBackgroundResource(R.drawable.scale_switch);
            mState = ROTATE;
        }

    }

    private Button createButton(int resource, android.widget.LinearLayout.LayoutParams minusLP, int id) {
        Button button = new Button(this);
        button.setBackgroundResource(resource);
        button.setLayoutParams(minusLP);
        button.setId(id);
        return button;
    }

    private String saveInternal(Bitmap image) {
        // String save = null; // =
        Log.e("HEIGHT OF SCROLLVIEW", this.mHorizontalScroll.getHeight() + "");
        Uri uri = Uri.parse(android.provider.MediaStore.Images.Media.insertImage(Viewer.this.getContentResolver(), image, null, null));
        String save = this.getRealPathFromURI(uri);

        Log.v("Moustache_Madness", "Save path: " + save);
        Toast.makeText(this, save, 2000);

        ContentValues cv = new ContentValues();

        cv.put(android.provider.MediaStore.Images.Media.ORIENTATION, mOrientation);
        cv.put(android.provider.MediaStore.Images.Media.DESCRIPTION, Viewer.MY_IDENTIFIER);
        int numRows = this.getContentResolver().update(uri, cv, null, null);

        Log.v("Moustache Madness", numRows + " rows were updated");
        if (save == null) {
            Log.e("Moustache Madness", "Save failed");
            Toast.makeText(this, "Save failed", 2000);
            return null;
        }
        MediaScannerConnection msc = null;
        MyScannerClient client = new MyScannerClient(save);
        msc = new MediaScannerConnection(Viewer.this, client);
        client.setScanner(msc);

        msc.connect();
        // }
        return save;
    }

    private String getRealPathFromURI(Uri contentUri) {
        String[] proj = { MediaStore.Images.Media.DATA };
        Cursor cursor = managedQuery(contentUri, proj, null, null, null);
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        switchButton = (MenuItem) menu.findItem(R.id.switch_mode);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.share:
                Intent sharingIntent = new Intent(Intent.ACTION_SEND);
                CustomImageView view = (CustomImageView) mRelative.getSelectedImage();
                mRelative.removeAllSelected();
                mRelative.setDrawingCacheEnabled(true);
                Bitmap b = mRelative.getDrawingCache();
                final Bitmap cropped = Bitmap.createBitmap(b, mCurrentPicture.getLeft(), mCurrentPicture.getTop(), mCurrentPicture.getWidth(), mCurrentPicture.getHeight());
                mRelative.setDragging(view);

                String path = saveInternal(cropped);
                if (path == null) {
                    // error
                    return true;
                }
                sharingIntent.setType("image/png");
                sharingIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(path)));
                startActivity(Intent.createChooser(sharingIntent, "Share image using"));
                /*
                 * Editor editor = mPreferences.edit(); Set<String> strings =
                 * new HashSet<String>(); strings =
                 * mPreferences.getStringSet(PREF_KEY_DELETE, strings);
                 * strings.add(path); editor.putStringSet(PREF_KEY_DELETE,
                 * strings);
                 */

                break;
            case R.id.switch_mode:
                if (mState == ROTATE) {
                    /* Scale mode */
                    mMinus.setBackgroundResource(R.drawable.minus);
                    mPlus.setBackgroundResource(R.drawable.plus);
                    mMode.setBackgroundResource(R.drawable.rotate_switch);
                    mState = SCALE;
                } else {
                    /* Rotate mode */
                    mMinus.setBackgroundResource(R.drawable.ctr_clk);
                    mPlus.setBackgroundResource(R.drawable.clk);
                    mMode.setBackgroundResource(R.drawable.scale_switch);
                    mState = ROTATE;
                }
        }
        return true;
    }

    private static class MyScannerClient implements MediaScannerConnectionClient {
        private MediaScannerConnection _msc;
        private String _file;

        public MyScannerClient(String file) {
            _file = file;
        }

        public void setScanner(MediaScannerConnection msc) {
            _msc = msc;
        }

        @Override
        public void onMediaScannerConnected() {
            _msc.scanFile(_file, "*/*");
        }

        @Override
        public void onScanCompleted(String path, Uri uri) {

        }

    }
}




Java Source Code List

com.owleyes.moustache.CustomHorizontalScrollView.java
com.owleyes.moustache.CustomImageView.java
com.owleyes.moustache.CustomRelativeLayout.java
com.owleyes.moustache.CustomScrollView.java
com.owleyes.moustache.Main.java
com.owleyes.moustache.UpdateImage.java
com.owleyes.moustache.Viewer.java