2013-01-02 44 views
-1

我有一張圖片需要發送到服務器。有沒有辦法將黑莓中的位圖(jpg)轉換爲base64字符串?將位圖轉換爲黑莓中的base64字符串

+0

首先將位圖轉換爲字節數組。然後將其轉換爲base64字符串 – Signare

+0

我試圖將我的位圖轉換爲字節數組,但首先將其轉換爲字節數組會消耗大量內存。 –

+0

如此使用大尺寸圖像? – Signare

回答

6

你要求什麼是有點模糊和奇怪,但是我希望這可以幫助:

有了下面的一段代碼有可能得到一個JPEG二進制數據爲Bitmap(注意,這是一個壓縮的一個,因此,如果比較原始的位圖數據的大小盡可能小):

Bitmap bmp = ...; // your bitmap 
int quality = 85; 
EncodedImage encodedImg = JPEGEncodedImage.encode(bmp, quality); 
byte[] data = encodedImg.getData(); 

然後你可以用Base64OutputStream編碼。有關如何編碼,請參閱API for sample code

+0

非常感謝你,這個比我發現的要好得多。我不需要創建另一個類來轉換我的圖像,另外我可以修改編碼圖像的質量。 –

+1

很高興,我很有幫助。所以最後事實證明,你不需要「獲得一個Base64編碼的數據」原始位圖二進制「。 :) –

1
package com.covidien.screens; 

import java.io.OutputStream; 

import javax.microedition.io.Connector; 
import javax.microedition.io.file.FileConnection; 

import net.rim.device.api.system.Bitmap; 
import net.rim.device.api.system.CDMAInfo; 
import net.rim.device.api.system.GPRSInfo; 
import net.rim.device.api.system.IDENInfo; 
import net.rim.device.api.system.RadioInfo; 
import net.rim.device.api.ui.Field; 
import net.rim.device.api.ui.FieldChangeListener; 
import net.rim.device.api.ui.UiApplication; 
import net.rim.device.api.ui.component.BitmapField; 
import net.rim.device.api.ui.component.ButtonField; 
import net.rim.device.api.ui.component.Dialog; 
import net.rim.device.api.ui.container.HorizontalFieldManager; 
import net.rim.device.api.ui.container.MainScreen; 

import org.kobjects.base64.Base64; 
import org.ksoap2.SoapEnvelope; 
import org.ksoap2.serialization.SoapObject; 
import org.ksoap2.serialization.SoapSerializationEnvelope; 
import org.ksoap2.transport.HttpTransport; 


public final class ImageScreen extends MainScreen 
{ 
    /** The down-scaling ratio applied to the snapshot Bitmap */ 
    private static final int IMAGE_SCALING = 5; 
    private static final String boundary = "31BF3856AD364E35"; 
    /** The base file name used to store pictures */ 
    private static String FILE_NAME = System.getProperty("fileconn.dir.photos") + "IMAGE"; 

    /** The extension of the pictures to be saved */ 
    private static String EXTENSION = ".png"; 

    /** A counter for the number of snapshots taken */ 
    private static int _counter; 

    /** A reference to the current screen for listeners */ 
    private ImageScreen _imageScreen; 

    static String imageName=null; 
    /** 
    * Constructor 
    * @param raw A byte array representing an image 
    */ 
    public ImageScreen(final byte[] raw) 
    { 
     // A reference to this object, to be used in listeners 
     _imageScreen = this; 

     setTitle("IMAGE"); 

     // Convert the byte array to a Bitmap image 
     Bitmap image = Bitmap.createBitmapFromBytes(raw, 0, -1, IMAGE_SCALING); 

     // Create two field managers to center the screen's contents 
     HorizontalFieldManager hfm1 = new HorizontalFieldManager(Field.FIELD_HCENTER); 
     HorizontalFieldManager hfm2 = new HorizontalFieldManager(Field.FIELD_HCENTER); 

     // Create the field that contains the image 
     BitmapField imageField = new BitmapField(image); 
     hfm1.add(imageField); 

     // Create the SAVE button which returns the user to the main camera 
     // screen and saves the picture as a file. 
     ButtonField photoButton = new ButtonField("Use"); 
     photoButton.setChangeListener(new SaveListener(raw)); 
     hfm2.add(photoButton); 

     // Create the CANCEL button which returns the user to the main camera 
     // screen without saving the picture. 
     ButtonField cancelButton = new ButtonField("Retake"); 
     cancelButton.setChangeListener(new CancelListener()); 
     hfm2.add(cancelButton); 

     // Add the field managers to the screen 
     add(hfm1); 
     add(hfm2); 
    } 

