Android Firebase图像存储-缩略图
我的android应用程序中有毕加索,所以我可以从firebase存储检索图像URL到我的recyclerview并显示出来,现在,我想添加一个占位符,以便用户可以看到图像加载的时间,但是,我想用每个应用程序的方式来做,首先像小尺寸的图像(缩略图)一样模糊图像,然后显示原始图像(不模糊),我一直在搜索堆栈溢出,我找到了很好的解决方案,比如,制作两个毕加索Stations,一个用于缩略图,然后,onsucceed方法为我带来了原始图像,但我有一个问题,我需要两个图像,首先显示原始图像的缩略图,然后显示原始完整图像,那么,我如何重新显示如果我只上传一张到服务器,我会尝试两张图片吗 这是一个我从中发现的小东西Android Firebase图像存储-缩略图,android,image,firebase,firebase-storage,Android,Image,Firebase,Firebase Storage,我的android应用程序中有毕加索,所以我可以从firebase存储检索图像URL到我的recyclerview并显示出来,现在,我想添加一个占位符,以便用户可以看到图像加载的时间,但是,我想用每个应用程序的方式来做,首先像小尺寸的图像(缩略图)一样模糊图像,然后显示原始图像(不模糊),我一直在搜索堆栈溢出,我找到了很好的解决方案,比如,制作两个毕加索Stations,一个用于缩略图,然后,onsucceed方法为我带来了原始图像,但我有一个问题,我需要两个图像,首先显示原始图像的缩略图,然后
Transformation blurTransformation = new Transformation() {
@Override
public Bitmap transform(Bitmap source) {
Bitmap blurred = Blur.fastblur(LiveImageView.this.context, source, 10);
source.recycle();
return blurred;
}
@Override
public String key() {
return "blur()";
}
};
Picasso.with(context)
.load(thumbUrl) // thumbnail url goes here
.placeholder(R.drawable.placeholder)
.resize(imageViewWidth, imageViewHeight)
.transform(blurTransformation)
.into(imageView, new Callback() {
@Override
public void onSuccess() {
Picasso.with(context)
.load(url) // image url goes here
.resize(imageViewWidth, imageViewHeight)
.placeholder(imageView.getDrawable())
.into(imageView);
}
@Override
public void onError() {
}
});
先进的坦斯克好吧,我想起来了,我得说那是一个很好的脑筋急转弯 步骤1 首先,您需要创建一个BlurJava类:
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Build;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
/**
* Created by RamithRD on 9/12/2016.
*/
public class Blur {
@SuppressLint("NewApi")
public static Bitmap fastblur(Context context, Bitmap sentBitmap, int radius) {
if (Build.VERSION.SDK_INT > 16) {
Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
final RenderScript rs = RenderScript.create(context);
final Allocation input = Allocation.createFromBitmap(rs, sentBitmap, Allocation.MipmapControl.MIPMAP_NONE,
Allocation.USAGE_SCRIPT);
final Allocation output = Allocation.createTyped(rs, input.getType());
final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
script.setRadius(radius /* e.g. 3.f */);
script.setInput(input);
script.forEach(output);
output.copyTo(bitmap);
return bitmap;
}
// Stack Blur v1.0 from
// http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
//
// Java Author: Mario Klingemann <mario at quasimondo.com>
// http://incubator.quasimondo.com
// created Feburary 29, 2004
// Android port : Yahel Bouaziz <yahel at kayenko.com>
// http://www.kayenko.com
// ported april 5th, 2012
// This is a compromise between Gaussian Blur and Box blur
// It creates much better looking blurs than Box Blur, but is
// 7x faster than my Gaussian Blur implementation.
//
// I called it Stack Blur because this describes best how this
// filter works internally: it creates a kind of moving stack
// of colors whilst scanning through the image. Thereby it
// just has to add one new block of color to the right side
// of the stack and remove the leftmost color. The remaining
// colors on the topmost layer of the stack are either added on
// or reduced by one, depending on if they are on the right or
// on the left side of the stack.
//
// If you are using this algorithm in your code please add
// the following line:
//
// Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
if (radius < 1) {
return (null);
}
int w = bitmap.getWidth();
int h = bitmap.getHeight();
int[] pix = new int[w * h];
bitmap.getPixels(pix, 0, w, 0, 0, w, h);
int wm = w - 1;
int hm = h - 1;
int wh = w * h;
int div = radius + radius + 1;
int r[] = new int[wh];
int g[] = new int[wh];
int b[] = new int[wh];
int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
int vmin[] = new int[Math.max(w, h)];
int divsum = (div + 1) >> 1;
divsum *= divsum;
int dv[] = new int[256 * divsum];
for (i = 0; i < 256 * divsum; i++) {
dv[i] = (i / divsum);
}
yw = yi = 0;
int[][] stack = new int[div][3];
int stackpointer;
int stackstart;
int[] sir;
int rbs;
int r1 = radius + 1;
int routsum, goutsum, boutsum;
int rinsum, ginsum, binsum;
for (y = 0; y < h; y++) {
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
for (i = -radius; i <= radius; i++) {
p = pix[yi + Math.min(wm, Math.max(i, 0))];
sir = stack[i + radius];
sir[0] = (p & 0xff0000) >> 16;
sir[1] = (p & 0x00ff00) >> 8;
sir[2] = (p & 0x0000ff);
rbs = r1 - Math.abs(i);
rsum += sir[0] * rbs;
gsum += sir[1] * rbs;
bsum += sir[2] * rbs;
if (i > 0) {
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
} else {
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
}
}
stackpointer = radius;
for (x = 0; x < w; x++) {
r[yi] = dv[rsum];
g[yi] = dv[gsum];
b[yi] = dv[bsum];
rsum -= routsum;
gsum -= goutsum;
bsum -= boutsum;
stackstart = stackpointer - radius + div;
sir = stack[stackstart % div];
routsum -= sir[0];
goutsum -= sir[1];
boutsum -= sir[2];
if (y == 0) {
vmin[x] = Math.min(x + radius + 1, wm);
}
p = pix[yw + vmin[x]];
sir[0] = (p & 0xff0000) >> 16;
sir[1] = (p & 0x00ff00) >> 8;
sir[2] = (p & 0x0000ff);
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
rsum += rinsum;
gsum += ginsum;
bsum += binsum;
stackpointer = (stackpointer + 1) % div;
sir = stack[(stackpointer) % div];
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
rinsum -= sir[0];
ginsum -= sir[1];
binsum -= sir[2];
yi++;
}
yw += w;
}
for (x = 0; x < w; x++) {
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
yp = -radius * w;
for (i = -radius; i <= radius; i++) {
yi = Math.max(0, yp) + x;
sir = stack[i + radius];
sir[0] = r[yi];
sir[1] = g[yi];
sir[2] = b[yi];
rbs = r1 - Math.abs(i);
rsum += r[yi] * rbs;
gsum += g[yi] * rbs;
bsum += b[yi] * rbs;
if (i > 0) {
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
} else {
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
}
if (i < hm) {
yp += w;
}
}
yi = x;
stackpointer = radius;
for (y = 0; y < h; y++) {
// Preserve alpha channel: ( 0xff000000 & pix[yi] )
pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];
rsum -= routsum;
gsum -= goutsum;
bsum -= boutsum;
stackstart = stackpointer - radius + div;
sir = stack[stackstart % div];
routsum -= sir[0];
goutsum -= sir[1];
boutsum -= sir[2];
if (x == 0) {
vmin[y] = Math.min(y + r1, hm) * w;
}
p = x + vmin[y];
sir[0] = r[p];
sir[1] = g[p];
sir[2] = b[p];
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
rsum += rinsum;
gsum += ginsum;
bsum += binsum;
stackpointer = (stackpointer + 1) % div;
sir = stack[stackpointer];
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
rinsum -= sir[0];
ginsum -= sir[1];
binsum -= sir[2];
yi += w;
}
}
bitmap.setPixels(pix, 0, w, 0, 0, w, h);
return (bitmap);
}
}
步骤3
使用毕加索加载图像:
Picasso.with(context)
.load(url) // thumnail url goes here
.transform(blurTransformation)
.into(imageView, new Callback() {
@Override
public void onSuccess() {
Picasso.with(context)
.load(url) // original image url goes here
.placeholder(imageView.getDrawable())
.into(imageView);
}
@Override
public void onError() {
}
});
当我启动应用程序时,它首先显示原始图像,但模糊,然后显示原始图像
为了提高效率,我需要做的技巧是,在将图像上载到Firebase存储时,您可以缩小图像的大小并将其与原始图像一起存储(使用Firebase数据库可以轻松完成,只需存储缩略图和原始图像的下载URL)通过毕加索加载图像时,您可以先加载缩略图,然后再加载原始图像
出于测试目的,我只使用了相同的Url
对于重新缩放图像,您会找到一些很好的答案
以下是我的示例应用程序中的GIF:
(来源:)您是否尝试过通过XML将占位符图像添加到ImageView(将占位符图像添加到drawable文件夹中)然后从毕加索加载原始图像?或者,如果您想将毕加索用于这两个图像,请手动将占位符图像上载到Firebase存储,并从Firebase控制台获取下载URL。@RamithDR是的,我可以在我的绘图表中放置标准图像,但我不想看到标准图像,我想隐藏上载到服务器的图像在完全加载之前,它是一个模糊的缩略图,看看这个。记住,上传到aerver的pica是随机的,每次都不一样,这就是为什么我不能放置标准占位符的原因。请在下面查看我的答案。准确的答案,做得很好,非常感谢!还有一个问题@RamithDR,假设我上传了2张图片,而不是o正如你所说,在我的存储中,只需将缩略图url带到.thumbnail(url)就会更容易然后是原始图片,而不是相同的图片模糊然后显示,我这样做的原因是因为我只想在用户可以看到最终结果之前快速加载预览,只是为了加快速度,我不想让他们等到图像加载,因为他们看到的只是一个空白,然后在2秒后,我图像弹出。@ArmandoBarreda是的,正如我所说的,如果你要上传两张缩略图和原始图片的图像,请确保在上传之前缩小缩略图的图像大小,然后模糊的缩略图将以非常快的速度显示给用户,图像质量是否低并不重要,因为它是模糊的;)看看这个[链接]()如果你转到json中的图像子级,你可以看到它存储了3个不同的图像,低分辨率、缩略图和全分辨率,宽度和高度各有3个不同,然后应用程序只需在全图像之前调用缩略图,这就是我指的:)@RamithDR
Picasso.with(context)
.load(url) // thumnail url goes here
.transform(blurTransformation)
.into(imageView, new Callback() {
@Override
public void onSuccess() {
Picasso.with(context)
.load(url) // original image url goes here
.placeholder(imageView.getDrawable())
.into(imageView);
}
@Override
public void onError() {
}
});