1

在我产生图像效果的android应用程序中,在选择图像时,有以下两个选项:

1) 从图库中选择

2) 从您的相机中拍摄

以下是完成上述任务的代码:

String imagePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" +  System.currentTimeMillis() + "_ePixels.jpg";
File imageFile = new File(imagePath);
imageUri = Uri.fromFile(imageFile);



public void onClick(View clickedView) {

    int clickedViewId = clickedView.getId();

    switch(clickedViewId) {
        case R.id.takeFromCamera:
            Intent imageCaptureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
            imageCaptureIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, imageUri);
            startActivityForResult(imageCaptureIntent,1888);
            break;
        case R.id.chooseFromGallery:
            Intent choosePictureIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            startActivityForResult(choosePictureIntent, 1);
            break;
        default:
            // As we have only two buttons, and nothing else can be clicked except the buttons. So no need to put
            // code in the "DEFAULT CASE"
    }
}

// Using one onActivityResult() for both calls and using a switch statement to differentiate what was called for actually!

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    super.onActivityResult(requestCode, resultCode, intent);

    switch(requestCode) {
        case 1888:
            if(resultCode == RESULT_OK) {
                // Success, when user actually took a photo and camera returned back it to us!
                Intent cameraIntent = new Intent(MainOptionsActivity.this,ApplyEffectsActivity.class);
                cameraIntent.putExtra("imageFileUri", imageUri);
                startActivity(cameraIntent);
            } else if(resultCode == RESULT_CANCELED){
                // Failure, Activity couldn't receive the photo captured by the camera
                Toast.makeText(MainOptionsActivity.this, "You didn't capture a photo!", Toast.LENGTH_LONG).show();
            }
            break;
        case 1:
            if(resultCode == RESULT_OK) {
                // Success, Activity received the image from gallery
                Uri imageUriForGallery = intent.getData();
                Intent galleryIntent = new Intent(MainOptionsActivity.this,ApplyEffectsActivity.class);
                galleryIntent.putExtra("imageFileUri", imageUriForGallery);
                startActivity(galleryIntent);
            } else if(resultCode == RESULT_CANCELED) {
                // Failure, Gallery didn't send an image
                Toast.makeText(MainOptionsActivity.this, "You didn't select an image", Toast.LENGTH_LONG).show();
            }
            break;
    }

}

它工作得很好。但是当我尝试加载一些重图像或在相机具有高分辨率的手机上运行我的应用程序时 android 会给我 ANR 错误,这显然是由于主线程上的繁重工作。

显然,解决这个问题的方法是在一个单独的线程上完成所有繁重的工作。但是怎么做呢?我无法找到解决方案。我不是在问您如何在单独的线程上运行代码,而是在调用另一个活动并从该活动中获得结果时如何在单独的线程上运行此代码。

以下是 ApplyEffectsActivity 的代码:

package com.arslanali.epixels;


import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.arslanali.epixels.imagelibrary.ImageEffectFactory;

public class ApplyEffectsActivity extends Activity implements OnClickListener{

ImageView sepiaGreenishImage;
ImageView embossImage;
ImageView sharpenImage;
ImageView slightYellowishImage;
ImageView slightBluishImage;
ImageView slightReddishImage;
ImageView slightGreenishImage;
ImageView negativeImage;
ImageView greyScaleImage;
ImageView tintSeventyImage;
ImageView tintThirtyImage;
ImageView snowImage;
ImageView darkImage;
ImageView noiseImage;
ImageView flipImage;
ImageView rotateImage;
ImageView gaussianBlurImage;
ImageView reddishImage;
ImageView bluishImage;
ImageView greenishImage;
ImageView blackFilterImage;
ImageView increasedSepiaImage;
ImageView spiaBluishImage;
ImageView brightImage;
ImageView mirrorImage;


Button nextButton;
Button saveCurrentEditedImageButton;

// For displaying the image after modification
ImageView affectedImageView;

ProgressBar waitingProgressBar;

Bitmap sourceBitmap;
Bitmap modifiedBitmap;

// For sending it to next activity for the sharing purposes
Uri modifiedImgaeUri;

// Since, In beginning, we are dealing with the raw image
Boolean isEdited = false;

EffectNames currentEffectName;

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

    setContentView(R.layout.activity_apply_effects);
    // Restricting the user to use mobile phone only in portrait mode
    setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

