将base64图像字符串转换为位图以在ImageView中显示,位图显示为空。

9
  • 在浏览器中访问API时,它会下载图片。URL为http://example.com/api/v1/filedownloader.json?file=GvygDaYb64wUon0lxp2H1458543376

  • 我已更改服务器名称并将example.com添加到该URL中。因此,在浏览器中运行时不会下载图像文件。但您可以在这里看到图像文件。

  • 然后我使用编码工具解码工具检查了该文件。

  • 解码后,我得到一个.bin文件。然后我将其更改为.png格式。只有这样才能获得完整的图像。

  • 我不知道如何执行所有这些功能以获取图像并在imageView中显示它。

  • 无论如何,我尝试了这里的代码:

日志:

03-24 04:29:43.816: E/OnResponse(15392): ÿØÿà��JFIF������������ÿí��Photoshop 3.0��8BIM����������g��9dXpsI_ORS9jWIcxWfWe(��bFBMD01000abe030000070e0000c51a0000161c0000251d0000bc2000007f350000fc370000323a00003f3c0000f4620000ÿâICC_PROFILE������lcms����mntrRGB XYZ Ü��������)��9acspAPPL����������������������������������������������������öÖ����������Ó-lcms����������������������������������������������������������������������������������������������
03-24 04:29:43.816: E/OnResponse(15392): desc������ü������^cprt����\������wtpt����h������bkpt����|������rXYZ����������gXYZ����¤������bXYZ����¸������rTRC����Ì������@gTRC����Ì������@bTRC����Ì������@desc��������������c2��������������������������������������������������������������������������������������������������������������������������������������������������������������������text��������FB����XYZ ������������öÖ����������Ó-XYZ ����������������3����¤XYZ ������������o¢����8õ����XYZ ������������b����·����ÚXYZ ������������$ ��������¶Ïcurv��������������������ËÉckö?Q4!ñ)2;FQw]íkpz±|¬i¿}ÓÃé0ÿÿÿÛ��C��       
03-24 04:29:43.816: E/OnResponse(15392):    

