- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在使用 Glide 加载图像、调整图像大小并通过 SimpleTarget<Bitmap>
将其保存到文件中.这些图像将上传到 Amazon S3,但这不是重点。我在上传之前调整图像大小,以尽可能多地节省用户的带宽。因为我的应用程序需要一张 1024 像素宽的图像就足够了,所以我使用以下代码来实现:
final String to = getMyImageUrl();
final Context appCtx = context.getApplicationContext();
Glide.with(appCtx)
.load(sourceImageUri)
.asBitmap()
.into(new SimpleTarget<Bitmap>(1024, 768) {
@Override
public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
try {
FileOutputStream out = new FileOutputStream(to);
resource.compress(Bitmap.CompressFormat.JPEG, 70, out);
out.flush();
out.close();
MediaScannerConnection.scanFile(appCtx, new String[]{to}, null, null);
} catch (IOException e) {
e.printStackTrace();
}
}
});
它几乎完美地工作,但生成的图像的大小不是 1024 像素宽。使用尺寸为 4160 x 2340 像素的源图像对其进行测试,结果保存图像的尺寸为 2080 x 1170 像素。
我试过使用 width
和 height
传递给 new SimpleTarget<Bitmap>(350, 350)
的参数使用这些参数,生成的图像尺寸为 1040 x 585 像素。
我真的不知道该怎么做才能让 Glide 尊重传递的维度。事实上,我想按比例调整图像的大小,以便将较大的尺寸(宽度或高度)限制为 1024 像素,而较小的尺寸相应地调整大小(我相信我必须找到一种方法来获取原始图像尺寸,然后将宽度和高度传递给 SimpleTarget
,但为此我需要 Glide 尊重传递的宽度和高度!)。
有人知道发生了什么事吗?我正在使用 Glide 3.7.0。
由于这个问题本身可能对尝试使用 Glide 调整大小和保存图像的人有用,我相信提供我的实际“解决方案”符合每个人的利益,该解决方案依赖于新的 SimpleTarget
。自动保存调整大小的图像的实现:
import android.graphics.Bitmap;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.SimpleTarget;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileTarget extends SimpleTarget<Bitmap> {
public FileTarget(String fileName, int width, int height) {
this(fileName, width, height, Bitmap.CompressFormat.JPEG, 70);
}
public FileTarget(String fileName, int width, int height, Bitmap.CompressFormat format, int quality) {
super(width, height);
this.fileName = fileName;
this.format = format;
this.quality = quality;
}
String fileName;
Bitmap.CompressFormat format;
int quality;
public void onResourceReady(Bitmap bitmap, GlideAnimation anim) {
try {
FileOutputStream out = new FileOutputStream(fileName);
bitmap.compress(format, quality, out);
out.flush();
out.close();
onFileSaved();
} catch (IOException e) {
e.printStackTrace();
onSaveException(e);
}
}
public void onFileSaved() {
// do nothing, should be overriden (optional)
}
public void onSaveException(Exception e) {
// do nothing, should be overriden (optional)
}
}
使用起来很简单:
Glide.with(appCtx)
.load(sourceImageUri)
.asBitmap()
.into(new FileTarget(to, 1024, 768) {
@Override
public void onFileSaved() {
// do anything, or omit this override if you want
}
});
最佳答案
经过一夜安眠,我终于明白了!我在 Glide 的 github 页面上偶然发现了一个有答案的问题,但我没有意识到:我在解释中遗漏了一些东西,在休息 10 小时后我现在完全理解了。永远不要低估 sleep 的力量!但我离题了。这是在 Glide's Github issue tracker 上找到的答案:
Sizing the image usually has two phases:
- Decoding/Downsampler read image from stream with inSampleSize
- Transforming/BitmapTransformation take the Bitmap and match the exact target size
The decoding is always needed and is included in the flow, the default case is to match the target size with the "at least" downsampler, so when it comes to the transformation the image can be downsized more without quality loss (each pixel in the source will match at least 1.0 pixels and at most ~1.999 pixels) this can be controlled by asBitmap().at least|atMost|asIs|decoder(with downsampler)
The transformation and target size is automatic by default, but only when using a ViewTarget. When you load into an ImageView the size of that will be detected even when it has match_parent. Also if there's no explicit transformation there'll be one applied from scaleType. Thus results in a pixel perfect Bitmap for that image, meaning 1 pixel in Bitmap = 1 pixel on screen resulting in the best possible quality with the best memory usage and fast rendering (because there's no pixel mapping needed when drawing the image).
With a SimpleTarget you take on these responsibilities by providing a size on the constructor or via override() or implementing getSize if the sizing info is async-ly available only.
To fix your load add a transformation: .fitCenter|centerCrop(), your current applied transformation is .dontTransform() (Answer by Róbert Papp)
因为这个,我对这个答案感到困惑:
With a SimpleTarget you take on these responsibilities by providing a size on the constructor or via override() or implementing getSize if the sizing info is async-ly available only.
由于我超过了尺码,所以我认为我已经得到了这个尺寸,应该尊重这样的尺码。我错过了这个重要的概念:
- Decoding/Downsampler read image from stream with inSampleSize
- Transforming/BitmapTransformation take the Bitmap and match the exact target size
还有这个:
To fix your load add a transformation: .fitCenter|centerCrop(), your current applied transformation is .dontTransform()
现在我把它拼凑起来了,这是有道理的。 Glide 只是对图像进行下采样(如 Róbert 所解释的调整图像大小流程的第一步),这给出了具有近似尺寸的图像。不得不说Glide在这方面是非常聪明的。通过在调整大小之前使用下采样方法,可以避免在内存中使用不必要的大位图并提高调整大小的质量,因为下采样到精确大小会损害太多“重要”像素!
由于我没有对这个加载管道应用任何转换,因此在第一步(下采样)中停止了尺寸调整流程,并且生成的图像只有我预期目标尺寸的近似尺寸。
为了解决这个问题,我只是应用了一个 .fitCenter()
转换,如下所示:
Glide.with(appCtx)
.load(sourceImageUri)
.asBitmap()
.fitCenter()
.into(new FileTarget(to, 1024, 768) {
@Override
public void onFileSaved() {
// do anything, or omit this override if you want
}
});
生成的图像现在具有 1024 x 576 像素的尺寸,这正是我所期望的。
Glide 是一个非常酷的库!
关于java - 滑动加载到 SimpleTarget<Bitmap> 中不遵守指定的宽度和高度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37847987/
我需要将文本放在 中在一个 Div 中,在另一个 Div 中,在另一个 Div 中。所以这是它的样子: #document Change PIN
奇怪的事情发生了。 我有一个基本的 html 代码。 html,头部, body 。(因为我收到了一些反对票,这里是完整的代码) 这是我的CSS: html { backgroun
我正在尝试将 Assets 中的一组图像加载到 UICollectionview 中存在的 ImageView 中,但每当我运行应用程序时它都会显示错误。而且也没有显示图像。 我在ViewDidLoa
我需要根据带参数的 perl 脚本的输出更改一些环境变量。在 tcsh 中,我可以使用别名命令来评估 perl 脚本的输出。 tcsh: alias setsdk 'eval `/localhome/
我使用 Windows 身份验证创建了一个新的 Blazor(服务器端)应用程序,并使用 IIS Express 运行它。它将显示一条消息“Hello Domain\User!”来自右上方的以下 Ra
这是我的方法 void login(Event event);我想知道 Kotlin 中应该如何 最佳答案 在 Kotlin 中通配符运算符是 * 。它指示编译器它是未知的,但一旦知道,就不会有其他类
看下面的代码 for story in book if story.title.length < 140 - var story
我正在尝试用 C 语言学习字符串处理。我写了一个程序,它存储了一些音乐轨道,并帮助用户检查他/她想到的歌曲是否存在于存储的轨道中。这是通过要求用户输入一串字符来完成的。然后程序使用 strstr()
我正在学习 sscanf 并遇到如下格式字符串: sscanf("%[^:]:%[^*=]%*[*=]%n",a,b,&c); 我理解 %[^:] 部分意味着扫描直到遇到 ':' 并将其分配给 a。:
def char_check(x,y): if (str(x) in y or x.find(y) > -1) or (str(y) in x or y.find(x) > -1):
我有一种情况,我想将文本文件中的现有行包含到一个新 block 中。 line 1 line 2 line in block line 3 line 4 应该变成 line 1 line 2 line
我有一个新项目,我正在尝试设置 Django 调试工具栏。首先,我尝试了快速设置,它只涉及将 'debug_toolbar' 添加到我的已安装应用程序列表中。有了这个,当我转到我的根 URL 时,调试
在 Matlab 中,如果我有一个函数 f,例如签名是 f(a,b,c),我可以创建一个只有一个变量 b 的函数,它将使用固定的 a=a1 和 c=c1 调用 f: g = @(b) f(a1, b,
我不明白为什么 ForEach 中的元素之间有多余的垂直间距在 VStack 里面在 ScrollView 里面使用 GeometryReader 时渲染自定义水平分隔线。 Scrol
我想知道,是否有关于何时使用 session 和 cookie 的指南或最佳实践? 什么应该和什么不应该存储在其中?谢谢! 最佳答案 这些文档很好地了解了 session cookie 的安全问题以及
我在 scipy/numpy 中有一个 Nx3 矩阵,我想用它制作一个 3 维条形图,其中 X 轴和 Y 轴由矩阵的第一列和第二列的值、高度确定每个条形的 是矩阵中的第三列,条形的数量由 N 确定。
假设我用两种不同的方式初始化信号量 sem_init(&randomsem,0,1) sem_init(&randomsem,0,0) 现在, sem_wait(&randomsem) 在这两种情况下
我怀疑该值如何存储在“WORD”中,因为 PStr 包含实际输出。? 既然Pstr中存储的是小写到大写的字母,那么在printf中如何将其给出为“WORD”。有人可以吗?解释一下? #include
我有一个 3x3 数组: var my_array = [[0,1,2], [3,4,5], [6,7,8]]; 并想获得它的第一个 2
我意识到您可以使用如下方式轻松检查焦点: var hasFocus = true; $(window).blur(function(){ hasFocus = false; }); $(win
我是一名优秀的程序员,十分优秀!