    // Grabbing the references of all the images
    sepiaGreenishImage      = (ImageView) findViewById(R.id.sepiaGreenish);
    embossImage             = (ImageView) findViewById(R.id.emboss);
    sharpenImage            = (ImageView) findViewById(R.id.sharpen);
    slightYellowishImage    = (ImageView) findViewById(R.id.ligth_yellow);
    slightBluishImage       = (ImageView) findViewById(R.id.light_blue);
    slightReddishImage      = (ImageView) findViewById(R.id.light_red);
    slightGreenishImage     = (ImageView) findViewById(R.id.light_green);
    negativeImage           = (ImageView) findViewById(R.id.negative);
    greyScaleImage          = (ImageView) findViewById(R.id.greyscale);
    tintSeventyImage        = (ImageView) findViewById(R.id.tint_at_70);
    tintThirtyImage         = (ImageView) findViewById(R.id.tint_at_30);
    snowImage               = (ImageView) findViewById(R.id.snow);
    darkImage               = (ImageView) findViewById(R.id.darken);
    noiseImage              = (ImageView) findViewById(R.id.noise);
    flipImage               = (ImageView) findViewById(R.id.flip);
    rotateImage             = (ImageView) findViewById(R.id.rotate);
    gaussianBlurImage       = (ImageView) findViewById(R.id.blur);
    reddishImage            = (ImageView) findViewById(R.id.reddish);
    bluishImage             = (ImageView) findViewById(R.id.bluish);
    greenishImage           = (ImageView) findViewById(R.id.greenish);
    blackFilterImage        = (ImageView) findViewById(R.id.black_filter);
    increasedSepiaImage     = (ImageView) findViewById(R.id.increased_sepia);
    spiaBluishImage         = (ImageView) findViewById(R.id.sepia_bluish);
    brightImage             = (ImageView) findViewById(R.id.brighten);
    mirrorImage             = (ImageView) findViewById(R.id.mirror);






    nextButton = (Button) findViewById(R.id.share);
    saveCurrentEditedImageButton = (Button) findViewById(R.id.saveit);

    affectedImageView = (ImageView) findViewById(R.id.affectedImage);
    waitingProgressBar =  (ProgressBar) findViewById(R.id.progressBar1);

    // Since, at the start we are displaying the image. So ProgressBar should be invisible
    waitingProgressBar.setVisibility(ProgressBar.INVISIBLE);

    nextButton.setOnClickListener(this);
    saveCurrentEditedImageButton.setOnClickListener(this);

    sepiaGreenishImage.setOnClickListener(this);
    embossImage.setOnClickListener(this);
    sharpenImage.setOnClickListener(this);
    slightYellowishImage.setOnClickListener(this);
    slightBluishImage.setOnClickListener(this);
    slightReddishImage.setOnClickListener(this);
    slightGreenishImage.setOnClickListener(this);
    negativeImage.setOnClickListener(this);
    greyScaleImage.setOnClickListener(this);
    tintSeventyImage.setOnClickListener(this);
    tintThirtyImage.setOnClickListener(this);
    snowImage.setOnClickListener(this);
    darkImage.setOnClickListener(this);
    noiseImage.setOnClickListener(this);
    flipImage.setOnClickListener(this);
    rotateImage.setOnClickListener(this);
    gaussianBlurImage.setOnClickListener(this);
    reddishImage.setOnClickListener(this);
    bluishImage.setOnClickListener(this);
    greenishImage.setOnClickListener(this);
    blackFilterImage.setOnClickListener(this);
    increasedSepiaImage.setOnClickListener(this);
    spiaBluishImage.setOnClickListener(this);
    brightImage.setOnClickListener(this);
    mirrorImage.setOnClickListener(this);


    // Grabbing the Uri from the previous calling activity
    Uri imageUri = (Uri) getIntent().getExtras().getParcelable("imageFileUri");