"##!  %*5-%'2(  .?/279<<<$-BFA:F5;<9ÿÛ��C
03-24 04:29:43.816: E/OnResponse(15392): 9& &99999999999999999999999999999999999999999999999999ÿÂ��¸¸��"��ÿÄ����������������������������ÿÄ��������������������������ÿÄ��������������������������ÿÚ����������íÐÙG,!.Ph5ð8ò÷¸¥®ÐàÔ§DUdº
de��kP'.¤ÅS BG  ìóölâvw@+.ÆÖ®©$¸
Ø
03-24 04:29:43.816: E/OnResponse(15392): K¥Yp ³ºXC¹O/)u RÉuEÊ$£³UÂP©hL^ÅÌ ·üûÌ%§ EU-1i6Ss©,ÞÌõ®{·W¹k`¤I!kwt%ÙeP¦*Ôªóï-¿
03-24 04:29:43.816: E/OnResponse(15392):  l"4áá#^-KSIBá¯S¨jYeîÌùucÓq}Lvå^ jÍ [Bz¾·í'nUï#tE  ÂQ(äf)Uw(5ݨG/cUÙÀSAIÓ(´ÌÑY.,±iíÒ«Bଽ^pvf;TAX,KÄEµ XbìÜHqßìx¯Wf    ¬«R.ªªì#IOYçx=ÿ��7+J%g(ªÉM*ÖhÙ­¶ìíZMøعs^²Èó¡fº­(%F¬î\ÓF¥§*ÇÈÉ+«Çu{H륭]G4Q%A]Eñî>±3¦Y:,tÖØ&:×F3Óf]¡9ÖõQ9Zã��ÕZ3¼9zIÖy¶ÓT ÓPֺϫ@eÎv ìô}¿%ên[Tz)h6v¹n­,h°°?ÅfìÓOÇZ1ЮÑCdÖJí³íÁ±ÌN·VcÔpÐèkEÃ`W°+5hg
`Eçg4µãß4VzÆÏ[ã½-x7¨A`ºÊD5Wå®ky{º¬ZùöeÔÏG¶Br    VD&´³·
&µçY׬fLDLEP²¬X°2®æ¹\{Æ|°o{¾¦®w* Kªj2ÖåÉâ��nkv¼yöÐC3·±MÎWÆ%ÈmÞ  e��æÌè*ÍsgJSWPØ+bn]@0×<¸7cßnçé³Ü߸pª(©AÕÂÖV*ϯNlë^¬:ùõÝjfz½©vuwV4nvFåf°ÒT±0&§c,³ Yv#tUH\%Ø\ÚÇ6¹-úr[n}ÃêÈÊ`J¡£!  t¬ªÍ£<7VMXë³Fmú¹«vwED¥pÐlÌ6k!m+[lI@2Ò¬êÂhFè© jl%\Gfß Ìäï¿>o!jJ²Ìn¡,®XJg"<ÊH!»±ô±ÔÞ¶c¦¥ÙÝÚÙ  `HwW¨Â]¡Â;R´eZ¦Í.¡T`-MSs3ståS|˧ØY¢VÛ1ÌA^¶"­¹Id"¹¹=,»ùÄô0o¾=©7¥ù¦u¶ò:WÚa..ÊAÙ F®tXhÐåJB#)Â1bj±jhÙÍÍÒæôåV,×-^ãÃûPúuë9rj#D^®4WFªêÞ_sÇÓÈáú(?¥r2³¡'äa¥y]yÖfúRàîèGf´¦vuóñCYë³Gj¹$t&
03-24 04:29:43.816: E/OnResponse(15392): ftK4]Oc¾yØ;u^ØÎûÀ!×ÎÖZ±yVµv    ÐÙËò¿/.ÃÇìr±Ó6ìÚõdÌél0MU±:æ3¤¼æµ¸é[qêÍ}´õàÚÍg³å^{0½*ÃÓÎò£¨Äàb«Óæëë/£¬Îo|½æîV{ðUµr®1É.¥Ü.
¥!ù±ÐyÝNo>ØõfÔuvc=C¨².¥H:M$º$£:·
dt(ÓZÆP×ró¬³P-P¥µR¯ü]9wØÕóínnÿ��+£æùç
pçRv¢E¢òêNw1j>]¸ë65.çլ첢² 1ì0aÝÉVrÀ¦] j¬eµpïÍeä×]9vW&;§ÑùßAßÆéɽc®|n Ù!æYbÔ£¢èLVwñïËÍÕâGUÙuã©°hC-eEg~u
03-24 04:29:43.816: E/OnResponse(15392):  MnK9Û0ìW¥Îzr¥º.êVÅBrjǬKOx%³*·µÍßÛÍììòúÉrCÍBcAXrÅ1Þ;Óçã¦Xusé jLS[uXïFuJf¡«²Ãôb|t3µ¶¢£(XÂÐùwË£ÒÌÖ¢#:qê^o·T��ä%gÈ`*WQlJ N×EÌéx®4»õáÓÃÓ±n6f6


03-24 04:29:43.816: D/skia(15392): --- SkImageDecoder::Factory returned null

03-24 04:29:43.816: E/myBitmap(15392): null

03-24 04:29:43.816: D/AndroidRuntime(15392): Shutting down VM
03-24 04:29:43.817: E/AndroidRuntime(15392): FATAL EXCEPTION: main
03-24 04:29:43.817: E/AndroidRuntime(15392): Process: com.steve.test, PID: 15392
03-24 04:29:43.817: E/AndroidRuntime(15392): java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference
03-24 04:29:43.817: E/AndroidRuntime(15392):    at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:596)
03-24 04:29:43.817: E/AndroidRuntime(15392):    at com.steve.test.SecondActivity$1.onResponse(SecondActivity.java:121)
03-24 04:29:43.817: E/AndroidRuntime(15392):    at com.steve.test.SecondActivity$1.onResponse(SecondActivity.java:1)
03-24 04:29:43.817: E/AndroidRuntime(15392):    at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:60)
03-24 04:29:43.817: E/AndroidRuntime(15392):    at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:1)
03-24 04:29:43.817: E/AndroidRuntime(15392):    at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:99)
03-24 04:29:43.817: E/AndroidRuntime(15392):    at android.os.Handler.handleCallback(Handler.java:739)
03-24 04:29:43.817: E/AndroidRuntime(15392):    at android.os.Handler.dispatchMessage(Handler.java:95)
03-24 04:29:43.817: E/AndroidRuntime(15392):    at android.os.Looper.loop(Looper.java:135)
03-24 04:29:43.817: E/AndroidRuntime(15392):    at android.app.ActivityThread.main(ActivityThread.java:5221)
03-24 04:29:43.817: E/AndroidRuntime(15392):    at java.lang.reflect.Method.invoke(Native Method)
03-24 04:29:43.817: E/AndroidRuntime(15392):    at java.lang.reflect.Method.invoke(Method.java:372)
03-24 04:29:43.817: E/AndroidRuntime(15392):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
03-24 04:29:43.817: E/AndroidRuntime(15392):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