    /** 
    * Handles trackball click events 
    * @see net.rim.device.api.ui.Screen#invokeAction(int) 
    */ 
    protected boolean invokeAction(int action) 
    { 
     boolean handled = super.invokeAction(action); 

     if(!handled) 
     { 
      switch(action) 
      { 
       case ACTION_INVOKE: // Trackball click. 
       { 
        return true; 
       } 
      } 
     } 
     return handled; 
    } 

    /** 
    * A listener used for the "Save" button 
    */ 
    private class SaveListener implements FieldChangeListener 
    { 


     /** A byte array representing an image */ 
     private byte[] _raw; 

     /** 
     * Constructor. 
     * @param raw A byte array representing an image 
     */ 
     SaveListener(byte[] raw) 
     { 
      _raw = raw; 
     } 

     /** 
     * Saves the image as a file in the BlackBerry filesystem 
     */ 
     public void fieldChanged(Field field, int context) 
     { 
      try 
      { 
       // Create the connection to a file that may or 
       // may not exist. 
       FileConnection file = (FileConnection)Connector.open(FILE_NAME + _counter + EXTENSION); 

       // If the file exists, increment the counter until we find 
       // one that hasn't been created yet. 
       while(file.exists()) 
       { 
        file.close(); 
        ++_counter; 
        file = (FileConnection)Connector.open(FILE_NAME + _counter + EXTENSION); 
       } 

       // We know the file doesn't exist yet, so create it 
       file.create(); 

       // Write the image to the file 
       OutputStream out = file.openOutputStream(); 
       out.write(_raw); 

       System.out.println("Boundary :::::"+boundary); 
       //******************************************************************************************************* 
       String serviceUrl = "URL/Service.asmx"; 
       String serviceNamespace = "http://tempuri.org/"; 
       String soapAction="http://tempuri.org/Upload"; 
       SoapObject rpc = new SoapObject(serviceNamespace, "Upload"); 
       SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); 

       envelope.bodyOut = rpc; 
       envelope.dotNet = true; 
       envelope.encodingStyle = SoapSerializationEnvelope.XSD; 
       rpc.addProperty("contents",Base64.encode(_raw)); 
       imageName="Image" + _counter + EXTENSION; 
       rpc.addProperty("FileName", imageName); 
       HttpTransport ht = new HttpTransport(serviceUrl); 
       ht.debug = true; 
       String result; 

       //    String str = null; 

       SoapObject soapObject; 

       try 
       { 
        ht.call(soapAction, envelope); 
        result = (envelope.getResponse()).toString(); 
        //      if((envelope.getResponse()).toString().trim().equals("OK")) 
        //      { 
         //       UiApplication.getUiApplication().pushScreen(new DoctorPopup()); 
        //      } 
        //     if(result.length()==2 || result.equalsIgnoreCase("OK")) 
        //      { 
         //      UiApplication.getUiApplication().pushScreen(new DoctorPopup()); 
        //      } 

        if(result.length()==2) 
        { 
         UiApplication.getUiApplication().pushScreen(new DoctorPopup()); 
        } 

        soapObject = (SoapObject) envelope.getResponse(); 
        //      Dialog.alert("soapObject" + soapObject); 
       } 
       catch(Exception ex) 
       { 
        //if we get an exception we'll just write the msg to the screen. 
        System.out.println(ex.getMessage()); 
        result = ex.toString(); 
       } 



       // Close the connections 
       out.close(); 
       file.close(); 
      } 
      catch(Exception e) 
      { 
       WelcomeScreen.errorDialog("ERROR " + e.getClass() + ": " + e.getMessage()); 
       System.out.println(e.getMessage()); 
      } 

      ++_counter; 
     } 
    } 

    /** 
    * A listener used for the "Cancel" button 
    */ 
    private class CancelListener implements FieldChangeListener 
    { 
     /** 
     * Return to the main camera screen 
     */ 
     public void fieldChanged(Field field, int context) 
     { 
      UiApplication.getUiApplication().popScreen(_imageScreen); 
     } 
    } 

    public final static boolean isCDMA() { 
     return RadioInfo.getNetworkType() == RadioInfo.NETWORK_CDMA; 
    } 

    public final static boolean isIDEN() { 
     return RadioInfo.getNetworkType() == RadioInfo.NETWORK_IDEN; 
    } 

    public static final String getIMEI() { 
     if (ImageScreen.isCDMA()) { 
      return ""+CDMAInfo.getESN(); 
     } else if (ImageScreen.isIDEN()){ 
      return IDENInfo.imeiToString(IDENInfo.getIMEI()); 
     } else { 
      return GPRSInfo.imeiToString(GPRSInfo.getIMEI()); 
     } 
    } 
} 
+4