    try {
        sourceBitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
        affectedImageView.setImageBitmap(sourceBitmap);


    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

}



@Override
public boolean onCreateOptionsMenu(Menu menu) {

    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}


// Using a switch statement for all cases and storing the result in "currentEffectName"

@Override
public void onClick(View clickedView) {
    int clickedViewId = clickedView.getId();

    switch(clickedViewId) {
        case R.id.sepiaGreenish:
            currentEffectName = EffectNames.SEPIA_GREEN_EFFECT;
            ImageAffector sepia = new ImageAffector();
            sepia.execute(sourceBitmap);
            break;
        case R.id.emboss:
            currentEffectName = EffectNames.EMBOSSING_EFFECT;
            ImageAffector emboss = new ImageAffector();
            emboss.execute(sourceBitmap);
            break;
        case R.id.sharpen:
            currentEffectName = EffectNames.SHARPEN_EFFECT;
            ImageAffector sharpen = new ImageAffector();
            sharpen.execute(sourceBitmap);
            break;
        case R.id.ligth_yellow:
            currentEffectName = EffectNames.LIGHT_YELLOW_EFFECT;
            ImageAffector lightYellow = new ImageAffector();
            lightYellow.execute(sourceBitmap);
            break;
        case R.id.light_blue:
                currentEffectName = EffectNames.SLIGHT_BLUISH_EFFECT;
                ImageAffector lightBlue = new ImageAffector();
                lightBlue.execute(sourceBitmap);
            break;
        case R.id.light_red:
            currentEffectName = EffectNames.SLIGHT_REDDISH_EFFECT;
            ImageAffector lightRed = new ImageAffector();
            lightRed.execute(sourceBitmap);
        break;
        case R.id.light_green:
            currentEffectName = EffectNames.SLIGHT_GREENISH_EFFECT;
            ImageAffector lightGreen = new ImageAffector();
            lightGreen.execute(sourceBitmap);
        break;
        case R.id.negative:
            currentEffectName = EffectNames.INVERT_EFFECT;
            ImageAffector negative = new ImageAffector();
            negative.execute(sourceBitmap);
        break;
        case R.id.greyscale:
            currentEffectName = EffectNames.GRAY_SCALE_EFFECT;
            ImageAffector greyScale = new ImageAffector();
            greyScale.execute(sourceBitmap);
        break;
        case R.id.tint_at_30:
            currentEffectName = EffectNames.TINT_AT_30;
            ImageAffector tintAt30 = new ImageAffector();
            tintAt30.execute(sourceBitmap);
        break;
        case R.id.tint_at_70:
            currentEffectName = EffectNames.TINT_AT_70;
            ImageAffector tintAt70 = new ImageAffector();
            tintAt70.execute(sourceBitmap);
        break;
        case R.id.snow:
            currentEffectName = EffectNames.SNOW_EFFECT;
            ImageAffector snowEffect = new ImageAffector();
            snowEffect.execute(sourceBitmap);
        break;
        case R.id.darken:
            currentEffectName = EffectNames.DARKEN_EFFECT;
            ImageAffector darken = new ImageAffector();
            darken.execute(sourceBitmap);
        break;
        case R.id.noise:
            currentEffectName = EffectNames.NOSIY_EFFECT;
            ImageAffector noise = new ImageAffector();
            noise.execute(sourceBitmap);
        break;
        case R.id.flip:
            currentEffectName = EffectNames.FLIPPING_EFFECT;
            ImageAffector flip = new ImageAffector();
            flip.execute(sourceBitmap);
        break;
        case R.id.rotate:
            currentEffectName = EffectNames.ROTATE_EFFECT;
            ImageAffector rotate = new ImageAffector();
            rotate.execute(sourceBitmap);
        break;
        case R.id.blur:
            currentEffectName = EffectNames.BLUR_EFFECT;
            ImageAffector blur = new ImageAffector();
            blur.execute(sourceBitmap);
        break;
        case R.id.reddish:
            currentEffectName = EffectNames.REDDISH_EFFECT;
            ImageAffector reddish = new ImageAffector();
            reddish.execute(sourceBitmap);
        break;
        case R.id.bluish:
            currentEffectName = EffectNames.BLUISH_EFFECT;
            ImageAffector bluish = new ImageAffector();
            bluish.execute(sourceBitmap);
        break;
        case R.id.greenish:
            currentEffectName = EffectNames.GREENISH_EFFECT;
            ImageAffector greenish = new ImageAffector();
            greenish.execute(sourceBitmap);
        break;
        case R.id.black_filter:
            currentEffectName = EffectNames.BLACK_FILTER_EFFECT;
            ImageAffector blackFilter = new ImageAffector();
            blackFilter.execute(sourceBitmap);
        break;
        case R.id.increased_sepia:
            currentEffectName = EffectNames.INCREASED_SEPIA_EFFECT;
            ImageAffector increasedSepia = new ImageAffector();
            increasedSepia.execute(sourceBitmap);
        break;
        case R.id.sepia_bluish:
            currentEffectName = EffectNames.SEPIA_BLUE_EFFECT;
            ImageAffector sepiaBluish = new ImageAffector();
            sepiaBluish.execute(sourceBitmap);
        break;
        case R.id.brighten:
            currentEffectName = EffectNames.BRIGHTENING_EFFECT;
            ImageAffector brighten = new ImageAffector();
            brighten.execute(sourceBitmap);
        break;
        case R.id.mirror:
            currentEffectName = EffectNames.MIRROR_EFFECT;
            ImageAffector mirror = new ImageAffector();
            mirror.execute(sourceBitmap);
        break;
        case R.id.saveit:
            modifiedImgaeUri = saveEditedImageIntoSDCard(modifiedBitmap);
            Toast.makeText(this, "Saved!" , Toast.LENGTH_SHORT).show();
            isEdited = true;
            break;
        case R.id.share:
            // Making sure that user has applied at least one effect. Otherwise it will be useless 
            // to share the unmodified image with the use of app.
            if(!isEdited) {
                // If not modified, enforce the user to first modify and then share!
                Toast.makeText(this, "You didn't apply any effect", Toast.LENGTH_LONG).show();
                break;
            }
            Intent shareActivityIntent = new Intent(ApplyEffectsActivity.this, ShareActivity.class);
            shareActivityIntent.putExtra("modifiedImageUri", modifiedImgaeUri);
            startActivity(shareActivityIntent);
        break;
    }
}

public static Uri saveEditedImageIntoSDCard(Bitmap bitmap) {


    // Using PNG format over JPEG for better performance of the app
    String imageFilePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/ePixels_" + System.currentTimeMillis() + ".png";
    File imageFile = new File(imageFilePath);
    Uri modifiedImageUri = Uri.fromFile(imageFile);



    FileOutputStream outStream;
    try {

        outStream = new FileOutputStream(imageFile);
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream); 
        // Writing the image to outStream 


        outStream.flush();
        // Making sure nothing else could be written to file from any other source
        outStream.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }   
    return modifiedImageUri;
}

