Add image to a specific location using iText in Android - android

I want to add image to a specific location in a PDF file using iText in Android. This is a fillable form and I have added textbox that is a place holder for the image and what I want to do is to get that textbox and image to it like this.
public class FormFill {
public static void fill(AcroFields form, Person person) throws IOException, DocumentException{
form.setField("firstname", person.getFirstName());
form.setField("lastname", person.getLastName());
form.setField("imagetextbox", "???");
}
I have the image uri like so
Uri imageUri = Uri.parse(person.getImagePath());
Any help would be appreciated.

try this.
i have used this function for add image in document.
public void addLogo(Document document) throws DocumentException {
try { // Get user Settings GeneralSettings getUserSettings =
Rectangle rectDoc = document.getPageSize();
float width = rectDoc.getWidth();
float height = rectDoc.getHeight();
float imageStartX = width - document.rightMargin() - 315f;
float imageStartY = height - document.topMargin() - 80f;
System.gc();
InputStream ims = getAssets().open("splashscreen.jpg");
Bitmap bmp = BitmapFactory.decodeStream(ims);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 50, stream);
byte[] byteArray = stream.toByteArray();
// PdfImage img = new PdfImage(arg0, arg1, arg2)
// Converting byte array into image Image img =
Image img = Image.getInstance(byteArray); // img.scalePercent(50);
img.setAlignment(Image.TEXTWRAP);
img.scaleAbsolute(200f, 50f);
img.setAbsolutePosition(imageStartX, imageStartY); // Adding Image
document.add(img);
} catch (Exception e) {
e.printStackTrace();
}
}

I ended adding the image like so
Image image = Image.getInstance(stream.toByteArray());
PdfContentByte overContent = stamper.getOverContent(1);
overContent.addImage(image);

Related

Android: Images uploaded to firebase with -90 rotation