請不要在這裏發佈你的整個應用程序。只需剪出您認爲應該用來對位圖圖像進行編碼的代碼即可。另外,請確保在編輯窗口中選擇全部**源代碼,然後使用** {} **按鈕將其格式化爲代碼。請在編輯器下方的預覽中查看您的答案,以確保其可讀性。謝謝。 – Nate

+0

確定下次我會記住這一點。 – Puneet

+2

它不必等到下一次。您的答案下方有一個**編輯**鏈接,您可以隨時使用該鏈接隨時返回並修改答案。我經常編輯我的答案很多次。 – Nate

1

發現這一個,更快地將位圖轉換爲byte []。正是我需要的。

import java.io.*; 
import javax.microedition.lcdui.Image; 
import net.rim.device.api.compress.ZLibOutputStream; 

public class MinimalPNGEncoder 
{ 
    public static Image toImage(int width, int height, byte[] alpha, byte[] red, byte[] green, byte[] blue) 
{ 
    try  
    { 
    byte[] png = toPNG(width, height, alpha, red, green, blue); 
    return Image.createImage(png, 0, png.length); 
    } 
    catch (IOException e) 
    { 
    return null; 
    } 
} 

public static byte[] toPNG(int width, int height, byte[] alpha, byte[] red, byte[] green, byte[] blue) throws IOException 
{ 
    byte[] signature = new byte[] {(byte) 137, (byte) 80, (byte) 78, (byte) 71, (byte) 13, (byte) 10, (byte) 26, (byte) 10}; 
    byte[] header = createHeaderChunk(width, height); 
    byte[] data = createDataChunk(width, height, alpha, red, green, blue); 
    byte[] trailer = createTrailerChunk(); 

    ByteArrayOutputStream png = new ByteArrayOutputStream(signature.length + header.length + data.length + trailer.length); 
    png.write(signature); 
    png.write(header); 
    png.write(data); 
    png.write(trailer); 
    return png.toByteArray(); 
} 

public static byte[] createHeaderChunk(int width, int height) throws IOException 
{ 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(13); 
    DataOutputStream chunk = new DataOutputStream(baos); 
    chunk.writeInt(width); 
    chunk.writeInt(height); 
    chunk.writeByte(8); // Bitdepth 
    chunk.writeByte(6); // Colortype ARGB 
    chunk.writeByte(0); // Compression 
    chunk.writeByte(0); // Filter 
    chunk.writeByte(0); // Interlace  
    return toChunk("IHDR", baos.toByteArray()); 
} 

public static byte[] createDataChunk(int width, int height, byte[] alpha, byte[] red, byte[] green, byte[] blue) throws IOException 
{  
    int source = 0; 
    int dest = 0; 
    byte[] raw = new byte[4*(width*height) + height]; 
    for (int y = 0; y < height; y++) 
    { 
     raw[dest++] = 0; // No filter 
     for (int x = 0; x < width; x++) 
     { 
     raw[dest++] = red[source]; 
     raw[dest++] = green[source]; 
     raw[dest++] = blue[source]; 
     raw[dest++] = alpha[source++]; 
     } 
    } 
    return toChunk("IDAT", toZLIB(raw)); 
} 

public static byte[] createTrailerChunk() throws IOException 
{ 
    return toChunk("IEND", new byte[] {}); 
} 

public static byte[] toChunk(String id, byte[] raw) throws IOException 
{ 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(raw.length + 12); 
    DataOutputStream chunk = new DataOutputStream(baos); 

    chunk.writeInt(raw.length); 

    byte[] bid = new byte[4]; 
    for (int i = 0; i < 4; i++) 
    { 
     bid[i] = (byte) id.charAt(i); 
    } 

    chunk.write(bid); 

    chunk.write(raw); 

    int crc = 0xFFFFFFFF; 
    crc = updateCRC(crc, bid); 
    crc = updateCRC(crc, raw);  
    chunk.writeInt(~crc); 

    return baos.toByteArray(); 
} 

static int[] crcTable = null; 

public static void createCRCTable() 
{ 
    crcTable = new int[256]; 

    for (int i = 0; i < 256; i++) 
    { 
     int c = i; 
     for (int k = 0; k < 8; k++) 
     { 
     c = ((c & 1) > 0) ? 0xedb88320^(c >>> 1) : c >>> 1; 
     } 
     crcTable[i] = c; 
    } 
} 

public static int updateCRC(int crc, byte[] raw) 
{ 
    if (crcTable == null) 
    { 
     createCRCTable(); 
    } 

    for (int i = 0; i < raw.length; i++) 
    { 
     crc = crcTable[(crc^raw[i]) & 0xFF]^(crc >>> 8);  
    } 

    return crc; 
} 

/* This method is called to encode the image data as a zlib 
block as required by the PNG specification. This file comes 
with a minimal ZLIB encoder which uses uncompressed deflate 
blocks (fast, short, easy, but no compression). If you want 
compression, call another encoder (such as JZLib?) here. */ 
public static byte[] toZLIB(byte[] raw) throws IOException 
{ 
     //used the BB ZLib ... 
    ByteArrayOutputStream outBytes = new ByteArrayOutputStream(1024); 
    ZLibOutputStream compBytes = new ZLibOutputStream(outBytes, false, 10, 9); 
    compBytes.write(raw, 0, raw.length); 
    compBytes.close(); 
    return outBytes.toByteArray(); 
//return ZLIB.toZLIB(raw); 
} 
} 