private class ImageAffector extends AsyncTask<Bitmap, Integer, Bitmap>{

    protected void onPreExecute(){
        // Since, image has gone into background for modification. Therefore hiding it and making
        // ProgressBar visible
        waitingProgressBar.setVisibility(ProgressBar.VISIBLE);
        affectedImageView.setVisibility(ImageView.INVISIBLE);
    }
    protected Bitmap doInBackground(Bitmap... bitmap) {
        try{

            switch(currentEffectName) {
                case SEPIA_GREEN_EFFECT:
                    modifiedBitmap = ImageEffectFactory.applySepiaEffectWithGreenAsMajority(bitmap[0]);
                    return modifiedBitmap;
                case EMBOSSING_EFFECT:
                    modifiedBitmap = ImageEffectFactory.embossAnImage(bitmap[0]);
                    return modifiedBitmap;
                case SHARPEN_EFFECT:
                    modifiedBitmap = ImageEffectFactory.sharpenAnImage(bitmap[0]);
                    return modifiedBitmap;
                case MIRROR_EFFECT:
                    modifiedBitmap = ImageEffectFactory.mirrorAnImage(bitmap[0]);
                    return modifiedBitmap;
                case LIGHT_YELLOW_EFFECT:
                    modifiedBitmap = ImageEffectFactory.produceSlightYellowishEffect(bitmap[0]);
                    return modifiedBitmap;
                case SLIGHT_REDDISH_EFFECT:
                    modifiedBitmap = ImageEffectFactory.produceSlightReddishEffect(bitmap[0]);
                    return modifiedBitmap;
                case SLIGHT_GREENISH_EFFECT:
                    modifiedBitmap = ImageEffectFactory.produceSlightGreenishEffect(bitmap[0]);
                    return modifiedBitmap;
                case SLIGHT_BLUISH_EFFECT:
                    modifiedBitmap = ImageEffectFactory.produceSlightBluishEffect(bitmap[0]);
                    return modifiedBitmap;
                case INVERT_EFFECT:
                    modifiedBitmap = ImageEffectFactory.invertAllPixels(bitmap[0]);
                    return modifiedBitmap;
                case GRAY_SCALE_EFFECT:
                    modifiedBitmap = ImageEffectFactory.turnIntoGrayScale(bitmap[0]);
                    return modifiedBitmap;
                case TINT_AT_30:
                    modifiedBitmap = ImageEffectFactory.tintImage(bitmap[0], 30);
                    return modifiedBitmap;
                case TINT_AT_70:
                    modifiedBitmap = ImageEffectFactory.tintImage(bitmap[0], 70);
                    return modifiedBitmap;
                case SNOW_EFFECT:
                    modifiedBitmap = ImageEffectFactory.applySnowEffect(bitmap[0]);
                    return modifiedBitmap;
                case DARKEN_EFFECT:
                    modifiedBitmap = ImageEffectFactory.darkenAnImage(bitmap[0]);
                    return modifiedBitmap;
                case NOSIY_EFFECT:
                    modifiedBitmap = ImageEffectFactory.applyNoiseEffect(bitmap[0]);
                    return modifiedBitmap;
                case FLIPPING_EFFECT:
                    modifiedBitmap = ImageEffectFactory.flipAnImage(bitmap[0]);
                    return modifiedBitmap;
                case ROTATE_EFFECT:
                    modifiedBitmap = ImageEffectFactory.rotateAnImage(bitmap[0]);
                    return modifiedBitmap;
                case BLUR_EFFECT:
                    modifiedBitmap = ImageEffectFactory.applyGaussainBlur(bitmap[0]);
                    return modifiedBitmap;
                case REDDISH_EFFECT:
                    modifiedBitmap = ImageEffectFactory.produceReddieshEffect(bitmap[0]);
                    return modifiedBitmap;
                case BLUISH_EFFECT:
                    modifiedBitmap = ImageEffectFactory.produceBluishEffect(bitmap[0]);
                    return modifiedBitmap;
                case GREENISH_EFFECT:
                    modifiedBitmap = ImageEffectFactory.produceGreenishEffect(bitmap[0]);
                    return modifiedBitmap;
                case BLACK_FILTER_EFFECT:
                    modifiedBitmap = ImageEffectFactory.applyBlackFilter(bitmap[0]);
                    return modifiedBitmap;
                case INCREASED_SEPIA_EFFECT:
                    modifiedBitmap = ImageEffectFactory.applyIncreasedSepiaEffect(bitmap[0]);
                    return modifiedBitmap;
                case SEPIA_BLUE_EFFECT:
                    modifiedBitmap = ImageEffectFactory.applySepiaEffectWithBlueAsMajority(bitmap[0]);
                    return modifiedBitmap;
                case BRIGHTENING_EFFECT:
                    modifiedBitmap = ImageEffectFactory.brigthenAnImage(bitmap[0]);
                    return modifiedBitmap;



            }

        }catch(Exception e){
            // For the reason: if the size of image is too large to load
            Toast.makeText(ApplyEffectsActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
            Log.e("Image","Failed to load image",e);
        }

        return null;
    } 

    protected void onPostExecute(Bitmap img){
            // After the modification of image, displaying it and hiding ProgressBar.
            waitingProgressBar.setVisibility(ProgressBar.INVISIBLE);
            affectedImageView.setVisibility(ImageView.VISIBLE);
            affectedImageView.setImageBitmap(img);
            // Setting it modifiedBitmap so that we could share it on next activity
            modifiedBitmap = img;
    }
    protected void onProgressUpdate(Integer... params){
         super.onProgressUpdate(params);
    }

    protected void onCancelled(){
    }
}

}

4

1 回答 1

1

用于AsyncTask完成您的繁重工作ApplyEffectsActivity。这一切都在文档中进行了解释。基本上,在方法中进行处理,在和函数doInBackground中进行所有的 UI 更新。onProgressUpdateonPostExecute

在 ApplyEffectsActivity 中,流程基本上是:

开始:

  1. 显示进度指示器
  2. 开始任务

在你的任务中:

  1. 在 doInBackground 中进行处理
  2. 在 onPostExecute 中隐藏进度指示器

编辑:

应该将什么移至任务:

    sourceBitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
    affectedImageView.setImageBitmap(sourceBitmap);

根据我的说法,您应该在 UI 中显示原始位图的缩小版本(节省内存)。然后您的任务将在此基础上运行,并在保存时将相同的效果设置应用于原始位图。

于 2013-05-05T15:08:48.440 回答