Diese Antwort wird von Loading large bitmaps Efficiently zusammengefasst, die erklären, wie inSampleSize verwenden, um eine abwärtsskalierten Bitmap Version zu laden.
Insbesondere Pre-scaling bitmaps erklärt die Details der verschiedenen Methoden, wie sie zu kombinieren, und welche die meisten Speicher effizient sind.
Es gibt drei dominante Möglichkeiten, um eine Bitmap auf Android, um die Größe, die unterschiedlichen Speichereigenschaften haben:
createScaledBitmap API
Diese API in einer vorhandenen Bitmap nehmen, und erstellen Sie eine neue Bitmap mit der genaue Abmessungen, die Sie ausgewählt haben.
Auf der positiven Seite können Sie genau die Bildgröße erhalten, die Sie suchen (unabhängig davon, wie es aussieht). Aber der Nachteil, ist, dass diese API eine bestehende Bitmap benötigt, um zu arbeiten. Das bedeutet, dass das Bild geladen, dekodiert und eine Bitmap erstellt werden muss, bevor eine neue, kleinere Version erstellt werden kann. Dies ist ideal in Bezug auf die genauen Abmessungen, aber schrecklich in Bezug auf zusätzliche Speicher Overhead. Als solches ist diese Art-eines Deal Breaker für die meisten App-Entwickler, die Speicher in der Regel bewusst
inSampleSize flag
BitmapFactory.Options
eine Eigenschaft festgestellt, wie inSampleSize
hat, dass Ihr Bild die Größe neu, während es Decodierung, um zu verhindern die Notwendigkeit, zu einer temporären Bitmap zu dekodieren. Dieser ganzzahlige Wert, der hier verwendet wird, lädt ein Bild mit einer 1/x-reduzierten Größe. Wenn Sie beispielsweise auf 2 setzen, wird ein Bild zurückgegeben, das halb so groß ist, und wenn Sie es auf 4 setzen, wird ein Bild zurückgegeben, das 1/4 der Größe entspricht. Grundsätzlich sind die Bildgrößen immer etwas kleiner als die Quellgröße.
Aus einer Speicherperspektive ist die Verwendung von inSampleSize
eine sehr schnelle Operation. Effektiv wird nur jedes X-te Pixel Ihres Bildes in die resultierende Bitmap decodiert. Es gibt zwei Hauptprobleme mit inSampleSize
aber:
Es gibt nicht Sie genaue Auflösungen. Es verringert nur die Größe Ihrer Bitmap um etwas 2.
Es produziert nicht die beste Qualität Größe ändern. Die meisten Größenänderungsfilter erzeugen gut aussehende Bilder durch Lesen von Pixelblöcken und dann Gewichten dieser, um das in der Größe veränderte Pixel zu erzeugen.inSampleSize
vermeidet all dies, indem nur alle paar Pixel gelesen wird. Das Ergebnis ist ziemlich performant und wenig Speicher, aber die Qualität leidet darunter.
Wenn Sie nur mit schrumpf Ihr Bild von einigen POW2 Größe zu tun, und Filterung ist kein Problem, dann können Sie keine mehr Speicher effizient (oder Leistung effizient) Methode als inSampleSize
finden.
inScaled, inDensity, inTargetDensity flags
Wenn Sie ein Bild auf eine Dimension müssen maßstabs, die eine Potenz von zwei nicht gleich ist, dann müssen Sie die inScaled
, inDensity
und inTargetDensity
Flaggen von BitmapOptions
. Wenn das Flag inScaled
gesetzt wurde, leitet das System den Skalierungswert ab, der auf Ihre Bitmap angewendet werden soll, indem der Wert inTargetDensity
durch die Werte inDensity
dividiert wird.
mBitmapOptions.inScaled = true;
mBitmapOptions.inDensity = srcWidth;
mBitmapOptions.inTargetDensity = dstWidth;
// will load & resize the image to be 1/inSampleSize dimensions
mCurrentBitmap = BitmapFactory.decodeResources(getResources(),
mImageIDs, mBitmapOptions);
Mit dieser Methode wird die Größe neu Ihr Bild, und auch ein ‚Ändern der Größe Filter‘, um es anzuwenden, das heißt, wird das Endergebnis besser aussehen, weil einige zusätzliche Mathematik berücksichtigt hat, während der Umskalierungsschritt genommen worden . Aber seien Sie gewarnt: dieser zusätzliche Filterschritt, benötigt zusätzliche Verarbeitungszeit, und kann schnell für große Bilder summieren, was zu langsamen Größenanpassungen und zusätzlichen Speicherzuweisungen für den Filter selbst führt.
Es ist generell keine gute Idee, diese Technik auf ein Bild anzuwenden, das aufgrund des zusätzlichen Filteraufwands deutlich größer ist als Ihre gewünschte Größe.
magische Kombination
aus einem Speicher und Performance-Perspektive, können Sie diese Optionen für die besten Ergebnisse kombinieren. (Einstellung der inSampleSize
, inScaled
, inDensity
und inTargetDensity
flags)
inSampleSize
wird zuerst auf das Bild angewendet werden, es auf die nächste mit Strom versorgt von zwei Kindern größer als Zielgröße. Dann werden inDensity
& inTargetDensity
verwendet, um das Ergebnis auf die gewünschten exakten Dimensionen zu skalieren, wobei eine Filteroperation angewendet wird, um das Bild zu bereinigen.
Die Kombination dieser beiden Verfahren ist viel schneller, da der Schritt inSampleSize
die Anzahl der Pixel verringert, die der resultierende dichtebasierte Schritt für die Anwendung des Größenänderungsfilters benötigt.
mBitmapOptions.inScaled = true;
mBitmapOptions.inSampleSize = 4;
mBitmapOptions.inDensity = srcWidth;
mBitmapOptions.inTargetDensity = dstWidth * mBitmapOptions.inSampleSize;
// will load & resize the image to be 1/inSampleSize dimensions
mCurrentBitmap = BitmapFactory.decodeFile(fileName, mBitmapOptions);
Wenn Sie benötigen ein Bild auf bestimmte Dimensionen passen, und einiger schöner Filterung, dann ist diese Technik ist die beste Brücke die richtige Größe zu bekommen, aber in einem schnellen, low-memory footprint getan Betrieb.
Erste Bildabmessungen
gibt es die Bildgröße, ohne das gesamte Bilddekodierungs Um Ihre Bitmap, um die Größe, benötigen Sie die eingehenden Dimensionen kennen. Mit dem Flag können Sie die Abmessungen des Bilds ermitteln, ohne die Pixeldaten dekodieren zu müssen.
Sie können dieses Flag verwenden, um zuerst die Größe zu dekodieren und dann die richtigen Werte für die Skalierung auf Ihre Zielauflösung zu berechnen.
Kann Ihr Server nicht die richtige Größe senden, so sparen Sie RAM und Bandbreite Ihres Kunden !? – James
Das ist nur dann gültig, wenn ich die Serverressource besaß, eine Compute-Komponente zur Verfügung hatte und in jedem Fall die genauen Abmessungen von Bildern für noch nicht gesehene Seitenverhältnisse vorhersagen konnte. Also, wenn Sie Ressourceninhalt von einer CDN von Drittanbietern laden (wie ich bin) funktioniert es nicht :( –