When saving bitmap to disk, solid paths show artifacts

♀尐吖头ヾ 提交于 2019-12-03 16:33:38
  1. I tested your program with PNG and the file has no artifacts
  2. These artifacts are a result of JPEG compression

Edit: The line

MediaStore.Images.Media.insertImage(context.getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName());

was causing the conversion to jpeg.

The proper way to save the image is

ContentValues values = new ContentValues();
values.put(Images.Media.DATE_TAKEN, System.currentTimeMillis());
values.put(Images.Media.MIME_TYPE, "image/png");
values.put(MediaStore.MediaColumns.DATA, file.getAbsolutePath());
context.getContentResolver().insert(Images.Media.EXTERNAL_CONTENT_URI, values);

Here is my simplified test program that sends the generated file directly

public class Test2Activity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    new saveBitmapToDisk().execute();
  }

  public Bitmap getBitmap() {
    final int bitmapHeight = 600, bitmapWidth = 600;
    Bitmap bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
    Canvas bitmapCanvas = new Canvas(bitmap);

    Paint solidPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    solidPaint.setStyle(Paint.Style.FILL);
    solidPaint.setColor(Color.RED);
    bitmapCanvas.drawCircle(300, 300, 200, solidPaint);

    return bitmap;
  }

  private class saveBitmapToDisk extends AsyncTask<Void, Void, Uri> {
    Boolean toShare;

    @Override
    protected Uri doInBackground(Void... shareFile) {
      Context context = Test2Activity.this;
      try {
        File file = new File(context.getExternalFilesDir(null), "test.png");
        FileOutputStream fOut = new FileOutputStream(file);

        Bitmap saveBitmap = getBitmap();
        saveBitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
        fOut.flush();
        fOut.close();
        return Uri.fromFile(file);
      } catch (OutOfMemoryError e) {
        Log.e("MainActivity", "Out of Memory saving bitmap; bitmap is too large");
        return null;
      } catch (Exception e) {
        Log.e("MainActivity", e.getMessage());
        return null;
      }

    }

    @Override
    protected void onPostExecute(Uri uri) {
      Context context = Test2Activity.this;
      Toast.makeText(context, "Image saved", Toast.LENGTH_SHORT).show();

      final Intent intent = new Intent(android.content.Intent.ACTION_SEND);
      intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      intent.putExtra(Intent.EXTRA_STREAM, uri);
      intent.setType("image/png");
      Test2Activity.this.startActivity(intent);
    }
  }
}

Artifacts like this are natural and unavoidable consequence of JPEG compression.

They should not crop up in PNG compression. If you are getting such artifacts when you create a PNG file, I'd wager that you are not creating a PNG stream at all, but rather a JPEG stream in a file with a PNG extension. No decent decoder relies on the file extension.

I noticed two things in your code:

1) The filename you save to is String.format("%s.jpg", appName) or String.format("%s%03d.png", appName, suffix) independent of the actual encoding.

2) The bitmap you save has its density determined by prefs.saveImageDensity().get() so it may not be the same as the actual density of the bitmap you see on the screen.

Maybe you confused yourself with 1) or perhaps 2) causes the compression-artefacts you're seeing?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!