I have a problem I've been stuck on for a few days. I am trying to convert a nine patch image into a bitmap array, and change a specific color to a different one. I am having trouble converting the bitmap back to a nine patch, so I can use it as a background for a layout. I have tried using this code to create the bitmap then convert it back to a nine-patch drawable, but it just starts the activity and blinks black then goes back to the parent activity. If I comment out the creation and initialization of the nine-patch the activity starts just fine.
Bitmap backMap = BitmapFactory.decodeResource(getResources(),R.drawable.outerbackground);
backMap = backMap.copy(Bitmap.Config.ARGB_8888, true);
backMap = getChangedColor(backMap, Color.rgb(212, 212, 212), Color.rgb(55, 50, 255));
byte[] chunk = backMap.getNinePatchChunk();
NinePatchDrawable np_drawable = new NinePatchDrawable(getResources(), backMap, chunk, new Rect(), null);
np_drawable.setBounds(0, 0, backMap.getWidth(), backMap.getHeight());
I usually don't ask for help on such a thing, but I have went through all the documentation I could find on nine-patch images and bitmaps and still can't figure it out.
Long question short, I need to know how to convert a bitmap to a nine-patch image for use as a background. Thanks a million in advance. you'll get the other million after your done.
O and I am targeting version 16 with the minimum of 8.
Related
When I create a Bitmap and Canvas with the following code:
Bitmap bitmap = Bitmap.createBitmap(640, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
and I put a breakpoint at the second line to display the preview, it turns out the created Bitmap's size is different than specified. It's supposed to be 640px wide, but the preview says it's 377px instead.
The height is scaled down by the same factor (640/377 is the same as 1737/1024) so I presume some unwanted scaling takes place there.
Interestingly, bitmap.getWidth() returns 640.
I initially thought it might be the debugger's preview related issue, but I checked that when I load some images using:
BitmapFactory.decodeResource(context.resources, R.drawable.image)
and I scale them later to the desired width:
Bitmap.createScaledBitmap(bitmap, desiredWidthPx, targetHeightToKeepAspectRatio, false)
the debugger's preview shows them correctly, i.e. their size matches desiredWidthPx and targetHeightToKeepAspectRatio. So it's not the preview's issue.
For context: I stumbled upon this issue while working on a Bitmap with a specific width in pixels. The Bitmap is going to be printed by a thermal printer later on, so the size must not depend on the Android device's screen size, density and so on. I started debugging this issue after realizing the printer printed around 60% of the image (it was cropped horizontally), e.g. something like this:
I'm not sure exactly what's going on, but by looking at the printouts, I think it's reasonable to suspect the scaling to be the issue here.
Bitmap size in the debug preview is limited to 1024px regardless of the method used to create it. Similar question and issue tracker. Your issue with the printer is not related to it.
You could use a BufferedImage instead:
https://docs.oracle.com/javase/7/docs/api/java/awt/image/BufferedImage.html
I have ported a Java implementation of AnimateGIFWriter to Android here. It works fine except I don't get the transparency. I tried to pass an Options to the decode() method like this:
Options opts = new Options();
opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeStream(fin, null, opts);
After reading the input image into a Bitmap, I will grab the data as an int array through Bitmap.getPixels() and auto-detect the transparency from the alpha value. But this doesn't work - the resulting animated GIF is not transparent (The input images are all transparent and my code is supposed to keep them through auto-transparency detect. This works for desktop application).
I am not quite familiar with Android related stuff. My question is given the above configuration, will BitmapFactory.decode() keep the transparency information of the input image?
Update: I found out for images support full alpha transparency like PNG images, it does keep the transparency information. But for single color transparency images like GIF, it seems not. This needs further confirmation.
My question is given the above configuration, will BitmapFactory.decode() keep the transparency information of the input image?
Yes, transparency/alpha should be loaded into that bitmap.
To verify this, you could try fetching the value of a single pixel -- maybe (0,0) -- and printing it to the log.
I don't have the time (or desire) to get into your full 1600 lines of code, but I would be suspicious of this part in the writeFrame method:
if(frame.getTransparencyFlag() == GIFFrame.TRANSPARENCY_INDEX_SET && frame.getTransparentColor() != -1) {
I've the known problem that my bitmap/canvas is too big and it throws the java.lang.OutOfMemoryError.
My question is what would be the best for my needs.
The Canvas should draw a graph (with given points) and can be very wide (like 3000px and more, theoretically it's wide could be much more, like 20000px). The height is fix.
Because thats to wide for any screen I put it in a Scrollview and draw the whole graph into the canvas.
So thats to wide for the bitmap and I get the error.
The second possibility would be a fix sized canvas where I'd write a "onScroll" method that redraws the graph depending on the users swipe. So it'd only draw a part of the graph.
Would that be the better way or is there a way to make the first option work?
Anyhow please give me some hints and example code for the solution.
Here is the code:
Bitmap bitmap = Bitmap.createBitmap(speedCanvasWidth,speedCanvasHeight,Bitmap.Config.RGB_565); //I also tried ARGB_8888
speedCanvas = new Canvas(bitmap);
graph.setImageBitmap(bitmap);
Thanks in advance
You can handle this with a BitmapRegionDecoder. Just create an instance of one that points to your image. The system will maintain a handle on the image and then you can call decode on the decoder based on what rectangle you want to be displayed within the canvas. Updates to the canvas will have to be handled based on your needs. This will help prevent loading this large image that you have to handle.
You can further get details of the Bitmap in question by checking the Bitmap information. This can be done by loading the bitmap into memory with BitmapFactory.Options flags set for to true for inJustDecodeBounds. That keeps the Bitmap from actually being loaded into memory during the checks.
For instance, a quick retrieval could be done with the following:
BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance("pathToFile", true);
Bitmap regionOfInterestBitmap = decoder.decodeRegion(rectWithinImage, null);//Or with options you have decided to load.
I am trying to write a SWT component, that is able to take and draw an instance of java.awt.BufferedImage. My problem is that SWT's Image and AWT's BufferedImage are incompatible: SWT components can't draw java.awt.Image, AWT/Swing components can't draw org.eclipse.swt.graphics.Image.
There are several approaches that try to solve this problem in other ways (which also may have some variations, but basically there are these two):
Convert between SWT Image and AWT BufferedImage
Swing/SWT Integration
They all have shortcomings and didn't satisfy my expectations:
The first approach, to convert an SWT Image to a BufferedImage, results in poor performance for large images due to the creation of a new RGB instance for every Pixel.
The second approach has several shortcomings in usability. See the "workarounds" at the end of the linked article.
This lead to the conclusion that I'd try my best to write a component (based on org.eclipse.swt.widgets.Canvas or org.eclipse.swt.widgets.Composite) which allows to draw a BufferedImage directly without any conversion of images.
My approach was to draw it pixel by pixel. Therefore I simply had to get an instance of GC, walk the source BufferedImage line by line, left-to-right and drawing the corresponding Color using GC.setForeground(Color color) and GC.drawPoint(int x, int y).
First, I created a new instance of Color for every pixel, which uses quite a lot of memory and adds an additional delay, since new Color acquires system resources and creating a new object for every pixel also takes its time.
Then I tried to pre-load all possible (24 bit) Colors into an array before drawing the image. This lead to an explosion of memory usage (>= 600 MB), which was clear before I was trying it, but I had to verify it.
Caching only the used Colors also lead to more memory consumption than would have been required.
I think there has to be a more low-level approach that doesn't require that much memory, since SWT is able to draw whole (SWT) Images without consuming that much memory.
I would appreciate any ideas or solutions.
I found out there's a way to "convert" an BufferedImage to an Image by using the original image's data buffer if it is 24 bit RGB. This is possible, since the image formats are compatible.
final BufferedImage original = ImageIO.read(new File("some-image.jpg");
final PaletteData palette =
new PaletteData(0x0000FF, 0x00FF00, 0xFF0000);
// the last argument contains the byte[] with the image data
final ImageData data = new ImageData(original.getWidth(), original.getHeight(),
24, palette, 4,
((DataBufferByte) original.getData().getDataBuffer()).getData());
final Image converted = new Image(getDevice(), data);
This way, one doesn't have to create thousands of new objects. This approach comes with the disadvantage that one needs to ensure that the original image is of type RGB 24 bit. Otherwise the image has to be converted to this format.
After that, an image can be drawn with the following code:
// get the GC of your component
gc.drawImage(image, 0, 0);
Probably other bit depths can be converted in a similar way, but this is all I need for the moment.
I have been researching this for a while on this site and have not came up with exactly what I am looking for. I am working with software in which I do not have the source for must pass that code an Image.class image. I have 2 images that I need to overlay the first one over the second and then pass that combined image to the software I am interfacing with. I must use the Java Language for all code.
Everything I have found is writing the 2 images directly. Is what I am trying to do possible and if so please can you help me get these results? A code stub would be wonderful. I surely appreciate all of the time you take in assisting me.
Basically, you can "paint" one image on to the other...The trick is getting one of them into the correct format...
Image image1 = ...;
Image image2 = ...;
BufferedImage buffer1 = new BufferedImage(image1.getWidth(this), image1.getHeight(this), BufferedImage.TYPE_ARGB);
Graphics2D g = buffer.createGraphics();
g.drawImage(image1, 0, 0, this);
g.drawImage(image2, 0, 0, this);
g.dispose();
This will overlay image2 over image1. You can either assign buffer1 to image1 and pass it to you other class or simple pass buffer1 as BufferedImage extends from java.awt.Image