class ZLIB 
{ 
    static final int BLOCK_SIZE = 32000; 

    public static byte[] toZLIB(byte[] raw) throws IOException 
{  
    ByteArrayOutputStream baos = new ByteArrayOutputStream(raw.length + 6 + (raw.length/BLOCK_SIZE) * 5); 
    DataOutputStream zlib = new DataOutputStream(baos); 

    byte tmp = (byte) 8;  
    zlib.writeByte(tmp);       // CM = 8, CMINFO = 0 
    zlib.writeByte((31 - ((tmp << 8) % 31)) % 31); // FCHECK (FDICT/FLEVEL=0) 

    int pos = 0; 
    while (raw.length - pos > BLOCK_SIZE) 
    { 
     writeUncompressedDeflateBlock(zlib, false, raw, pos, (char) BLOCK_SIZE); 
     pos += BLOCK_SIZE; 
    } 

    writeUncompressedDeflateBlock(zlib, true, raw, pos, (char) (raw.length - pos)); 

    // zlib check sum of uncompressed data 
    zlib.writeInt(calcADLER32(raw)); 

    return baos.toByteArray(); 
} 

private static void writeUncompressedDeflateBlock(DataOutputStream zlib, boolean last, 
        byte[] raw, int off, char len) throws IOException 
{ 
    zlib.writeByte((byte)(last ? 1 : 0));   // Final flag, Compression type 0 
    zlib.writeByte((byte)(len & 0xFF));   // Length LSB 
    zlib.writeByte((byte)((len & 0xFF00) >> 8)); // Length MSB 
    zlib.writeByte((byte)(~len & 0xFF));   // Length 1st complement LSB 
    zlib.writeByte((byte)((~len & 0xFF00) >> 8)); // Length 1st complement MSB 
    zlib.write(raw,off,len);      // Data  
} 

private static int calcADLER32(byte[] raw) 
{ 
    int s1 = 1; 
    int s2 = 0; 
    for (int i = 0; i < raw.length; i++) 
    { 
     int abs = raw[i] >=0 ? raw[i] : (raw[i] + 256); 
     s1 = (s1 + abs) % 65521; 
     s2 = (s2 + s1) % 65521;  
    } 
    return (s2 << 16) + s1; 
} 
} 

而這是您需要調用的方法。

public static byte[] toPNG(Bitmap image) throws IOException { 

    int imageSize = image.getWidth() * image.getHeight(); 
    int[] rgbs = new int[imageSize]; 
    byte[] a, r, g, b; 
    int colorToDecode; 

    image.getARGB(rgbs, 0, image.getWidth() , 0, 0, image.getWidth(), image.getHeight()); 

    a = new byte[imageSize]; 
    r = new byte[imageSize]; 
    g = new byte[imageSize]; 
    b = new byte[imageSize]; 

    for (int i = 0; i < imageSize; i++) { 
     colorToDecode = rgbs[i]; 

     a[i] = (byte) ((colorToDecode & 0xFF000000) >>> 24); 
     r[i] = (byte) ((colorToDecode & 0x00FF0000) >>> 16); 
     g[i] = (byte) ((colorToDecode & 0x0000FF00) >>> 8); 
     b[i] = (byte) ((colorToDecode & 0x000000FF)); 
    } 

    return MinimalPNGEncoder.toPNG(image.getWidth(), image.getHeight(), a, r, g, b); 
} 

這不是我的。我非常感謝ChristianFrï¿schslin創建這個並讓其他開發者使用它。這是terms.的鏈接

在我忘記之前,這個有一個限制。它可以將位圖成功轉換爲大小小於或等於63kb的字節[],但是如果大小超過限制,轉換後的圖像將變色。

相關問題