3

アップロードする画像のサイズに制限を追加したい(現在、画像はサーバーにアップロードされています)

誰かが SDcard から画像を取得したり、カメラから画像をキャプチャしたりするときに、最大ファイル サイズ (つまり 500kb) をアップロードしたこと、または画像のサイズを小さいサイズに変更できることをユーザーに表示したいと思います。たとえば、1 MB の画像を 400 ~ 500 KB にサイズ変更します (Facebook など)。

これは、SDカードから画像を取得した後、またはカメラからキャプチャした画像を取得した後に実装したサンプルコードです。

 FileConnection file = (FileConnection)Connector.open(url);
 if(file.exists())
 {
     try{
         String fileName = url .substring(url.lastIndexOf('/') + 1);
         //String fileName = url ;
         Dialog.alert("fileName  " + fileName);
         InputStream inputStream = file.openInputStream();

         ByteArrayOutputStream bos=new ByteArrayOutputStream();
         int buffersize=1024;
         byte[] buffer=new byte[buffersize];
         int length=0;
         while((length=inputStream.read(buffer))!=-1)
         {
             bos.write(buffer,0,length);
         }
         byte[] imagedata=bos.toByteArray();
         Dialog.alert("Url  " + Url  + " Image Data Byte " + imagedata);
         HttpConnection conn = (HttpConnection) Connector.open(Url, Connector.READ_WRITE);
         conn.setRequestMethod(HttpConnection.POST);
         String boundary = "Some_Unique_Text_Also_Alphanumeric";
         conn.setRequestProperty(HttpProtocolConstants.HEADER_CONTENT_TYPE,                    
             HttpProtocolConstants.CONTENT_TYPE_MULTIPART_FORM_DATA
                                 + ";boundary=" + boundary);

             conn.setRequestProperty(HttpProtocolConstants.HEADER_CONTENT_LENGTH,
                         String.valueOf(imagedata.length));
         conn.setRequestProperty("x-rim-transcode-content", "none");

         ByteArrayOutputStream out = new ByteArrayOutputStream();
         OutputStream finalOut = conn.openOutputStream();

         String newLine = "\r\n";
         out.write(newLine.getBytes());
         out.write("--".getBytes());
         out.write(boundary.getBytes());
         out.write(newLine.getBytes());
         String contDisp = "Content-Disposition:form-data;name=\"image\";fileName=\"Image.jpg\"";
         String contEnc = "Content-Transfer-Encoding: binary";
         String contentType = "Content-Type:image/jpeg";
         out.write(contDisp.getBytes());
         out.write(newLine.getBytes());
         out.write(contentType.getBytes());
         out.write(newLine.getBytes());
         out.write(contEnc.getBytes());
         out.write(newLine.getBytes());
         out.write(newLine.getBytes());
         out.write(imagedata);
         out.write(newLine.getBytes());
         out.write("--".getBytes());
         out.write(boundary.getBytes());
         out.write("--".getBytes());
         out.write(newLine.getBytes());
         finalOut.write(out.toByteArray());

         out.flush();
         out.close();

         finalOut.flush();
         finalOut.close();
         InputStream instream=conn.openInputStream();
         int ch=0;
         StringBuffer buffesr=new StringBuffer();
         while((ch=instream.read())!=-1)
         {
             buffesr.append((char)ch);
             Dialog.alert("Uploaded");
         }
     }
     catch (Exception e) {

         Dialog.alert("Exception " + e);
     }   
 }

何か助けて??

4

1 に答える 1

5

問題は、カメラの画像では、特定のバイト単位のサイズに対応する物理的な画像サイズ (ピクセル幅 x 高さ) を予測できないことです。

アップロードできるサイズ (バイト単位) に厳密な固定制限がある場合は、次のような操作が必要になる場合があります。

  • いくつかの画像を試して、通常は 400 ~ 500 KB の制限内に収まる JPG ファイルを生成するおおよその画像サイズ (幅 x 高さ) を見つけます。

  • アプリで、カメラ画像のサイズをその物理サイズ (幅 x 高さ、ピクセル単位) に変更します。

  • 新しい JPG データのサイズを確認し、制限内に収まるかどうかを確認します

  • 収まらない場合は、元の画像を小さいサイズに再スケーリングする必要があります

ご覧のとおり、これを行うのはそれほど簡単ではありません。私が見たほとんどのサーバー ( Facebook など) は、画像の物理的な最大サイズをピクセル単位で示します (たとえば、幅または高さのいずれかの最大幅として 960 ピクセル)。それがサーバーにとって十分である場合は、BlackBerry クライアント側でコーディングする方がはるかに簡単です。

幅と高さを固定ピクセルに制限する

次のようなものを使用できます。

FileConnection file;
InputStream inputStream;

try {
    file = (FileConnection) Connector.open(url);  // JPG file:// URL
    if (file.exists())
    {
        inputStream = file.openInputStream();           
        byte[] data = IOUtilities.streamToBytes(inputStream);

        Bitmap original = Bitmap.createBitmapFromBytes(data, 0, data.length, 1);

        Bitmap scaledImg = new Bitmap(640, 480);    // maximum width and height
        original.scaleInto(scaledImg, 
                           Bitmap.FILTER_LANCZOS,   /* LANCZOS is for best quality */
                           Bitmap.SCALE_TO_FIT);  

        // http://stackoverflow.com/a/14147236/119114
        int jpegQuality = 85;
        EncodedImage encodedImg = JPEGEncodedImage.encode(scaledImg, jpegQuality);
        byte[] imageData = encodedImg.getData(); 
        // TODO: send imageData as you already were       
    }
} catch (Exception e) {
    // log exception
} finally {
    try {
        if (file != null) {
            file.close();
        }
        if (inputStream != null) {
            inputStream.close();
        }
    } catch (IOException ioe) {
        // nothing can be done here
    }
}

もちろん、この作業はすべてバックグラウンド スレッドで実行する必要があります。最終的な画像サイズがわかったら、本当に必要な場合は、次のような方法でユーザーに通知できます。

final uploadSizeKb = imageData.length / 1024;
UiApplication.getUiApplication().invokeLater(new Runnable() {
   public void run() {
      Dialog.alert(uploadSizeKb + "KB uploaded to server");
   }
});

さらなる最適化

おそらくおわかりのように、このアルゴリズムで調整できることがいくつかあります。

  • スケーリングを試みる前に、画像ファイルがすでに十分に小さいかどうかを確認することで最適化できます。(チェックfile.fileSize())

  • の代わりにBitmap.FILTER_BILINEARまたはを使用すると、画像のスケーリングを高速化できます。Bitmap.FILTER_BOXBitmap.FILTER_LANCZOS

  • アップロード用に JPEG に変換し直すときに、JPEG 品質係数を 85 から変更できます。

  • で拡大/縮小するときにスペースが無駄にならないように、画像の向きを確認する必要がある場合がありますSCALE_TO_FIT。カメラ画像の向きが間違っている場合は、scaledImgビットマップの幅と高さを変更してください (例: 640x480 -> 480x640)。

  • 実際には、いくつかの手順をスキップして、画像ファイルを読み込むときに直接スケーリングできますcreateBitmapFromBytes()。最後のパラメータはスケール パラメータです。残念ながら、写真はすべて異なるため、適切な縮尺比を1 つ選択することも困難です。前述したように、サーバーが単純に最大画像サイズをピクセル単位で指定するのが一般的です。

OS < 5.0 のサポート

OS 5.0 のイメージ スケーリング API を使用できない場合は、この古いツールキットが役立ちます。

于 2013-05-31T10:31:24.017 に答える