I am using Samsung A52 to take some images with camera not my firebase app and save them, after that i would upload these images to firebase, iam compressing them before upload .
now after images were uploaded i checked and found that they are -90 rotated, not all images rotated , some were rotated and some weren't;
any idea?
or is there any possibly to detect while loading images from firebase if it rotated to retotate is to 90 ?
function to upload images after getting them from gallery.
for (uploadCount = 0; uploadCount < ImageList.size(); uploadCount++) {
String imagePath = productRef.child(UID).child("images").push().getKey();
Uri IndividualImage = ImageList.get(uploadCount);
assert imagePath != null;
StorageReference ImageName = productImagesRef.child(UID).child(imagePath);
//Compress Images
Bitmap bmp = null;
try {
bmp = MediaStore.Images.Media.getBitmap(getContentResolver(), IndividualImage);
} catch (IOException e) {
e.printStackTrace();
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
assert bmp != null;
bmp.compress(Bitmap.CompressFormat.JPEG, 25, baos);
byte[] data = baos.toByteArray();
//End of compressing
//start on uploading compressed
ImageName.putBytes(data).addOnSuccessListener(taskSnapshot -> ImageName.getDownloadUrl()
.addOnSuccessListener(uri -> {
String url = String.valueOf(uri);
StoreLink(url, imagePath);
})).addOnProgressListener(snapshot1 -> {
double progress = (100.0* snapshot1.getBytesTransferred()/snapshot1.getTotalByteCount());
loadingDialog.setMessage("صورة رقم " + (count+ 1) + " -->> " +(int) progress + "%");
});
}
So i self Solved it and this was my solution:
i added a rotate button to the layout of recyclerView item(Adapter), and then created an empty ArrayList to store the value or rotation degree.
i passed the arraylist to adapter which has the rotate button, now when user click on rotate a value of 90f would be saved to arraylist with the position like this:
imageRotation.set(holder.getAdapterPosition(), "90f");
since arrayList can take (index, value)
Note: if there isn't an exiting value for the Arralist position and you skipped the position to change rotation for other item, it would crash.
and to solve this i made a for loop to populate the Arratlist with 0f as a rotatiion degree.
for (int i = 0; i <= imageUriList.size(); i++) {
imageRotation.add(i,"0f");
}
then when user click on rotate, it would update the position value:
imageRotation.set(holder.getAdapterPosition(), "90f");
and onActivityResult of the Upload Activity:
i used this:
if (requestCode == LAUNCH_SECOND_ACTIVITY) {
if (resultCode == Activity.RESULT_OK) {
assert data != null;
imageRotationArray = data.getStringArrayListExtra("imageRotationArray");
}
}
and before the Compress image function:
// create new matrix
Matrix matrix = new Matrix();
// setup rotation degree
matrix.postRotate(Float.parseFloat(imageRotationArray.get(countRotateImage)));
bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
countRotateImage++;

Byte Array to 2D array

What My code does . is take a snapshot of the map convert it to gray (opencv) and then make it to byte array.
Now what I dont know how to start doing is making this Bytearray to a 2D Array,
here is a block of the code.
Date now = new Date();
android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss",now);
try {
StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy();
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder(old)
.permitDiskWrites()
.build());
String mPath = Environment.getExternalStorageDirectory().toString() + "/" + now + ".jpg";
File imageFile = new File(mPath);
FileOutputStream out = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.PNG,90,out);
Log.d("Image:","Saved Snashot. Starting covertion");
//show snapshot in imageview
ImageView imgview = (ImageView) findViewById(R.id.imageView);
Bitmap smyBitmap = BitmapFactory.decodeFile(mPath);
Bitmap myBitmap = BitmapFactory.decodeFile(mPath);
imgview.setImageBitmap(smyBitmap);
Mat mat = new Mat(myBitmap.getHeight(),myBitmap.getWidth(),CvType.CV_8UC3);
Mat mat1 = new Mat(myBitmap.getHeight(),myBitmap.getWidth(),CvType.CV_8UC1);
Imgproc.cvtColor(mat,mat1,Imgproc.COLOR_BGR2GRAY);
ImageView imgview2 = (ImageView) findViewById(R.id.imageView2);
Mat tmp = new Mat (myBitmap.getWidth(), myBitmap.getHeight(), CvType.CV_8UC1);
Utils.bitmapToMat(myBitmap, tmp);
Imgproc.cvtColor(tmp, tmp, Imgproc.COLOR_RGB2GRAY);
Utils.matToBitmap(tmp, myBitmap);
// Utils.matToBitmap(mat1,img);
String mPathgray = Environment.getExternalStorageDirectory().toString() + "/" + now + "gray.jpg";
File imageFilegray = new File(mPathgray);
FileOutputStream gout = new FileOutputStream(imageFilegray);
bitmap.compress(Bitmap.CompressFormat.PNG,90,gout);
byte[] byteArray = bttobyte(myBitmap);
Log.d("location"," " + mPathgray);
imgview2.setImageBitmap(myBitmap);
Log.d("Activity", "Byte array: "+ Arrays.toString(byteArray));
}
catch (Exception e) {
e.printStackTrace();
}
}
};
mMap.snapshot(callback);
Log.d("test","test2");
}
});
}
public byte[] bttobyte(Bitmap bitmap) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 70, stream);
return stream.toByteArray();
}
The problem you are trying to solve is actually extracting image data from JPEG encoding in the byte array. It is not as simple as being stored pixel by pixel in a grid of width and height equal to your image size, as you seem to be implying. That is a consequence of using this
bitmap.compress(Bitmap.CompressFormat.JPEG, 70, stream);
For example that byte data actually might encode JFIF format:
0xffd8 - SOI - exactly 1 - start of image
e.g. 0xffe0 - zero or more - e.g. APP0 for JFIF - [some sort of header, either JFIF or EXIF].
0xffdb - DQT - one or more - define quantisation tables. These are the main source of quality in the image.
0xffcn - SOFn - exactly one - start of frame. SOF0 indicates a baseline DCT JPEG
0xffc4 - DHT - one or more - define Huffman tables. These are used in the final lossless encoding steps.
0xffda - SOS - exactly one (for baseline, more than one intermixed with more DHTs if progressive) - start of stream. This is where the actual data starts.
0xffd9 - EOI - exactly one - end of image.
Essentially once you have transformed your bitmap, you need a JPEG decoder to parse this data.
I think what you want is to be working with the original bitmap. For example there are APIs to extract pixel data. That is what you need if I understand what it is you want to do correctly.
Bitmap.getPixels(int[] pixels,
int offset,
int stride,
int x,
int y,
int width,
int height)
The array pixels[] is filled with data. You can then parse the array if you want to store it in a w by h 2D array by iterating copying the data. Something like:
int offset = 0;
int pixels2d[w][h]= new int[w][h];
for (int[] row : pixels2d) {
System.arraycopy(pixels, offset, row, 0, row.length);
offset += row.length;
}
You just create a new array with 2 dimensions
byte[][] picture = new byte[myBitmap.getWidth()][,myBitmap.getHeight()]
which you can access via
byte myByte = picture[x][y]
after this you iterate your original bytarray by line followed by row

