How to limit part size of MultipartEntity - httpclient

Is there some way to limit the parts size sended on a MultipartEntity from the org.apache.http.entity.mime.MultipartEntity ? I need limit this size to 2 MB.
Thanks!

While sending any file you must have tu reduce size.
Here decodeFile() function will reduce the size of image, when we convert it to bitmap to show selected image. If we send file as it is then large size of image can crash your application. you require 2 MB of size, Yes you can:
public void decodeFile(String filePath) {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, o);
// The new size we want to scale to
final int REQUIRED_SIZE = 2048;
// Find the correct scale value. It should be the power of 2.
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true) {
if (width_tmp < REQUIRED_SIZE && height_tmp < REQUIRED_SIZE)
break;
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
bitmap = BitmapFactory.decodeFile(filePath, o2);
imgView.setImageBitmap(bitmap);
Also If you want to upload the full sized image then, just use the filePath.
entity.addPart("uploaded", new FileBody(new File(filepath)));

Related

Converting grayscale 1D list of Image Pixels to Grayscale Image Dart

I am trying to convert a binary mask predicted with the pytorch_mobile package to an image I can show in my app.
The Prediction I receive is a 1-Dimensional list containing the predictions that my model spits out, these are negative for pixels assigned to the background and positive for pixels assigned to the area of interest. After this, I create a list that assigns the value 0 to all previously negative values, and 255 to all previously positive values yielding a 1-Dimensional list containing the values 0 or 255 depending on what the pixel was classified as.
The image prediction is a size of 512x512 pixels, and the length of the list is subsequently 262,144.
How would I be able to convert this list into an image that I could save to storage or show via the flutter UI?
Here is my current code:
customModel = await PyTorchMobile
.loadModel('assets/segmentation_model.pt');
result_list = [];
File image = File(filePath);
List prediction = await customModel.getImagePredictionList(image, 512, 512);
prediction.forEach((element) {
if (element >0){
result_list.add(255);
}else if(element <= 0){
result_list.add(0);
}
});
result_list_Uint8 = Uint8List.fromList(result_list);
The following should do the trick. Just use Image.setPixelSafe to set every pixel in the image and then convert it to a Flutter Image widget with encodePng and Image.memory.
import 'package:image/image.dart' as im;
...
final img = im.Image(512, 512);
for (var i = 0, len = 512; i < len; i++) {
for (var j = 0, len = 512; j < len; j++) {
final color = result_list_Uint8[i * 512 + j] == 0 ? 0 : 0xffffff;
img.setPixelSafe(i, j, 0xff000000 | color);
}
}
final pngBytes = Uint8List.fromList(im.encodePng(img));
photoImage = Image.memory(pngBytes);

MeshData GetVertexData has the incorrect length

I'm trying to optimize some mesh generation using MeshData & the Job System, but for some reason when I try to use 2 params in meshData.SetVertexBufferParams, the resulting meshData.GetVertexData is half the length it should be (I set the vertex count to 5120, but the resulting VertexData NativeArray is only 2560 items long).
When I force it to be double the length (SetVertexBufferParams(numVerts * 2, ...)), it creates a mesh that appears to treat the norms and vert positions as all position data and also makes the screen go black so no screen shot.
Here's my code:
// generate 256 height values
int[] arr = new int[256];
for (int i = 0; i < arr.Length; i++)
{
arr[i] = (int) (Mathf.PerlinNoise(i / 16 / 16f, i % 16 / 16f) * 5);
}
// put it in a NativeArray
NativeArray<int> heights = new NativeArray<int>(arr, Allocator.TempJob);
// 4 verts per face * 5 faces = 20
int numVerts = heights.Length * 20; // this value is always 5120
// 2 tris per face * 5 daces * 3 indices = 30
int indices = heights.Length * 30;
// MeshData setup
Mesh.MeshDataArray meshDataArray = Mesh.AllocateWritableMeshData(1);
Mesh.MeshData meshData = meshDataArray[0];
meshData.SetVertexBufferParams(numVerts,
new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3, stream:0),
new VertexAttributeDescriptor(VertexAttribute.Normal, VertexAttributeFormat.Float32, 3, stream:1)
);
meshData.SetIndexBufferParams(indices, IndexFormat.UInt16);
// Create job
Job job = new Job
{
Heights = heights,
MeshData = meshData
};
// run job
job.Schedule().Complete();
// struct I'm using for vertex data
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct VData
{
public float3 Vert;
public float3 Norm;
}
// Here's some parts of the job
public struct Job : IJob
{
[ReadOnly]
public NativeArray<int> Heights;
public Mesh.MeshData MeshData;
public void Execute()
{
NativeArray<VData> Verts = MeshData.GetVertexData<VData>();
NativeArray<ushort> Tris = MeshData.GetIndexData<ushort>();
// loops from 0 to 255
for (int i = 0; i < Heights.Length; i++)
{
ushort t1 = (ushort)(w1 + 16);
// This indicates that Verts.Length is 2560 when it should be 5120
Debug.Log(Verts.Length);
int t = i * 30; // tris
int height = Heights[i];
// x and y coordinate in chunk
int x = i / 16;
int y = i % 16;
float3 up = new float3(0, 1, 0);
// This throws and index out of bounds error because t1 becomes larger than Verts.Length
Verts[t1] = new VData { Vert = new float3(x + 1, height, y + 1), Norm = up};
// ...
}
}
}
meshData.SetVertexBufferParams(numVerts,
new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3, stream:0),
new VertexAttributeDescriptor(VertexAttribute.Normal, VertexAttributeFormat.Float32, 3, stream:1)
);
Your SetVertexBufferParams here places VertexAttribute.Position and VertexAttribute.Normal on a separate streams thus halving the size of the buffer per stream and later the length of the buffers if buffer becomes reinterpreted with the wrong struct by mistake.
This is how documentation explains streams:
Vertex data is laid out in separate "streams" (each stream goes into a separate vertex buffer in the underlying graphics API). While Unity supports up to 4 vertex streams, most meshes use just one. Separate streams are most useful when some vertex attributes don't need to be processed, for example skinned meshes often use two vertex streams (one containing all the skinned data: positions, normals, tangents; while the other stream contains all the non-skinned data: colors and texture coordinates).
But why it might end up re-interpreted as half the length? Well, because of this line:
NativeArray<VData> Verts = MeshData.GetVertexData<VData>();
How? Because there is a implicit stream parameter value there (doc)
public NativeArray<T> GetVertexData(int stream = 0);
and it defaults to 0. So what happens here is this:
var Verts = Positions_Only.Reinterpret<Position_And_Normals>();
or in other words:
var Verts = NativeArray<float3>().Reinterpret<float3x2>();
case solved :T
TL;DR:
Change stream:1 to stream:0 so both vertex attributes end up on the same stream.
or var Positions = MeshData.GetVertexData<float3>(0); & var Normals = MeshData.GetVertexData<float3>(1);
or create a dedicated VData struct per stream var Stream0 = MeshData.GetVertexData<VStream0>(0); & var Stream1 = MeshData.GetVertexData<VStream1>(1);

