[Bearbeiten: Ich habe ein minimales Projekt gemacht, um zu versuchen, einzugrenzen, was los ist. Der Code am unteren Rand erzeugt immer noch die gleichen Artefakte beim Speichern.Beim Speichern von Bitmap auf Festplatte, feste Pfade zeigen Artefakte
Ich habe eine App, die einfache 2D-Geometrie mit Pfaden zeichnet. Die Formen sind alle einfarbig, manchmal mit Alpha < 255, und können mit Linien verziert sein. In der Ansicht, die die Geometrie zeichnet, gab es nie ein Problem mit der Art, wie Dinge gezeichnet werden. Wenn ich jedoch den gleichen Code verwende, um zu einer Bitmap zu zeichnen und sie dann entweder als JPEG (mit 100er Qualität) oder PNG zu speichern, gibt es in den durchgehenden Bereichen der Ausgabedateien immer das gleiche Artefakt. Es ist eine Art Sprenkelung, die normalerweise mit JPEG-Komprimierung verbunden ist.
ich folgendes
- Speichern entweder PNG versucht haben und JPEG
- Drehen Dithering und Anti-Aliasing und Ausschalten
- die DPI des Bitmaps erhöhen und erlaubt auch die Bitmap seine Standard API
- Anwenden der Matrix I als Kamera zur geometrischen Darstellung verwenden zu verwenden, anstatt es zu bewerben die Leinwand für die Bitmap
- Drehen HW-Beschleunigung und ausschalten App weit
- eine 3rd-Party-Bibliothek Verwenden der Bitmap in eine .bmp Datei
alle die gleichen Artefakte liefern zu retten, weder macht es noch schlimmer noch besser.
public class MainActivity extends AppCompatActivity {
Context context;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.context = getApplicationContext();
}
// button OnClick listener
public void saveImage(View view) {
new saveBitmapToDisk().execute(false);
}
public Bitmap getBitmap() {
final int bitmapHeight = 600, bitmapWidth = 600;
Bitmap bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
Canvas bitmapCanvas = new Canvas(bitmap);
float[] triangle = new float[6];
triangle[0] = bitmapWidth/2;
triangle[1] = 0;
triangle[2] = 0;
triangle[3] = bitmapHeight/2;
triangle[4] = bitmapWidth/2;
triangle[5] = bitmapHeight/2;
Path solidPath = new Path();
Paint solidPaint = new Paint();
solidPaint.setStyle(Paint.Style.FILL);
solidPath.moveTo(triangle[0], triangle[1]);
for(int i = 2; i < triangle.length; i += 2)
solidPath.lineTo(triangle[i], triangle[i+1]);
solidPath.close();
solidPaint.setColor(Color.GREEN);
bitmapCanvas.drawPath(solidPath, solidPaint);
return bitmap;
}
private class saveBitmapToDisk extends AsyncTask<Boolean, Integer, Uri> {
Boolean toShare;
@Override
protected Uri doInBackground(Boolean... shareFile) {
this.toShare = shareFile[0];
final String appName = context.getResources().getString(R.string.app_name);
final String IMAGE_SAVE_DIRECTORY = String.format("/%s/", appName);
final String fullPath = Environment.getExternalStorageDirectory().getAbsolutePath() + IMAGE_SAVE_DIRECTORY;
File dir, file;
try {
dir = new File(fullPath);
if (!dir.exists())
dir.mkdirs();
OutputStream fOut;
file = new File(fullPath, String.format("%s.png", appName));
for (int suffix = 0; file.exists(); suffix++)
file = new File(fullPath, String.format("%s%03d.png", appName, suffix));
file.createNewFile();
fOut = new FileOutputStream(file);
Bitmap saveBitmap = getBitmap();
saveBitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
MediaStore.Images.Media.insertImage(context.getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName());
} 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;
}
return Uri.fromFile(file);
}
@Override
protected void onPostExecute(Uri uri) {
super.onPostExecute(uri);
Toast.makeText(context, "Image saved", Toast.LENGTH_SHORT).show();
}
}
}
Ich habe nur ein neues Gerät überprüft, und ich habe definitiv immer noch Artefakte, und es ist definitiv keine alte Datei. Noch ist es ein thumbnail; Wenn Sie zum Abschnitt "Info" gehen, werden die korrekten Abmessungen angezeigt. Ist es möglich, dass dies etwas in der Build-Umgebung oder etwas ähnliches ist? – Project
@Projekt Ich fügte meiner Antwort eine vereinfachte Aktivität hinzu, die Sie testen sollten. Es erstellt ein Kreisbild auf transparentem Hintergrund und öffnet die Freigabeabsicht, um diese Datei zu senden, auf Ihrem Gerät auszuführen und das generierte Bild per E-Mail an Sie zu senden. Wenn das Bild einen transparenten Hintergrund hat, wurde es als PNG codiert, wenn es undurchsichtig war, wurde es als JPEG codiert. – yoah
Getestet Ihr Beispiel, es hat einen transparenten Hintergrund und keine Artefakte. Neugierig, ob es sich um das Verzeichnis handelt, in dem ich mich gerade aufhalte, oder um sowas ... stochert es herum, sobald Kaffee passiert ist. – Project