#java #android #base64 #gzip
#ява #Android #базовый 64 #gzip — файл #java #base64 #gzip
Вопрос:
В моем приложении я получаю изображение профиля пользователя, затем сохраняю его в сериализованном классе в виде строки.
Я выполняю сжатие GZIP и Base64, используя приведенный ниже код, но я не могу сделать обратное, как вы видите в getProfilePicture()
методе ниже:
private void saveBitmap(){
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
mBitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream.toByteArray();
String bitmapContent = "";
try {
bitmapContent = FileHelpers.compressAndBase64(byteArray);
//later save it...
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "Error converting bitmap to gzip and base64");
}
}
public static String compressAndBase64(byte[] byteArray)
throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream zos = new GZIPOutputStream(baos);
zos.write(byteArray);
zos.close();
byte[] bytes = baos.toByteArray();
return Base64.encodeToString(bytes, Base64.DEFAULT);
}
Теперь я хочу преобразовать его обратно в растровое изображение … но пока мне это не удалось.
Шаги заключаются в обратном декодировании строки из Base64 в массив байт, затем распаковке массива байт и преобразовании в растровое изображение.
public Bitmap getProfilePicture(){
if(getProfilePhotoBase64() != null) {
byte[] decoded = Base64.decode(mProfilePhotoBase64.getBytes(), Base64.DEFAULT);
final int BUFFER_SIZE = 32;
ByteArrayInputStream is = new ByteArrayInputStream(decoded);
GZIPInputStream gis = null;
try {
gis = new GZIPInputStream(is, BUFFER_SIZE);
} catch (IOException e) {
e.printStackTrace();
}
StringBuilder string = new StringBuilder();
byte[] data = new byte[BUFFER_SIZE];
int bytesRead;
try {
while ((bytesRead = gis.read(data)) != -1) {
string.append(new String(data, 0, bytesRead));
}
} catch (IOException e) {
e.printStackTrace();
}
try {
gis.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
byte[] byteArray = string.toString().getBytes();
Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0,byteArray.length);
if(bitmap != null) {
return bitmap;
} else {
return null;
}
}
return null;
}
Это сообщение об ошибке, которое я получаю, используя приведенный выше код:
--- SkImageDecoder::Factory returned null
Я могу сделать это довольно легко на PHP, но чертовски сложно заставить его работать на Java!
if(isset($_POST["photo"])) {
$photoContent = $_POST["photo"];
$photo = imap_base64 ($photoContent);
$photo = gzdecode($photo);
$filename = $_POST["username"].".png";
$dir = SITE_ROOT_PATH."/images/".$user."/".$filename;
file_force_contents($dir, $photo);
} else {
$filename = "NO_PROFILE_PHOTO";
}
Ответ №1:
Хорошо, мне удалось решить проблему таким образом:
/**
* IMPORTANT NOTE!!!!!!!!!!!!!!
* String is first converted to byte array, then compressed using GZIP and then
* the resulting byte array is encoded to Base64.DEFAULT
* @return
*/
public String getProfilePhotoBase64() {
return mProfilePhotoBase64;
}
public Bitmap getProfilePicture(){
if(getProfilePhotoBase64() != null) {
byte[] decoded = Base64.decode(mProfilePhotoBase64.getBytes(), Base64.DEFAULT);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ByteArrayInputStream bis = new ByteArrayInputStream(decoded);
GZIPInputStream zis = null;
try {
zis = new GZIPInputStream(bis);
byte[] tmpBuffer = new byte[256];
int n;
while ((n = zis.read(tmpBuffer)) >= 0) {
bos.write(tmpBuffer, 0, n);
}
zis.close();
} catch (IOException e) {
e.printStackTrace();
}
Bitmap bitmap = BitmapFactory.decodeByteArray(bos.toByteArray(), 0
, bos.toByteArray().length);
if(bitmap != null) {
return bitmap;
} else {
return null;
}
}
return null;
}
Комментарии:
1. Вы должны рассказать, что вы изменили и почему.
Ответ №2:
И в чем именно проблема? compressAndBase64() вернет пустую строку в виде boas.toByteArray() вернет 0 байт, так как boas только что создан и, следовательно, пуст. Вам не нужно создавать boas. Просто измените
return Base64.encodeToString(bytes, Base64.DEFAULT);
Для
return Base64.encodeToString(byteArray, Base64.DEFAULT);
Комментарии:
1.
boas.toByteArray()
было объявлено ранее, поэтому оно работает довольно хорошо, оно сжимает и использует base64 растровое изображение, но я не могу сделать обратное. Я могу распаковать base64 и gzip в php, так что код сжатия работает просто отлично.2. Извините. Я проследил, чтобы вы заархивировали ByteArray в boas. Но если бы я использовал encodeToString для кодирования, то я бы использовал decodeFromString для декодирования. Или используйте пару encode()/ decode().
3. Такого метода не существует (если это имеет какое-либо значение)
4. Измените
Base64.decode(mProfilePhotoBase64.getBytes(),
наBase64.decode(mProfilePhotoBase64,
.5. О, я понимаю… Вы используете StringBuilder и обрабатываете байты вашего изображения как строку. Ну, вы не можете этого сделать. Лучше поместить байты данных, считываемые непосредственно в ByteArray.