我使用以下代码在ImageView中旋转图像一个角度.有没有更简单,更简单的方法可用.
ImageView iv = (ImageView)findViewById(imageviewid);
TextView tv = (TextView)findViewById(txtViewsid);
Matrix mat = new Matrix();
Bitmap bMap = BitmapFactory.decodeResource(getResources(),imageid);
mat.postRotate(Integer.parseInt(degree));===>angle to be rotated
Bitmap bMapRotate = Bitmap.createBitmap(bMap, 0, 0,bMap.getWidth(),bMap.getHeight(), mat, true);
iv.setImageBitmap(bMapRotate);
Run Code Online (Sandbox Code Playgroud) 尽管我在drawable文件夹中有一个非常小的图像,我从用户那里得到了这个错误.我没有在代码中使用任何位图功能.至少故意:)
java.lang.OutOfMemoryError
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:683)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:513)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:889)
at android.content.res.Resources.loadDrawable(Resources.java:3436)
at android.content.res.Resources.getDrawable(Resources.java:1909)
at android.view.View.setBackgroundResource(View.java:16251)
at com.autkusoytas.bilbakalim.SoruEkrani.cevapSecimi(SoruEkrani.java:666)
at com.autkusoytas.bilbakalim.SoruEkrani$9$1.run(SoruEkrani.java:862)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5602)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
at dalvik.system.NativeStart.main(Native Method)
Run Code Online (Sandbox Code Playgroud)
根据这个stackTrace,我在这一行得到了这个错误('tv'是一个textView):
tv.setBackgroundResource(R.drawable.yanlis);
Run Code Online (Sandbox Code Playgroud)
问题是什么?如果您需要有关代码的其他信息,我可以添加它.谢谢!
对于我的10,000点,我决定用这个很酷的网站来点缀一些东西:一种在本机内存上缓存位图的机制.
Android设备的每个应用程序的内存量非常有限 - 堆的范围从16MB到128MB,具体取决于各种参数.
如果您通过此限制,则会获得OOM,当您使用位图时,这可能会发生多次.
很多时候,应用程序可能需要克服这些限制,对巨大的位图执行繁重的操作,或者只是存储它们以供以后使用,并且您需要
我想出的是一个简单的java类,它可以使事情变得更容易.
它使用JNI来存储位图数据,并能够在需要时恢复它.
为了支持该类的多个实例,我必须使用我发现的技巧(这里).
数据仍然存储在RAM中,因此如果设备没有足够的RAM,应用程序可能会被杀死.
记得尽快释放记忆.它不仅可以避免内存泄漏,而且还可以避免在您的应用程序到达后台时首先被系统优先处理.
如果您不想忘记释放内存,可以在每次还原位图时释放它,或者使类实现Closable.
作为一种安全措施,我已经使它在finalize()方法中自动释放其本机内存,但不要让它负责这项工作.风险太大了.当这样的事情发生时,我也写了它写入日志.
它的工作方式是将整个数据复制到JNI对象中,为了还原,它从头开始创建位图并将数据放入其中.
正在使用和恢复的位图采用ARGB_8888格式.当然,您可以将其更改为您想要的任何内容,只是不要忘记更改代码...
大位图可能需要一些时间来存储和恢复,因此在后台线程上执行它可能是明智的.
这不是一个完整的OOM解决方案,但它可能有所帮助.例如,您可以将它与您自己的LruCache结合使用,同时避免将堆内存用于缓存本身.
代码仅用于存储和恢复.如果您需要执行某些操作,则需要进行一些研究.openCV可能就是答案,但是如果你想要执行一些基本的东西,你可以自己实现它们(这里是使用JNI旋转大图像的例子).如果你知道其他选择,请在这里告诉我.
希望这对某些人有用.请写下你的意见.
此外,如果您发现代码有任何问题或建议填补,请告知我们.
如果您希望在JNI端执行更多操作,您可以使用我所做的这篇文章.它基于我在这里编写的代码,但允许您进行更多操作,您可以轻松添加更多自己的代码.
我正在开发一个应用程序并在运行Android 2.2的设备上进行测试.在我的代码,我使用,我检索使用BitmapFactory.decodeResource位图的,我能够通过调用进行更改bitmap.setPixels()就可以了.当我在运行Android 1.6的朋友的设备上测试时,我IllegalStateException接到了电话bitmap.setPixels.在线文档说,IllegalStateException当位图不可变时,会抛出此方法.文档没有说明decodeResource返回不可变位图,但显然必须如此.
是否有不同的呼叫我可以从一个应用程序资源可靠地获得一个可变的位图,而不需要第二个Bitmap对象(我可以创建一个可变的一个同样大小并绘制成帆布包裹它,但这需要两个大小相等的位图使用的内存是我预期的两倍)?
我的应用程序中有一个图像缓存,它使用SoftReferences实现.Dalvik以相对较小的堆启动应用程序,然后在需求的情况下增加它.但我想从一开始就让我的堆大小更大.这是因为当我已经在缓存中有一些图像,并且活动开始(例如)或其他峰值内存需求发生时,我的缓存被清除,以便为该峰值需求提供内存.结果,在峰值消失后,我仍然有2-3 MB的可用空间,但我的缓存是空的!
我看到这个问题的解决方案是预先分配一个更大的正式堆,所以即使峰值消耗为2-3 MB,它仍然有一些空间,所以我的SoftReferences不会被清除.
我发现这VMRuntime.getRuntime().setMinimumHeapSize(BIGGER_SIZE)会有所帮助.尤其是,谷歌使用,在他们的应用程序,如提到这里.但是,VMRuntime类已标记为已弃用,并且在将来的版本中表示将从公共API中删除.所以setMinimumHeapSize不是一个永久的解决方案.
然后我如何让Dalvik在启动时增加我的堆?
目前,我通过分配一个大型数组并释放它来使用一种非常简单和俗气的技术.这使得Dalvik成长为我想要的堆.但是,我确信必须有更优雅的方式.你能告诉我吗?
根据Android参考文档Bitmap.recycle():
释放与此位图关联的本机对象,并清除对像素数据的引用.这不会同步释放像素数据; 如果没有其他引用,它只是允许它被垃圾收集.位图标记为"死",这意味着如果调用getPixels()或setPixels(),它将抛出异常,并且不会绘制任何内容.此操作无法撤消,因此只有在您确定位图没有进一步用途时才应调用此操作.这是一个高级调用,通常不需要调用,因为正常的GC进程将在没有更多对此位图的引用时释放此内存.
但是,我读过的很多书都建议通过调用Bitmap.recycle()来释放内存,确保不再需要它.
这让我很困惑:使用后是否需要打电话Bitmap.recycle()?
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/your_drawable"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" />
Run Code Online (Sandbox Code Playgroud)
我想以编程方式旋转drawable.
我该怎么办?
这是我的回调
private class RotateListener implements RotateGestureDetector.OnRotateGestureListener{
@Override
public boolean onRotate(MotionEvent event1, MotionEvent event2,
double deltaAngle) {
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
在deltaangle不大于0.1,我不知道什么是提取价值.
我是所有内存管理主题的新手,所以有很多我不理解的东西.
我正在尝试在我的应用程序中缓存图像,但我的内存消耗有问题:
所有的Bitmap Chaching代码都是从这里复制粘贴的:http://developer.android.com/training/displaying-bitmaps/index.html
我调试了代码并在eclipse的DDMS视图中检查了堆大小,在这些代码行之后大约有15mb的跳转:
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
Run Code Online (Sandbox Code Playgroud)
在"decodeSampledBitmapFromResource"方法中.
图像是1024x800,75kb jpg文件.根据我在互联网上已经看到的内容,这个图像应该占用的内存量大约是1024*800*4(每像素字节数)= 3.125mb
关于这个主题的所有线程都没有说明为什么它会占用更多的内存.有没有办法用合理数量的内存缓存一个图像?
编辑
我尝试使用@ ArshadParwez下面的答案中建议的decodeFile方法.使用此方法,在BitmapFactory.decodeStream方法之后,内存仅增加了3.5mb - 问题解决了,但是我想直接从资源缓存位图.
我注意到在decodeResource方法中有2个内存"跳转" - 一个大约3.5mb - 这是合理的,另一个奇怪的是14mb.那些14mb用于什么,为什么会发生这种情况?
我已经决定,由于位图会占用大量内存,而这些内存很容易导致内存不足错误,因此我会对C/C++代码进行大量内存消耗.
即使一切似乎都没有任何错误,输出图像也不是原始的旋转.事实上,它完全毁了它.
旋转应该是逆时针方向,90度.

所以你可以看到,不仅颜色变得怪异,而且尺寸与我设定的尺寸不符.这里真的很奇怪.
也许我没有正确读取/放置数据?
当然这只是一个例子.代码应该可以在任何位图上正常工作,只要设备有足够的内存来容纳它.另外,我可能想在位图上执行其他操作而不是旋转它.
Android.mk文件:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := JniTest
LOCAL_SRC_FILES := JniTest.cpp
LOCAL_LDLIBS := -llog
LOCAL_LDFLAGS += -ljnigraphics
include $(BUILD_SHARED_LIBRARY)
APP_OPTIM := debug
LOCAL_CFLAGS := -g
Run Code Online (Sandbox Code Playgroud)
cpp文件:
#include <jni.h>
#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <android/bitmap.h>
#include <cstring>
#include <unistd.h>
#define LOG_TAG "DEBUG"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
extern "C"
{
JNIEXPORT jobject JNICALL Java_com_example_jnitest_MainActivity_rotateBitmapCcw90(JNIEnv * env, jobject obj, jobject …Run Code Online (Sandbox Code Playgroud) java-native-interface android bitmap image-rotation android-ndk
我有一个应用程序,为用户显示了很多图像,我们已经看到很多错误报告,OutOfMemoryError但有例外.
我们目前的工作是:
// Check if image is a landscape image
if (bmp.getWidth() > bmp.getHeight()) {
// Rotate it to show as a landscape
Matrix m = image.getImageMatrix();
m.postRotate(90);
bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), m, true);
}
image.setImageBitmap(bmp);
Run Code Online (Sandbox Code Playgroud)
显而易见的问题是我们必须从内存中的图像重新创建位图并旋转矩阵,这对于内存来说非常昂贵.
我的问题很简单:
是否有更好的方法来旋转图像而不会导致OutOfMemoryError?
我以这种方式旋转位图,在每个按钮上单击图像旋转90度
Matrix matrix = new Matrix();
matrix.postRotate(90);
rotated = Bitmap.createBitmap(rotated, 0, 0,
rotated.getWidth(), rotated.getHeight(), matrix, true);
iv.setImageBitmap(rotated);
Run Code Online (Sandbox Code Playgroud)
我用很多图像试过这个,但是现在一个引起了OutOfMemoryError.有办法防止这种情况吗?当然我可以调用recycle,但后来我丢失了位图并且必须从imageview再次获取它.我认为这不会有任何区别.
在某些应用程序中,处理没有OOM的大型图像以及快速处理这些图像非常重要.
为此,JNI(或令人遗憾地缺乏文档的renderscript)可以是一个很好的解决方案.
在过去,我成功地使用JNI来旋转巨大的位图,同时避免使用OOM(链接在这里,这里和这里).这是一个很好的(但很烦人)经验,但最终它的工作.
android框架有很多处理位图的功能,但我不知道JNI方面的情况如何.
我已经知道如何将位图从android的"java世界"传递到"JNI世界"并返回.
我不知道的是我可以在JNI端使用哪些功能来帮助我使用位图.
我希望能够在JNI上进行所有图像操作(包括解码),这样我在呈现大图像时就不用担心OOM了,在这个过程的最后,我可以将数据转换为Java-位图(显示用户)和/或将其写入文件.
再次,我不想将JNI端的数据转换为java位图,只是为了能够运行这些操作.
事实证明,有一些库提供了许多功能(如JavaCV),但是它们非常大,我不太确定它们的功能,如果它们真的在JNI端进行解码,所以我更喜欢能够通过Android的内置JNI功能知道什么是可能的.
哪些功能可以在Android上的JNI端进行图像处理?
例如,我如何在位图上运行面部检测,应用矩阵,下采样位图,缩放位图等等?
对于某些操作,我已经可以想到一种实现它们的方法(缩放图像非常简单,维基百科可以提供很多帮助),但有些操作非常复杂.
即使我自己实现了这些操作,也许其他人已经提高了效率,想到了C/C++可以拥有的那么多优化.
当我去Android的JNI方面时,我真的是靠自己,我需要从头开始实现每一个方面吗?
为了说清楚,我感兴趣的是:
在java上输入位图 - >纯粹在JNI和C/C++中的图像处理(无论如何都没有转换为java对象) - >在java上输出位图.
public static boolean rotateBitmapByExifAndSave(File targetFile){
if (targetFile==null || !targetFile.exists() || !targetFile.canRead() || !targetFile.canWrite())
return false;
boolean isSucceed = false;
// detect if photo is need to be rotated
try {
final Matrix matrix = new Matrix();
ExifInterface exifReader = new ExifInterface(targetFile.getAbsolutePath());
int orientation = exifReader.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
boolean isRotationNeeded = true;
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
matrix.postRotate(90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix.postRotate(180);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix.postRotate(270);
break;
default: // ExifInterface.ORIENTATION_NORMAL
// Do nothing. The original image is fine.
isRotationNeeded = false;
isSucceed …Run Code Online (Sandbox Code Playgroud)