Imebra - Change color contrasts

I am able to load dicom image using imebra, and want to change the colors of image, but cant figure out a way. I want to achieve functionality as in Dicomite app.
Following is my code:
public void loadDCM() {
com.imebra.DataSet loadedDataSet = com.imebra.CodecFactory.load(dicomPath.getPath());
com.imebra.VOIs voi = loadedDataSet.getVOIs();
com.imebra.Image image = loadedDataSet.getImageApplyModalityTransform(0);
// com.imebra.Image image = loadedDataSet.getImage(0);
String colorSpace = image.getColorSpace();
long width = image.getWidth();
long height = image.getHeight();
TransformsChain transformsChain = new TransformsChain();
com.imebra.DrawBitmap drawBitmap = new com.imebra.DrawBitmap(transformsChain);
com.imebra.TransformsChain chain = new com.imebra.TransformsChain();
if (com.imebra.ColorTransformsFactory.isMonochrome(image.getColorSpace())) {
// Allocate a VOILUT transform. If the DataSet does not contain any pre-defined
// settings then we will find the optimal ones.
VOILUT voilutTransform = new VOILUT();
// Retrieve the VOIs (center/width pairs)
com.imebra.VOIs vois = loadedDataSet.getVOIs();
// Retrieve the LUTs
List < LUT > luts = new ArrayList < LUT > ();
for (long scanLUTs = 0;; scanLUTs++) {
try {
luts.add(loadedDataSet.getLUT(new com.imebra.TagId(0x0028, 0x3010), scanLUTs));
} catch (Exception e) {
break;
}
}
if (!vois.isEmpty()) {
voilutTransform.setCenterWidth(vois.get(0).getCenter(), vois.get(0).getWidth());
} else if (!luts.isEmpty()) {
voilutTransform.setLUT(luts.get(0));
} else {
voilutTransform.applyOptimalVOI(image, 0, 0, width, height);
}
chain.addTransform(voilutTransform);
com.imebra.DrawBitmap draw = new com.imebra.DrawBitmap(chain);
// Ask for the size of the buffer (in bytes)
long requestedBufferSize = draw.getBitmap(image, drawBitmapType_t.drawBitmapRGBA, 4, new byte[0]);
byte buffer[] = new byte[(int) requestedBufferSize]; // Ideally you want to reuse this in subsequent calls to getBitmap()
ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);
// Now fill the buffer with the image data and create a bitmap from it
drawBitmap.getBitmap(image, drawBitmapType_t.drawBitmapRGBA, 4, buffer);
Bitmap renderBitmap = Bitmap.createBitmap((int) image.getWidth(), (int) image.getHeight(), Bitmap.Config.ARGB_8888);
renderBitmap.copyPixelsFromBuffer(byteBuffer);
image_view.setImageBitmap(renderBitmap);
}
If you are dealing with a monochrome image and you want to modify the presentation luminosity/contrast, then you have to modify the parameters of the VOILUT transform (voilutTransform variable in your code).
You can get the center and width that the transform is applying to the image before calculating the bitmap to be displayed, then modify them before calling drawBitmap.getBitmap again.
E.g., to double the contrast:
voilutTransform.setCenterWidth(voilutTransform.getCenter(), voilutTransform.getWidth() / 2);
// Now fill the buffer with the image data and create a bitmap from it
drawBitmap.getBitmap(image, drawBitmapType_t.drawBitmapRGBA, 4, buffer);
See this answer for more details about the center/width

Incorrect transformation of frames from YUV_420_888 format to NV21 within an image reader

