在 Xamarin c# 中以 .bmp 格式保存裁剪图像
Save a cropped image in .bmp format in Xamarin c#
你好,我是 xamarin 表单的新手,我有一个应用程序可以让你通过相机拍照,然后我给了一个矩形框来裁剪捕获的图像...我已经为 xamarin 编写了代码 android 所有这一切都很好,我最终也可以将图像保存为 JPG 或 PNG。
但我想将最终图像保存为.bmp 文件。
private void SaveOutput(Bitmap croppedImage)
{
if (saveUri != null)
{
try
{
using var outputStream = ContentResolver.OpenOutputStream(saveUri);
if (outputStream != null)
{
croppedImage.Compress(Bitmap.CompressFormat.Jpeg, 75, outputStream);
}
}
在此函数中,croppedImage 位图被压缩为 jpg。
相反,我想将该位图保存为 .bmp file.i 已经看了很多,但还没有找到任何解决方案。
有人可以建议我能做什么吗?
这是一个与原生 Android 类似的 issue 。您可以将解决方案转换为 C#,如下所示
public class AndroidBmpUtil
{
private readonly int BMP_WIDTH_OF_TIMES = 4;
private readonly int BYTE_PER_PIXEL = 3;
/**
* Android Bitmap Object to Window's v3 24bit Bmp Format File
* @param orgBitmap
* @param filePath
* @return file saved result
*/
public bool Save(Bitmap orgBitmap, string filePath)
{
if (orgBitmap == null)
{
return false;
}
if (filePath == null)
{
return false;
}
var isSaveSuccess = true;
//image size
var width = orgBitmap.Width;
var height = orgBitmap.Height;
//image dummy data size
//reason : bmp file's width equals 4's multiple
var dummySize = 0;
byte[] dummyBytesPerRow = null;
var hasDummy = false;
if (isBmpWidth4Times(width))
{
hasDummy = true;
dummySize = BMP_WIDTH_OF_TIMES - width%BMP_WIDTH_OF_TIMES;
dummyBytesPerRow = new byte[dummySize*BYTE_PER_PIXEL];
for (var i = 0; i < dummyBytesPerRow.Length; i++)
{
dummyBytesPerRow[i] = 0xFF;
}
}
var pixels = new int[width*height];
var imageSize = pixels.Length*BYTE_PER_PIXEL + height*dummySize*BYTE_PER_PIXEL;
var imageDataOffset = 0x36;
var fileSize = imageSize + imageDataOffset;
//Android Bitmap Image Data
orgBitmap.GetPixels(pixels, 0, width, 0, 0, width, height);
//ByteArrayOutputStream baos = new ByteArrayOutputStream(fileSize);
var buffer = ByteBuffer.Allocate(fileSize);
try
{
/**
* BITMAP FILE HEADER Write Start
**/
buffer.Put(0x42);
buffer.Put(0x4D);
//size
buffer.Put(WriteInt(fileSize));
//reserved
buffer.Put(WriteShort(0));
buffer.Put(WriteShort(0));
//image data start offset
buffer.Put(WriteInt(imageDataOffset));
/** BITMAP FILE HEADER Write End */
//*******************************************
/** BITMAP INFO HEADER Write Start */
//size
buffer.Put(WriteInt(0x28));
//width, height
buffer.Put(WriteInt(width));
buffer.Put(WriteInt(height));
//planes
buffer.Put(WriteShort(1));
//bit count
buffer.Put(WriteShort(24));
//bit compression
buffer.Put(WriteInt(0));
//image data size
buffer.Put(WriteInt(imageSize));
//horizontal resolution in pixels per meter
buffer.Put(WriteInt(0));
//vertical resolution in pixels per meter (unreliable)
buffer.Put(WriteInt(0));
buffer.Put(WriteInt(0));
buffer.Put(WriteInt(0));
/** BITMAP INFO HEADER Write End */
var row = height;
var col = width;
var startPosition = 0;
var endPosition = 0;
while (row > 0)
{
startPosition = (row - 1)*col;
endPosition = row*col;
for (var i = startPosition; i < endPosition; i++)
{
buffer.Put(Write24BitForPixcel(pixels[i]));
if (hasDummy)
{
if (isBitmapWidthLastPixcel(width, i))
{
buffer.Put(dummyBytesPerRow);
}
}
}
row--;
}
var fos = new FileOutputStream(filePath);
fos.Write(new byte[buffer.Remaining()]);
fos.Close();
}
catch (Exception e1)
{
isSaveSuccess = false;
}
finally
{
}
return isSaveSuccess;
}
/**
* Is last pixel in Android Bitmap width
* @param width
* @param i
* @return
*/
private bool isBitmapWidthLastPixcel(int width, int i)
{
return i > 0 && i%(width - 1) == 0;
}
/**
* BMP file is a multiples of 4?
* @param width
* @return
*/
private bool isBmpWidth4Times(int width)
{
return width%BMP_WIDTH_OF_TIMES > 0;
}
/**
* Write integer to little-endian
* @param value
* @return
* @throws IOException
*/
private byte[] WriteInt(int value)
{
var b = new byte[4];
b[0] = (byte) (value & 0x000000FF);
b[1] = (byte) ((value & 0x0000FF00) >> 8);
b[2] = (byte) ((value & 0x00FF0000) >> 16);
b[3] = (byte) ((value & 0xFF000000) >> 24);
return b;
}
/**
* Write integer pixel to little-endian byte array
* @param value
* @return
* @throws IOException
*/
private byte[] Write24BitForPixcel(int value)
{
var
b = new byte[3];
b[0] = (byte) (value & 0x000000FF);
b[1] = (byte) ((value & 0x0000FF00) >> 8);
b[2] = (byte) ((value & 0x00FF0000) >> 16);
return b;
}
/**
* Write short to little-endian byte array
* @param value
* @return
* @throws IOException
*/
private byte[] WriteShort(short value)
{
var
b = new byte[2];
b[0] = (byte) (value & 0x00FF);
b[1] = (byte) ((value & 0xFF00) >> 8);
return b;
}
}
你好,我是 xamarin 表单的新手,我有一个应用程序可以让你通过相机拍照,然后我给了一个矩形框来裁剪捕获的图像...我已经为 xamarin 编写了代码 android 所有这一切都很好,我最终也可以将图像保存为 JPG 或 PNG。 但我想将最终图像保存为.bmp 文件。
private void SaveOutput(Bitmap croppedImage) {
if (saveUri != null)
{
try
{
using var outputStream = ContentResolver.OpenOutputStream(saveUri);
if (outputStream != null)
{
croppedImage.Compress(Bitmap.CompressFormat.Jpeg, 75, outputStream);
}
}
在此函数中,croppedImage 位图被压缩为 jpg。 相反,我想将该位图保存为 .bmp file.i 已经看了很多,但还没有找到任何解决方案。 有人可以建议我能做什么吗?
这是一个与原生 Android 类似的 issue 。您可以将解决方案转换为 C#,如下所示
public class AndroidBmpUtil
{
private readonly int BMP_WIDTH_OF_TIMES = 4;
private readonly int BYTE_PER_PIXEL = 3;
/**
* Android Bitmap Object to Window's v3 24bit Bmp Format File
* @param orgBitmap
* @param filePath
* @return file saved result
*/
public bool Save(Bitmap orgBitmap, string filePath)
{
if (orgBitmap == null)
{
return false;
}
if (filePath == null)
{
return false;
}
var isSaveSuccess = true;
//image size
var width = orgBitmap.Width;
var height = orgBitmap.Height;
//image dummy data size
//reason : bmp file's width equals 4's multiple
var dummySize = 0;
byte[] dummyBytesPerRow = null;
var hasDummy = false;
if (isBmpWidth4Times(width))
{
hasDummy = true;
dummySize = BMP_WIDTH_OF_TIMES - width%BMP_WIDTH_OF_TIMES;
dummyBytesPerRow = new byte[dummySize*BYTE_PER_PIXEL];
for (var i = 0; i < dummyBytesPerRow.Length; i++)
{
dummyBytesPerRow[i] = 0xFF;
}
}
var pixels = new int[width*height];
var imageSize = pixels.Length*BYTE_PER_PIXEL + height*dummySize*BYTE_PER_PIXEL;
var imageDataOffset = 0x36;
var fileSize = imageSize + imageDataOffset;
//Android Bitmap Image Data
orgBitmap.GetPixels(pixels, 0, width, 0, 0, width, height);
//ByteArrayOutputStream baos = new ByteArrayOutputStream(fileSize);
var buffer = ByteBuffer.Allocate(fileSize);
try
{
/**
* BITMAP FILE HEADER Write Start
**/
buffer.Put(0x42);
buffer.Put(0x4D);
//size
buffer.Put(WriteInt(fileSize));
//reserved
buffer.Put(WriteShort(0));
buffer.Put(WriteShort(0));
//image data start offset
buffer.Put(WriteInt(imageDataOffset));
/** BITMAP FILE HEADER Write End */
//*******************************************
/** BITMAP INFO HEADER Write Start */
//size
buffer.Put(WriteInt(0x28));
//width, height
buffer.Put(WriteInt(width));
buffer.Put(WriteInt(height));
//planes
buffer.Put(WriteShort(1));
//bit count
buffer.Put(WriteShort(24));
//bit compression
buffer.Put(WriteInt(0));
//image data size
buffer.Put(WriteInt(imageSize));
//horizontal resolution in pixels per meter
buffer.Put(WriteInt(0));
//vertical resolution in pixels per meter (unreliable)
buffer.Put(WriteInt(0));
buffer.Put(WriteInt(0));
buffer.Put(WriteInt(0));
/** BITMAP INFO HEADER Write End */
var row = height;
var col = width;
var startPosition = 0;
var endPosition = 0;
while (row > 0)
{
startPosition = (row - 1)*col;
endPosition = row*col;
for (var i = startPosition; i < endPosition; i++)
{
buffer.Put(Write24BitForPixcel(pixels[i]));
if (hasDummy)
{
if (isBitmapWidthLastPixcel(width, i))
{
buffer.Put(dummyBytesPerRow);
}
}
}
row--;
}
var fos = new FileOutputStream(filePath);
fos.Write(new byte[buffer.Remaining()]);
fos.Close();
}
catch (Exception e1)
{
isSaveSuccess = false;
}
finally
{
}
return isSaveSuccess;
}
/**
* Is last pixel in Android Bitmap width
* @param width
* @param i
* @return
*/
private bool isBitmapWidthLastPixcel(int width, int i)
{
return i > 0 && i%(width - 1) == 0;
}
/**
* BMP file is a multiples of 4?
* @param width
* @return
*/
private bool isBmpWidth4Times(int width)
{
return width%BMP_WIDTH_OF_TIMES > 0;
}
/**
* Write integer to little-endian
* @param value
* @return
* @throws IOException
*/
private byte[] WriteInt(int value)
{
var b = new byte[4];
b[0] = (byte) (value & 0x000000FF);
b[1] = (byte) ((value & 0x0000FF00) >> 8);
b[2] = (byte) ((value & 0x00FF0000) >> 16);
b[3] = (byte) ((value & 0xFF000000) >> 24);
return b;
}
/**
* Write integer pixel to little-endian byte array
* @param value
* @return
* @throws IOException
*/
private byte[] Write24BitForPixcel(int value)
{
var
b = new byte[3];
b[0] = (byte) (value & 0x000000FF);
b[1] = (byte) ((value & 0x0000FF00) >> 8);
b[2] = (byte) ((value & 0x00FF0000) >> 16);
return b;
}
/**
* Write short to little-endian byte array
* @param value
* @return
* @throws IOException
*/
private byte[] WriteShort(short value)
{
var
b = new byte[2];
b[0] = (byte) (value & 0x00FF);
b[1] = (byte) ((value & 0xFF00) >> 8);
return b;
}
}