SecondActivity.java:

 public class SecondActivity extends AppCompatActivity {


    String base64String;
    Bitmap bitmap;
    ImageView img ;

     String userValidationURL, base64;
     byte[] data;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.second_activity);

        img = (ImageView)findViewById(R.id.imageView);

        base64String = "GvygDaYb64wUon0lxp2H1458543376";

        userValidationURL = "http://example.com/api/v1/filedownloader.json?file=GvygDaYb64wUon0lxp2H1458543376"; 

       hitSearchApi(); 
    }

    private void hitSearchApi(){

            Log.e("userValidationUrl", userValidationURL);

            StringRequest request = new StringRequest(Request.Method.GET, userValidationURL, new Response.Listener<String>() {

                @Override
                public void onResponse(String response) {
                    if(response != null && !response.startsWith("<HTML>")){
                        Log.e("OnResponse", response);                                               

                    byte[] decodedString = Base64.decode("GvygDaYb64wUon0lxp2H1458543376", Base64.DEFAULT);
                    Bitmap myBitmap = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);

                    Log.e("mybitmap", ""+myBitmap);
                                            img.setImageBitmap(Bitmap.createScaledBitmap(myBitmap, img.getWidth(), img.getHeight(), false));

                        dialog.dismiss();

                    }else{

                        Log.e("onResponseElse", "onResponseElse");

                        dialog.dismiss();
                    }
                }
            }, new Response.ErrorListener() {

                @Override
                public void onErrorResponse(VolleyError error) {
                    if(error != null){
                        Log.e("error", error.toString());
                        dialog.dismiss();
                    }

                }
            }){
                @Override
                protected Map<String,String> getParams(){
                    Map<String,String> params = new HashMap<String, String>();

                    params.put("file", base64String);

                    Log.e("paramsImg", ""+params);

                    return params;
                }

                @Override
                public Map<String, String> getHeaders() throws AuthFailureError {
                    Map<String,String> params = new HashMap<String, String>();
                    params.put("Content-Type","application/x-www-form-urlencoded");
                    return params;
                }
            };
        RequestQueue queue = Volley.newRequestQueue(SecondActivity.this);
        queue.add(request);
        queue.getCache().remove(userValidationURL);    
    }        
}

这段代码有什么问题?为什么我的位图中会出现null。请有经验的人帮帮我。

我需要将该文件ID转换为HTTP图像格式。不,您必须将其用作URL参数以从Web服务器请求文件。但是您没有对接收到的数据进行任何操作。而且您正在尝试从文件ID而不是从从Web服务器接收到的数据创建位图。 - greenapps
当然可以。有许多上传base64编码图像的示例,也有下载base64编码图像的示例。然后可以显示或保存结果。这个网站上有很多这样的例子。所以请稍微搜索一下。如果你阅读了二十页(50个帖子)并使用“android”标签进行筛选,你就会找到它们。 - greenapps
你的位图代码看起来没问题,我怀疑问题出在输入流上,也许设置一个日志并捕获输入流(InputStream)的值会有帮助。 - GordonW
看起来异常发生在CardsFragment.java而不是MainActivity.java。此外,如果有的话,请将loadImage(...)发布在CardsFragment.java中。还有一件事,我猜测MainActivity.java中的loadImage没有被调用,因为如果调用它会抛出NetworkOnMainThreadException。 - BNK
@HugoGresse base64Image 是一个字符串。 - Stephen
显示剩余11条评论
7个回答

7

从日志中可以看出,

E/myBitmap: null

这意味着您无法解码位图。请参考此答案:

将Base64字符串转换为位图

还要确保您根据是否接收到适当的方法来处理。

data:image/jpg;base64

在Base64编码字符串中,可以选择切割部分内容。

data:image/jpg;base64

从字符串中获取数据,然后使用Base64.DEFAULT对其进行解码。

或者,如果您要切割它,则可以选择使用Base64.URL_SAFE

编辑:loadImage函数中修改以下行:

Bitmap myBitmap = BitmapFactory.decodeStream(input);

to

BufferedReader in = new BufferedReader(new InputStreamReader(input));
String inputLine;
StringBuffer response = new StringBuffer();

while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();

String encodedImage = response.toString();
byte[] decodedString = Base64.decode(encodedImage, Base64.DEFAULT);
Bitmap myBitmap = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);

如果不起作用,请告诉我encodedImage字符串的值。同时确保:

data:image/jpg;base64

响应中未传递。

如果您无法验证字符串是否为图像,可以创建一个简单的 HTML 页面,其中包含以下内容:

<!DOCTYPE html>
<html>
<head>
    <title>Base 64 Sample</title>
</head>
<body>

<img src="data:image/< png/jpeg/gif etc goes here >;base64,< image content goes here>">

</body>
</html>

将'<'和'>'之间的内容替换为适当的内容,并在浏览器中打开HTML页面。 或者您可以前往此链接并将字符串粘贴到那里。


我已经尝试了那个SO答案。但对我来说它不起作用。 - Stephen
示例意味着我删除了该服务器名称。 - Stephen
好的。如果您仍然得到null,请告诉我encodedImage的值。 - Anirudha Agashe
我没有把日志放在那里。你放了日志语句吗?或者即使放了日志语句,什么也没有打印出来。 - Anirudha Agashe
我放置了Log.e("encodedImage", ""+encodedImage); 但是我在日志中没有得到任何结果。我检查了很多次。 - Stephen
显示剩余3条评论