I configured my code in order to get a stream of YUV_420_888 frames from my device's camera using an imageReader object and the rest of the well known camera2 API. Now I need to transform these frames to NV21 pixel format and call a native function which expect a frame in this format to perform certain computations. This is the code I am using inside the imagereader callback to rearrange the bytes of the frame:
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader mReader) {
Image image = null;
image = mReader.acquireLatestImage();
if (image == null) {
return;
}
byte[] bytes = convertYUV420ToNV21(image);
nativeVideoFrame(bytes);
image.close();
}
};
private byte[] convertYUV420ToNV21(Image imgYUV420) {
byte[] rez;
ByteBuffer buffer0 = imgYUV420.getPlanes()[0].getBuffer();
ByteBuffer buffer1 = imgYUV420.getPlanes()[1].getBuffer();
ByteBuffer buffer2 = imgYUV420.getPlanes()[2].getBuffer();
int buffer0_size = buffer0.remaining();
int buffer1_size = buffer1.remaining();
int buffer2_size = buffer2.remaining();
byte[] buffer0_byte = new byte[buffer0_size];
byte[] buffer1_byte = new byte[buffer1_size];
byte[] buffer2_byte = new byte[buffer2_size];
buffer0.get(buffer0_byte, 0, buffer0_size);
buffer1.get(buffer1_byte, 0, buffer1_size);
buffer2.get(buffer2_byte, 0, buffer2_size);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
try {
outputStream.write( buffer0_byte );
outputStream.write( buffer1_byte );
outputStream.write( buffer2_byte );
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
rez = outputStream.toByteArray( );
return rez;
}
But I dont know why, the resulting frame is "flipped" in the horizontal direction. In other word, when I move the camera to the right, the frame after the packing procedure I have described is moving to the left, like if the sensor is placed in an antinatural position.
I hope you may understand what I mean
Thanks,
JM
It's ok for camera to produce mirrored image. If you don't want it to be mirrored - you need to perform horizontal mirroring, swapping pixels in each row.

[cocos2dx android]Rendering CCSprite using raw data from Bitmap

I am trying to fetch an image from a URL into a Bitmap and then using the raw data from the Bitmap am trying to create a CCSprite. The issue here is that the image is corrupted when I display the sprite. I created a standalone android only application(no cocos2dx) and used the same code to fetch and display the Bitmap and its displayed correctly. Any reason why the image is not being properly rendered in cocos2dx?
My code to fetch the image from the URL is:
String urlString = "http://www.mathewingram.com/work/wp-content/themes/thesis/rotator/335f69c5de_small.jpg";//http://graph.facebook.com/"+user.getId()+"/picture?type=large";
Bitmap pic = null;
pic = BitmapFactory.decodeStream((InputStream) new URL(urlString).getContent());
int[] pixels = new int[pic.getWidth() * pic.getHeight()];
pic.getPixels(pixels, 0, pic.getWidth(), 0, 0,pic.getWidth(),pic.getHeight());
int len = pic.getWidth()* pic.getHeight();
nativeFbUserName(pixels,len,pic.getWidth(), pic.getHeight());
The function "nativeFbUserName" is a call to a native c++ function which is :
void Java_com_WBS_Test0001_Test0001_nativeFbUserName(JNIEnv *env, jobject thiz,jintArray name, jint len, jint width, jint height) {
jint *jArr = env->GetIntArrayElements(name,NULL);
int username[len];
for (int i=0; i<len; i++){
username[i] = (int)jArr[i];
}
HelloWorld::getShared()->picLen = (int)len;
HelloWorld::getShared()->picHeight = (int)height;
HelloWorld::getShared()->picWidth = (int)width;
HelloWorld::getShared()->saveArray(username);
HelloWorld::getShared()->schedule(SEL_SCHEDULE(&HelloWorld::addSprite),0.1);
}
void HelloWorld::saveArray(int *arrayToSave)
{
arr = new int[picLen];
for(int i = 0; i < picLen; i++){
arr[i] = arrayToSave[i];
}
}
void HelloWorld::addSprite(float time)
{
this->unschedule(SEL_SCHEDULE(&HelloWorld::addSprite));
CCTexture2D *tex = new CCTexture2D();
bool val = tex->initWithData(arr,(cocos2d::CCTexture2DPixelFormat)0,picWidth,picHeight, CCSizeMake(picWidth,picHeight));
CCLog("flag is %d",val);
CCSprite *spriteToAdd = CCSprite::createWithTexture(tex);
spriteToAdd->setPosition(ccp(500, 300));
this->addChild(spriteToAdd);
}
Edit:
So I found this link Access to raw data in ARGB_8888 Android Bitmap that states that it might be a bug. Has anyone found a solution to this?
EDIT
So I just noticed a corruption of images on the lower right corner of the image.I am not sure why this is happening and how to fix it. Any ideas?
EDIT END
Answering my own question, I obtained a byte array from the bitmap using:
byte[] data = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
pic.compress(Bitmap.CompressFormat.JPEG, 100, baos);
data = baos.toByteArray();
And then passed this byte array to the native code.

Categories

Resources