how to copy a part of a raw image

I want to copy selected part of a raw image to another image
I get start and end position as percentage and by that I can calculate the start and end position in width
how can I copy that selected part to another raw image?
Assuming it's a Texture2D, you can do the following:
Calculate A texture start/end X (dX)
Create a new Texture2D (B), sized as dX and full Y
Call A.GetPixels()
Iterate on array copying pixels to new texture
Apply on new texture
Pseudo code:
var aPixels = aTexture.GetPixels();
var bWidth = endX - startX;
var bTexture = new Texture2D(bWidth, endY);
var bPixels = bTexture.GetPixels();
for (int x = startX; x < endX; x++)
{
for (int y = 0; y < endY; y++)
{
var aIndex = x + y * A.width;
var bIndex = (x - startX) + y * bWidth;
bPixels[bIndex] = aPixels[aIndex];
}
}
bTexture.Apply();
Note that my code quite possibly won't work; as I'm typing this on a mobile phone.
Usually, Image Processing is an expensive process for CPUs, so I don't recommend it in Unity,
But anyway, For your image and in this special case, I think you can crop your image by changing the Size and Offset of texture in material.
Update:
This is an example of what I mentioned:
You can calculate Tile and Offset based on the dragged mouse position on Texture. (Check Here)
I found this.
you can set start coordinates and width and height to GetPixels();
void Start () {
public Texture2D mTexture;
Color[] c = mTexture.GetPixels (startX, startY, width, height);
Texture2D m2Texture = new Texture2D (width, height);
m2Texture.SetPixels (c);
m2Texture.Apply ();
gameObject.GetComponent<MeshRenderer> ().material.mainTexture = m2Texture;
}
```

3 channel depth image 1 channel

I have record a depth video using Kinect v2, when I extracted images using MATLAB then each image is 3 channel. Normally the images I saw are just 1 channel. Please any one tell me how can make this 3 channel image to 1 channel?
Here is the code of the depth part:
IplImage depth = new IplImage(512, 424, BitDepth.U16, 1);
CvVideoWriter DepthWriter;
Width = sensor.DepthFrameSource.FrameDescription.Width;
DHeight = sensor.DepthFrameSource.FrameDescription.Height;
WbDepth = new WriteableBitmap(DWidth, DHeight, 96, 96, PixelFormats.Gray16, null);
int depthshft = (int)SliderDepth.Value;
using (DepthFrame depthframe = frame.DepthFrameReference.AcquireFrame())
ushort* depthdata = (ushort*)depth.ImageData;
if (depthframe != null)
{
Depthdata = new ushort[DWidth * DHeight];
ushort[] Depthloc = new ushort[DWidth * DHeight];
depthframe.CopyFrameDataToArray(Depthdata);
for (int i = 0; i < DWidth * DHeight; i++)
{
Depthloc[i] = 0x1000;
}
colorspacePoint = new ColorSpacePoint[DWidth * DHeight];
depthspacePoint = new DepthSpacePoint[CWidth * CHeight];
sensor.CoordinateMapper.MapDepthFrameToColorSpace(Depthloc, colorspacePoint);
for (int y = 0; y < DHeight; y++)
{
for (int x = 0; x < DWidth; x++)
{
if (depthshft != 0)
{
Depthdata[y * DWidth + x] = (ushort)((Depthdata[y * DWidth + x]) << depthshft);
}
}
}
depth.CopyPixelData(Depthdata);
}
WbDepth.WritePixels(new Int32Rect(0, 0, DWidth, DHeight), Depthdata, strideDep, 0);
ImageDepth.Source = WbDepth;
if (depth != null && DepthWriter.FileName != null) Cv.WriteFrame(DepthWriter, depth);
Cv.ReleaseVideoWriter(DepthWriter);
if (CheckBox_saveD.IsChecked == true)
DepthWriter = new CvVideoWriter(string.Format("{1}\\Scene{0}_DepthRecord.avi", scene, TextBlock_saveloca.Text.ToString()), FourCC.Default, 30.0f, new CvSize(512, 424));
CheckBox_saveD.IsEnabled = false;
if (CheckBox_saveD.IsChecked == true) Cv.ReleaseVideoWriter(DepthWriter);
Thank you
Everyone so far is advising you to convert the (supposedly) color image to grayscale. I don't think you should do this.
The kinect gives you a "1 channel" image of depth values. If you have a color (3 channel) depth map, then something is wrong. Converting to gray scale will then make you lose depth information.
Instead, try to figure out why your image is loaded as gray scale in the first place. What is the source? Is the conversion maybe done by Matlab when reading the image? Can you then give it some flag to tell it not to?

Reduce border width on QR Codes generated by ZXing?

I'm using com.google.zxing.qrcode.QRCodeWriter to encode data and com.google.zxing.client.j2se.MatrixToImageWriter to generate the QR Code image. On a 400x400 image, there is about a 52 pixel wide border around the code. I'd like this border to be narrower, maybe 15 pixels, but I don't see anything in the API for doing that. Am I missing something in the documenation? Or would I need to process the image myself?
For reference, here is an example 400x400 QR Code produced with the ZXing library:
The QR spec requires a four module quiet zone and that's what zxing creates. (See QUIET_ZONE_SIZE in QRCodeWriter.renderResult.)
More recent versions of ZXing allow you to set the size of the quiet zone (basically the intrinsic padding of the QR code) by supplying an int value with the EncodeHintType.MARGIN key. Simply include it in the hints Map you supply to the Writer's encode(...) method, e.g.:
Map<EncodeHintType, Object> hints = new EnumMap<EncodeHintType, Object>(EncodeHintType.class);
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints.put(EncodeHintType.MARGIN, 2); /* default = 4 */
If you change this, you risk lowering the decode success rate.
Even by setting EncodeHintType.MARGIN to 0, the algorithm that convert the QRCode "dot" matrix to pixels data can generate a small margin (the algorithm enforce a constant number of pixels per dots, so the margin pixel size is the remainder of the integer division of pixels size by QR-Code dot size).
However you can completely bypass this "dot to pixel" generation: you compute the QRCode dot matrix directly by calling the public com.google.zxing.qrcode.encoder.Encoder class, and generate the pixel image yourself. Code below:
// Step 1 - generate the QRCode dot array
Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>(1);
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
QRCode qrCode = Encoder.encode(what, ErrorCorrectionLevel.L, hints);
// Step 2 - create a BufferedImage out of this array
int width = qrCode.getMatrix().getWidth();
int height = qrCode.getMatrix().getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
int[] rgbArray = new int[width * height];
int i = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
rgbArray[i] = qrCode.getMatrix().get(x, y) > 0 ? 0xFFFFFF : 0x000000;
i++;
} }
image.setRGB(0, 0, width, height, rgbArray, 0, width);
The conversion of the BufferedImage to PNG data is left as an exercise to the reader. You can also scale the image by setting a fixed number of pixels per dots.
It's usually more optimized that way, the generated image size is the smallest possible. If you rely on client to scale the image (w/o blur) you do not need more than 1 pixel per dot.
HashMap hintMap = new HashMap();
hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.Q);
hintMap.put(EncodeHintType.MARGIN, -1);
no margin
UPDATE
Add dependencies (from comments)
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.2.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.2.0</version>
</dependency>
In swift you can:
let hints = ZXEncodeHints()
hints!.margin = NSNumber(int: 0)
let result = try writer.encode(code, format: format, width: Int32(size.width), height: Int32(size.height), hints: hints)
let cgImage = ZXImage(matrix: result, onColor: UIColor.blackColor().CGColor, offColor: UIColor.clearColor().CGColor).cgimage
let QRImage = UIImage(CGImage: cgImage)
My problem is that I need to generate a PNG image with a transparent background fixed to x * x pixels.
I find that whatever I do with EncodeHintType.MARGIN, these is always some unexpected margin.
After reading its source code, I find a way to fix my problem, this is my code. There is no margin in the output BufferedImage.
BufferedImage oriQrImg = getQrImg(CONTENT_PREFIX+userInfo, ErrorCorrectionLevel.L,BLACK);
BufferedImage scaledImg = getScaledImg(oriQrImg,REQUIRED_QR_WIDTH,REQUIRED_QR_HEIGHT);
private static BufferedImage getQrImg(String content, ErrorCorrectionLevel level, int qrColor) throws WriterException {
QRCode qrCode = Encoder.encode(content, level, QR_HINTS);
ByteMatrix input = qrCode.getMatrix();
int w=input.getWidth(),h=input.getHeight();
BufferedImage qrImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = qrImg.createGraphics();
qrImg = g2d.getDeviceConfiguration().createCompatibleImage(w,h, Transparency.BITMASK);
g2d.dispose();
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
if (input.get(x,y) == 1) {
qrImg.setRGB(x, y, qrColor);
}else{
qrImg.setRGB(x, y, Transparency.BITMASK);
}
}
}
return qrImg;
}
static BufferedImage getScaledImg(BufferedImage oriImg,int aimWidth,int aimHeight){
Image scaled = oriImg.getScaledInstance(aimWidth,aimHeight,SCALE_DEFAULT);
Graphics2D g2d = new BufferedImage(aimWidth,aimHeight, BufferedImage.TYPE_INT_RGB).createGraphics();
BufferedImage scaledImg = g2d.getDeviceConfiguration().createCompatibleImage(aimWidth,aimHeight, Transparency.BITMASK);
g2d.dispose();
scaledImg.createGraphics().drawImage(scaled, 0, 0,null);
return scaledImg;
}