5
您获取了正确的base64编码字符串。只需使用以下代码将该字符串转换为位图即可:
byte[] decodedString = Base64.decode(StrBase64, Base64.DEFAULT);
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length); 
imageView1.setImageBitmap(decodedByte);

4

实际上,Base64字符串有很多字符。你的Base64字符串不正确,请将图像上传到这个网站以获取正确的Base64字符串。请使用该字符串替换你的代码中的原字符串。


4

您传递给bitMapToString函数的位图为null,因此出现了null对象错误。

loadImage();中,您没有获得正确的bitmap,因此请进行更改:

InputStream input = connection.getInputStream();
BufferedInputStream bufferedInputStream = new BufferedInputStream(input);
Bitmap myBitmap = BitmapFactory.decodeStream(input);

通过这种方式,你将获得位图


3
03-24 04:29:43.816: D/skia(15392): --- SkImageDecoder::Factory返回了null,这意味着BitmapFactory.decode的输入方式存在一些问题。以下列出了一些可能会使你困惑的情况,但不确定哪种情况适用,因为你没有透露真实的URL,而且你发布的代码甚至没有尝试解码从网络传来的数据。
Base64填充:你的硬编码输入字符串是"GvygDaYb64wUon0lxp2H1458543376",这不是一个有效的Base64编码字符串。在http://string-functions.com/base64decode.aspx页面上输入它,它会说:“无效长度的Base-64字符数组。”将其更改为"GvygDaYb64wUon0lxp2H1458543376=="(注意结尾),它将显示奇怪的字形,但这只是因为它是二进制数据,所以成功解码。
奇怪的是,当缺少填充时,Base64类应该抛出异常,但你没有得到...
您还可以在Chrome中检查编码字符串的内容,将以下内容输入到新标签页的地址栏中(替换逗号后面的内容,参见有效示例):
data:image/png;base64,GvygDaYb64wUon0lxp2H1458543376==

我看到一个小方块,可能不是图片(见下一节)。

Base64格式

你试图解码的样本也处于某种奇怪的格式中。它不是 Android 系统支持的 PNG/GIF/JPEG 文件,它缺少头文件。查看支持的格式列表:http://developer.android.com/guide/appendix/media-formats.html(向下滚动到 Images),这些是您可以加载的数据类型。

我尝试使用多个图像软件在我的笔记本上加载短字节数组,但没有任何软件将其识别为图像文件。我同意它们的观点,在十六进制编辑器中也看不到任何类似图像的东西。

非 Base64 格式!

如果您尝试解码变量 response,请确保它是 Base64 编码的字符串。上面的日志中是 JPEG 文件,但可能已损坏。请注意,您正在使用 StringRequest,这只有在您真正获得由 [a-zA-Z0-9+/=] 字符组成的 Base64 字符串时才有效。

要读取二进制数据,您需要发出不同类型的请求,这取决于您的网络库,但关键点是,如果您以字符串格式接收二进制数据,则表示对其应用了某种文本编码,但二进制数据没有字符编码,它只是纯粹的0x00-0xFF字节,没有任何解释。
在二进制数据上使用BitmapFactory.decode仅在您从网络库或InputStreamReader也有与二进制数据不符的文本编码)接收到byte[]时才起作用。

3
byte[] decodedString = Base64.decode(StrBase64, Base64.DEFAULT);
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length); 
imageView1.setImageBitmap(decodedByte);

0

这可能会有所帮助,尽管不是直接相关的。我的情况是我有一个图像处理程序,通过隐藏它们的位置并在严格验证后仅呈现它们的base64编码字符串来保护图像。然后我想这可以与Android Web视图一起使用,用硬编码的URL访问本地存储位置的HTML文件,但Bitmap Factory一直抱怨空值。我不得不通过同样的脚本来保护位置,但是我强制使用此代码(在php服务器端)通过必要的授权下载图像:

//url construction with creds from android – using normal download stream – app side (download class must be created) 
String targetURL = "https://www.example.com/images.php?download&xuname="+uname+"&xuagent="+useragent+"&xaccn="+ xaccn;

//grab vital details and validate the call – server side
if(isset($_GET['uname'])){      
    $uname = $_GET['xuname'];   //---- normal cleaning may apply
    //...
    //...
    //... authorization engines 
}else {
    //handle this with may be generic image 
}   
//if fine, now force the normal download of the file – normal input / output streams will understand it 
$filepath = "$path/$imagename";     //--- actual file location with name 
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($filepath).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filepath));
flush(); // Flush system output buffer
readfile($filepath);
exit;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接