我有一个要存储为图像的视图(例如对其进行屏幕截图)。 为此,我使用以下代码:
View view = findViewById(R.id.share_preview);
Bitmap b = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
view.draw(c);
然后将位图存储到图库中。
问题在于,保存的图像始终与视图具有相同的大小。由于视图的大小取决于手机的屏幕大小,因此每个设备上的图像大小都不同。
能否以更高的分辨率(每个设备上的分辨率相同)获取视图的图像?
我试图在绘制到画布上之前在视图上调用scaleX()和scaleY()。该视图已按比例缩放,但图像仍然具有旧尺寸(我也更改了位图的尺寸)。 然后,代码如下所示:
View view = findViewById(R.id.share_preview);
// here's the difference
view.setScaleX(2);
view.setScaleY(2);
Bitmap b = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
view.draw(c);
也许要花很长时间才能更新音阶。但是我不知道如何检查缩放的完成时间(缩放的视图也不应呈现,因为那样看起来就完全错误了。)
答案 0 :(得分:1)
这个问题可能没有绝对答案-您可能会意识到,随时在给定设备上合成视图层次结构涉及很多步骤,所有这些步骤都经过渲染以优化其在给定设备上的布局设备以及其他系统内容(如侧边栏,键盘,工具栏等);所有这些都是在特定的屏幕分辨率,像素密度和其他显示属性下呈现的。我现在还注意到,用我概述的这种方法很难捕获任何动态内容,例如文本输入。
可能会为您提供一个完全途径,使您控制的视图可以使用虚拟显示器来实现一致,标准化的“屏幕截图”。 createVirtualDisplay根据需要设置显示w,h和dpi。并提供将在其上呈现内容的表面。
mDisplayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION |
DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
mVirtualDisplay = mDisplayManager.createVirtualDisplay("MyVirtualDisplay",
WIDTH, HEIGHT, DENSITY_DPI, surface, flags);
需要提示将其绘制到表面上(可以插入各种标准示例,例如Presentation),然后将要在设备上渲染的相同视图布局充气到虚拟表面上。您可以在最近渲染后将表面数据最终传递到位图。请参阅此处以获取帮助:screenshot android presentation display/surface
最近,从API 24开始,PixelCopy可能对此有所帮助。
答案 1 :(得分:0)
将视图包装在ScrollView和HorizontalView内。
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:id="@+id/sv"
android:layout_height="match_parent">
<HorizontalScrollView
android:layout_width="match_parent"
android:id="@+id/hsv"
android:layout_height="wrap_content">
<FrameLayout
android:id="@+id/share_preview"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<!--CONTENT-->
</FrameLayout>
</HorizontalScrollView>
</ScrollView>
将运行时视图的宽度和高度设置为所需的大小。 然后,而不是从View绘制位图,而是从HorizontalScrollView绘制。
View view = findViewById(R.id.share_preview);
view.setLayoutParams(new HorizontalScrollView.LayoutParams(1600,900));
HorizontalScrollView hsv = findViewById(R.id.hsv);
Bitmap b = Bitmap.createBitmap(hsv.getWidth(), hsv.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
hsv.draw(c);
答案 2 :(得分:0)
您可以使用以下代码获取
view.setDrawingCacheEnabled(true);
view.buildDrawingCache(true);
Bitmap bitmap = shareContainer.getDrawingCache();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
File f = new File(Environment.getExternalStorageDirectory() +File.separator+ "test.jpg");
f.createNewFile();
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
fo.close();
您可以使用“ Bitmap.createScaledBitmap(originalBitmap,newWidth,newHeight,false)”来缩放位图,但是如果您尝试放大,则只能减小大小而不会造成任何损失图像将开始变得模糊
答案 3 :(得分:-1)
您可以将位图调整为特定大小,然后使用此代码可以确保每部电话中的位图大小相同:
public static boolean createFileFromBitmapForSet(Context context, String filename, Bitmap bitmapImage, boolean resize, int newSize) {
boolean result = false;
try {
Bitmap bitmapItem;
if (resize) {
int imageHeight = bitmapImage.getHeight();
int imageWidth = bitmapImage.getWidth();
int maxHeight;
int maxWidth;
if (imageWidth > imageHeight) {
maxWidth = newSize;
int per = (100 * newSize / imageWidth);
maxHeight = (imageHeight * per) / 100;
} else {
maxHeight = newSize;
int per = (100 * newSize / imageHeight);
maxWidth = (imageWidth * per) / 100;
}
bitmapItem = Bitmap.createScaledBitmap(bitmapImage, maxWidth, maxHeight, false);
} else {
bitmapItem = bitmapImage;
}
File dirctory = new File(FileManager.getExternalStorage(context) + "/tmpimgset");
if (!dirctory.exists())
dirctory.mkdirs();
File fTmp = new File(FileManager.getExternalStorage(context) + "/tmpimgset", "Size" + filename);
if (fTmp.exists()) {
fTmp.delete();
fTmp.createNewFile();
} else {
fTmp.createNewFile();
}
//Convert bitmap to byte array
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] bitmapdata = bos.toByteArray();
//write the bytes in file
FileOutputStream fos = new FileOutputStream(fTmp);
fos.write(bitmapdata);
fos.flush();
fos.close();
bitmapdata = null;
int rotate = 0;
ExifInterface exif = new ExifInterface(fTmp.getPath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
}
Matrix matrix = new Matrix();
matrix.postRotate(rotate);
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmapItem, 0, 0, bitmapItem.getWidth(), bitmapItem.getHeight(), matrix, true);
File f1 = new File(FileManager.getExternalStorage(context) + "/tmpimgset", filename);
if (f1.exists()) {
f1.delete();
f1.createNewFile();
} else {
f1.createNewFile();
}
//Convert bitmap to byte array
bos = new ByteArrayOutputStream();
rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 100 /*ignored for PNG*/, bos);
bitmapdata = bos.toByteArray();
//write the bytes in file
fos = new FileOutputStream(f1);
fos.write(bitmapdata);
fos.flush();
fos.close();
rotatedBitmap = null;
bitmapdata = null;
bitmapItem = null;
result = true;
} catch (Exception e) {
e.getMessage();
}
return result;
}