Imebra - Change color contrasts - android

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

Related

How to change the pixel color of an image in real time

I need to develop a function that changes the pixel color of an image in real time, I currently wrote this part of the code that seems to work partially
private void changePixelsColor() {
try {
tileView.buildDrawingCache(true);
tileView.setDrawingCacheEnabled(true);
int height = tileView.getDrawingCache().getHeight();
int width = tileView.getDrawingCache().getWidth();
int[] pixelNumber = new int[height * width];
tileView.getDrawingCache().getPixels(pixelNumber, 0, width, 0, 0, width, height);
for (int i = 0; i < pixelNumber.length; i++) {
if (String.valueOf(pixelNumber[i]).length() > 2) {
String hexColor = "#" + Integer.toHexString(pixelNumber[i]).substring(2);
if (hexColor.compareToIgnoreCase("#f0f1f0") == 0) {
pixelNumber[i] = Color.RED;
}
}
}
tileView.getDrawingCache().setPixels(pixelNumber, 0, width, 0, 0, width, height);
File file = new File(MYPATH);
FileOutputStream out = new FileOutputStream(file);
Bitmap mappedCar = Bitmap.createBitmap(tileView.getDrawingCache());
mappedCar.compress(Bitmap.CompressFormat.JPEG, 100, out);
mappedCar.recycle();
out.flush();
out.close();
tileView.setDrawingCacheEnabled(false);
tileView.destroyDrawingCache();
} catch (Exception e) {
}
}
Specifically I'm using a "TileView" library to show the user an image (I'm simplifying the explanation), in a certain part of the code I need to scan all the pixels of an image, and replace some (eg # f0f1f0 with the red).
Currently I can retrieve the pixel map and understand for each of them what color it is. What I can not do is change the image colors in real time and save the result in a file.
/*********************EDIT 1 *********************/

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

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.

Print Generated Barcode / QR Code On Receipt

Hello I am new to android, I am currently trying to print a receipt from my Android 4.4.2 table to my Zicox thermal receipt printer. I have been able to print the text so far but now I need to go a step further and print barcodes / qrcodes. Unfortunately this is way beyond my knowledge, I have googled solutions and have not found one for me yet.
These are the methods I use to generate my barcode:
/**************************************************************
* getting from com.google.zxing.client.android.encode.QRCodeEncoder
*
* See the sites below
* http://code.google.com/p/zxing/
* http://code.google.com/p/zxing/source/browse/trunk/android/src/com/google/zxing/client/android/encode/EncodeActivity.java
* http://code.google.com/p/zxing/source/browse/trunk/android/src/com/google/zxing/client/android/encode/QRCodeEncoder.java
*/
private static final int WHITE = 0xFFFFFFFF;
private static final int BLACK = 0xFF000000;
Bitmap encodeAsBitmap(String contents, BarcodeFormat format, int img_width, int img_height) throws WriterException {
String contentsToEncode = contents;
if (contentsToEncode == null) {
return null;
}
Map<EncodeHintType, Object> hints = null;
String encoding = guessAppropriateEncoding(contentsToEncode);
if (encoding != null) {
hints = new EnumMap<EncodeHintType, Object>(EncodeHintType.class);
hints.put(EncodeHintType.CHARACTER_SET, encoding);
}
MultiFormatWriter writer = new MultiFormatWriter();
BitMatrix result;
try {
result = writer.encode(contentsToEncode, format, img_width, img_height, hints);
} catch (IllegalArgumentException iae) {
// Unsupported format
return null;
}
int width = result.getWidth();
int height = result.getHeight();
int[] pixels = new int[width * height];
for (int y = 0; y < height; y++) {
int offset = y * width;
for (int x = 0; x < width; x++) {
pixels[offset + x] = result.get(x, y) ? BLACK : WHITE;
}
}
Bitmap bitmap = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}
private static String guessAppropriateEncoding(CharSequence contents) {
// Very crude at the moment
for (int i = 0; i < contents.length(); i++) {
if (contents.charAt(i) > 0xFF) {
return "UTF-8";
}
}
return null;
}
This is my onClick method that starts the entire process:
// barcode data
String barcode_data = "123456";
// barcode image
ImageView iv = new ImageView(this);
try {
barCode = encodeAsBitmap(barcode_data, BarcodeFormat.CODE_128, 300, 40);
// bitmap.getRowBytes();
iv.setImageBitmap(barCode);
} catch (WriterException e) {
e.printStackTrace();
}
iv.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
innerLayout.addView(iv);
So now I am basically able to generate and display the barcode now I want to be able to print in on my receipts.
As I can understand from your question, you basically want to print a bitmap, that contains the QR code.
You can use PrintHelper class for the same. Here's a sample code from the official documentation that shows how to use it.
private void doPhotoPrint() {
PrintHelper photoPrinter = new PrintHelper(getActivity());
photoPrinter.setScaleMode(PrintHelper.SCALE_MODE_FIT);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.droids);
photoPrinter.printBitmap("droids.jpg - test print", bitmap);
}
Also, it says :
After the printBitmap() method is called, no further action from your application is required. The Android print user interface appears, allowing the user to select a printer and printing options.
Update :
The above method prints only a bitmap. For printing a whole layout (like a receipt, as you said), instructions have been laid out here. I'll try to summarize it for you here :
The first step is to to extend PrintDocumentAdapter class and override certain methods. In that adapter, there's a callback method known as onWrite() that is called for drawing content on the file to be printed. In this method, you'll have to use Canvas object to draw content. This object has all the helper methods to draw bitmap/line/text etc.
Then, when the print is requested, obtain an instance of `PrintManager' class as follows :
PrintManager printManager = (PrintManager) getActivity()
.getSystemService(Context.PRINT_SERVICE);
Then, call the print method as :
printManager.print(jobName, new CustomDocumentAdapter(getActivity()),
null);
Let me know if this helps.

combining two png files in android

I have two png image files that I would like my android app to combine programmatically into one png image file and am wondering if it is possible to do so? if so, what I would like to do is just overlay them on each other to create one file.
the idea behind this is that I have a handful of png files, some with a portion of the image on the left with the rest transparent and the others with an image on the right and the rest transparent. and based on user input it will combine the two to make one file to display. (and i cant just display the two images side by side, they need to be one file)
is this possible to do programmatically in android and how so?
I've been trying to figure this out for a little while now.
Here's (essentially) the code I used to make it work.
// Get your images from their files
Bitmap bottomImage = BitmapFactory.decodeFile("myFirstPNG.png");
Bitmap topImage = BitmapFactory.decodeFile("myOtherPNG.png");
// As described by Steve Pomeroy in a previous comment,
// use the canvas to combine them.
// Start with the first in the constructor..
Canvas comboImage = new Canvas(bottomImage);
// Then draw the second on top of that
comboImage.drawBitmap(topImage, 0f, 0f, null);
// comboImage is now a composite of the two.
// To write the file out to the SDCard:
OutputStream os = null;
try {
os = new FileOutputStream("/sdcard/DCIM/Camera/" + "myNewFileName.png");
comboImage.compress(CompressFormat.PNG, 50, os)
} catch(IOException e) {
e.printStackTrace();
}
EDIT :
there was a typo,
So, I've changed
image.compress(CompressFormat.PNG, 50, os)
to
bottomImage.compress(CompressFormat.PNG, 50, os)
You can do blending. This is not particular to Android. It's just universal image processing.
EDIT:
You may find these articles & samples & code useful:
http://www.jhlabs.com/ip/
http://kfb-android.blogspot.com/2009/04/image-processing-in-android.html
http://code.google.com/p/jjil/
Image Processing on Android
I use this code
private class PhotoComposition extends AsyncTask<Object, Void, Boolean> {
private String pathSave;//path save combined images
#Override
protected Boolean doInBackground(Object... objects) {
List<String> images = (List<String>) objects[0]; //lsit of path iamges
pathSave = (String) objects[1];//path save combined images
if (images.size() == 0) {
return false;
}
List<Bitmap> bitmaps = new ArrayList<>();
for (int i = 0; i < images.size(); i++) {
bitmaps.add(BitmapFactory.decodeFile( images.get(i)));
}
int width = findWidth(bitmaps);//Find the width of the composite image
int height = findMaxHeight(bitmaps);//Find the height of the composite image
Bitmap combineBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);//create bitmap of composite image
combineBitmap.eraseColor(Color.parseColor("#00000000")); //bcakgraound color of composite image
Bitmap mutableCombineBitmap = combineBitmap.copy(Bitmap.Config.ARGB_8888, true);//create mutable bitmap to create canvas
Canvas canvas = new Canvas(mutableCombineBitmap);// create canvas to add bitmaps
float left = 0f;
for (int i = 0; i < bitmaps.size(); i++) {
canvas.drawBitmap(bitmaps.get(i), left, 0f, null);//Taking photos horizontally
left += bitmaps.get(i).getWidth();//Take right to the size of the previous photo
}
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(pathSave);//path of save composite image
mutableCombineBitmap.compress(Bitmap.CompressFormat.PNG, 80, outputStream);
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
#Override
protected void onPostExecute(Boolean isSave) {
if (isSave) {
//iamge save on pathSave
Log.i("PhotoComposition", "onPostExecute: " + pathSave);
}
super.onPostExecute(isSave);
}
private int findMaxHeight(List<Bitmap> bitmaps) {
int maxHeight = Integer.MIN_VALUE;
for (int i = 0; i < bitmaps.size(); i++) {
if (bitmaps.get(i).getHeight() > maxHeight) {
maxHeight = bitmaps.get(i).getHeight();
}
}
return maxHeight;
}
private int findWidth(List<Bitmap> bitmaps) {
int width = 0;
for (int i = 0; i < bitmaps.size(); i++) {
width += bitmaps.get(i).getWidth();
}
return width;
}
USAGE
List<String> images = new ArrayList<>();
images.add("/storage/emulated/0/imageOne.png");//path of image in storage
images.add("/storage/emulated/0/imageTwo.png");
// images.add("/storage/emulated/0/imageThree");
// ... //add more images
String pathSaveCombinedImage = "/storage/emulated/0/CombinedImage.png";//path save result image
new PhotoComposition().execute(images, pathSaveCombinedImage);
And the result of using the above code will be as follows
You may wish to look into the Canvas object, which would make it easy to do other drawing operations as well. You can just draw your bitmaps onto a canvas where you want them, then save the resulting bitmap.
If they have transparent sections, then if you draw one on top of the other, only the non-transparent portions will overlap. It will be up to you to arrange the bitmaps however you like.
For the separate issue of re-saving your image to a png, use bitmap.compress().
Try this .
public Bitmap mergeBitmap(Bitmap frame, Bitmap img){
Bitmap bmOverlay = Bitmap.createBitmap(frame.getWidth(), frame.getHeight(), frame.getConfig());
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(img, 0, 0, null);
canvas.drawBitmap(frame, new Matrix(), null);
return bmOverlay;
}
Returns a bitmap image
Pass two bitmap images to your function as shown below
Bitmap img= mergeBitmap(imgone, imagetwo);
See the entire post or also see merge multiple images in android programmatically

Categories

Resources