my code are as follows
private void photoChooserTask_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
Stream stream = e.ChosenPhoto;
int len = (int)stream.Length;
byte[] PhoteBytes = new byte[len];
stream.Read(PhoteBytes,0,len);
}
}
I am wondering is it possible to convert
byte array(PhoteBytes in this example)
to WriteableBitmap?
Thanks for the help
Try this.
WritableBitmap bitmap = new WritableBitmap(); //Use appropriate constructor
bitmap.SetSource(e.ChosenPhoto);
EDIT: You'll have to use the appropriate constructor. In one WriteableBitmap(Int32, Int32) constructor you can specify the bitmap width and height. See documentation here
Related
I'm working on Xmarin Forms(PCL) project, I want to convert the StackLayout to Image / buffer and send it to printer for hard print.
Can anyone suggest how to do it in (Xamarin.Android & Xamarin.iOS).
You can't. Xamarin does not have that kind of feature. You should write a Renderer for your UIComponent.
Fortunately there is an Objective-C iOS implementation, and an Android one as well. You can inspire from them.
Taken from this link, which I have personally used, quite a while back though, the following code will take a screenshot of the entire page.
I ended up modifying the code to only take a screenshot of a specific view on the page and also changed a few other things but this example is what I based it off of, so let me know if you would rather see that code and/or if something below is not working for you.
First you create an interface in your Forms project, IScreenshotManager.cs for example:
public interface IScreenshotManager {
Task<byte[]> CaptureAsync();
}
Now we need to implement our interface in Android, ScreenshotManager.cs for example:
public class ScreenshotManager : IScreenshotManager {
public static Activity Activity { get; set; }
public async System.Threading.Tasks.Task<byte[]> CaptureAsync() {
if(Activity == null) {
throw new Exception("You have to set ScreenshotManager.Activity in your Android project");
}
var view = Activity.Window.DecorView;
view.DrawingCacheEnabled = true;
Bitmap bitmap = view.GetDrawingCache(true);
byte[] bitmapData;
using (var stream = new MemoryStream()) {
bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream);
bitmapData = stream.ToArray();
}
return bitmapData;
}
}
Then set ScreenshotManager.Activity in MainActivity:
public class MainActivity : Xamarin.Forms.Platform.Android.FormsApplicationActivity {
protected override async void OnCreate(Android.OS.Bundle bundle) {
...
ScreenshotManager.Activity = this; //There are better ways to do this but this is what the example from the link suggests
...
}
}
Finally we implement this on iOS, ScreenshotManager.cs:
public class ScreenshotManager : IScreenshotManager {
public async System.Threading.Tasks.Task<byte[]> CaptureAsync() {
var view = UIApplication.SharedApplication.KeyWindow.RootViewController.View;
UIGraphics.BeginImageContext(view.Frame.Size);
view.DrawViewHierarchy(view.Frame, true);
var image = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
using(var imageData = image.AsPNG()) {
var bytes = new byte[imageData.Length];
System.Runtime.InteropServices.Marshal.Copy(imageData.Bytes, bytes, 0, Convert.ToInt32(imageData.Length));
return bytes;
}
}
}
public interface Kernel32 extends StdCallLibrary {
int GetComputerNameW(Memory lpBuffer, IntByReference lpnSize);
}
public class Kernel32Test {
private static final String THIS_PC_NAME = "tiangao-160";
private static Kernel32 kernel32;
#BeforeClass
public static void setUp() {
System.setProperty("jna.encoding", "GBK");
kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
}
#AfterClass
public static void tearDown() {
System.setProperty("jna.encoding", null);
}
#Test
public void testGetComputerNameW() {
final Memory lpBuffer = new Memory(1024);
final IntByReference lpnSize = new IntByReference();
final int result = kernel32.GetComputerNameW(lpBuffer, lpnSize);
if (result != 0) {
throw new IllegalStateException(
"calling 'GetComputerNameW(lpBuffer, lpnSize)'failed,errorcode:" + result);
}
final int bufferSize = lpnSize.getValue();
System.out.println("value of 'lpnSize':" + bufferSize);
Assert.assertEquals(THIS_PC_NAME.getBytes().length + 1, bufferSize);
final String name = lpBuffer.getString(0);
System.out.println("value of 'lpBuffer':" + name);
Assert.assertEquals(THIS_PC_NAME, name);
}
}
The offical instructions says use byte[]、char[]、Memory or NIO Buffer for mapping char pointer in c native function.But I tried all of above, and String、WString、StringArrays、class extends PointType etc, all of them are no use.
Out parameter 'lpnSize' can return the corret buffer size,but 'lpBuffer' return 'x>'(i think it's random memory) or nothing no matter I mapping any java type.If i wrote someting to the 'lpBuffer' memory first, it would read the same things after calling native function.
How can I solve the problem?
You need to use Pointer.getString(0, true) to extract the unicode string returned by GetComputerNameW.
EDIT
You'll also need to call GetComputerNameW again with the length parameter initialized before the function will fill in the result. Either pass back the same IntByReference to a second call, or initialize the IntByReference to the size of your Memory buffer to have the buffer written to in the first call.
I am new to BlackBerry development. But good about android.
I want to load Images coming from the server in ListField.
I have implement like below code but not getting success:
package mypackage;
public class TempScreen extends MainScreen implements ListFieldCallback{
Bitmap[] images=null;
private ListField mylist;
private static Bitmap _bitmap;
private ImageDownloader downloader;
int size = 0;
String[] urls={
"http://www.kentnews.co.uk/polopoly_fs/damian_lewis_at_port_lympne_wild_animal_park_c_taf_1_1738362!image/2626063106.jpg_gen/derivatives/landscape_225/2626063106.jpg",
"http://www.kentnews.co.uk/polopoly_fs/damian_lewis_at_port_lympne_wild_animal_park_c_taf_1_1738362!image/2626063106.jpg_gen/derivatives/landscape_225/2626063106.jpg",
"http://www.kentnews.co.uk/polopoly_fs/damian_lewis_at_port_lympne_wild_animal_park_c_taf_1_1738362!image/2626063106.jpg_gen/derivatives/landscape_225/2626063106.jpg",
"http://www.kentnews.co.uk/polopoly_fs/damian_lewis_at_port_lympne_wild_animal_park_c_taf_1_1738362!image/2626063106.jpg_gen/derivatives/landscape_225/2626063106.jpg"};
public TempScreen()
{
images=new Bitmap[urls.length];
size = urls.length;
mylist = new ListField();
mylist.setCallback(this);
mylist.setSize(4);
mylist.setRowHeight(getFont().getHeight() * 3);
add(mylist);
Thread downloader=new Thread(new ImageDownloader());
downloader.start();
}
public void drawListRow(ListField listField, Graphics graphics, int index,
int y, int width) {
if(images[index]==null)
{
//Load placeholder image
_bitmap = Bitmap.getBitmapResource("close_btn.png");// load some bitmap
// of your choice
// here
}
else
//Load Bitmap
_bitmap = images[index];
graphics.drawText("row details", 100, y + 30);
//graphics.drawBitmap(0, y, _bitmap.getWidth(), _bitmap.getHeight(),_bitmap, 0, 0);
mylist.invalidate(index);
}
public class ImageDownloader implements Runnable
{
public void run()
{
for(int i=0; i<size;i++)
{
if(images[i]==null)
{
images[i]=connectServerForImage(urls[i].toString());//replace downloadImage method to whatever method you have to download the bitmap from url
UiApplication.getUiApplication().invokeLater(new Runnable(){
public void run()
{
mylist.invalidate();
}
});
}
}
}
}
public Object get(ListField listField, int index) {
// TODO Auto-generated method stub
return null;
}
public int getPreferredWidth(ListField listField) {
// TODO Auto-generated method stub
return 0;
}
public int indexOfList(ListField listField, String prefix, int start) {
// TODO Auto-generated method stub
return 0;
}
public static Bitmap connectServerForImage(String url) {
HttpConnection httpConnection = null;
DataOutputStream httpDataOutput = null;
InputStream httpInput = null;
int rc;
Bitmap bitmp = null;
try {
// httpConnection = (HttpConnection)
// Connector.open(url+";interface=wifi");
httpConnection = (HttpConnection) Connector.open(url);
rc = httpConnection.getResponseCode();
// System.out.println("===============================");
Dialog.alert("beore if condition");
if (rc == HttpConnection.HTTP_OK) {
System.out.println(" ============= IN FUNCTION. . . . .");
httpInput = httpConnection.openInputStream();
InputStream inp = httpInput;
byte[] b = IOUtilities.streamToBytes(inp);
EncodedImage hai = EncodedImage.createEncodedImage(b, 0,
b.length);
bitmp = hai.getBitmap();
} else {
throw new IOException("HTTP response code: " + rc);
}
} catch (Exception ex) {
System.out.println("URL Bitmap Error........" + ex.getMessage());
} finally {
try {
if (httpInput != null)
httpInput.close();
if (httpDataOutput != null)
httpDataOutput.close();
if (httpConnection != null)
httpConnection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return bitmp;
}
}
Dont know where i am wrong. Please can any budy help me for the same.
Several problems with your code:
The BitmapLazyLoader class looks like a consumer. It holds a Thread reference. This alone is very confusing, since Runnables are intended to be passed to a Thread constructor, but Runnables should not know about the thread for the sake of encapsulation. Letting this apart, this class attempts to spawn a thread only once, but as you are creating an instance of Runnable each time a row is drawn, you'll end up spawning a considerable number of threads. This will probably end in a TooManyThreadsException being thrown as in BlackBerry the max number of threads is limited to 16 per app. Even if you don reach the limit, performance will degrade as BlackBerries, which sport a single core CPU, you shouldn't have more than 2-3 threads running at the same time. EVEN if you could spawn infinite threads, in BlackBerry you can only have X connections opened at the same time (I think X is 5 for the whole OS, not sure about this). So first of all modify the code to ensure only a single worker thread is downloading images. (and if possible, extract the thread instantiation and launch out of the Runnable class).
When the bitmap is downloaded, you are not doing anything with it. Look at the ImageDownloadCompleted method, it is empty. (BTW, the convention for methods is to start with lowercase) So you should store the bitmap somewhere and call invalidate on your list, which in turn will paint the stored bitmaps.
Hope it helps.
You can try using this link :
http://www.coderholic.com/blackberry-webbitmapfield/
You have to create a separate class named as WebBitmapField as suggested in above link.
How to use that class in your list field image objects:
For every image url create WebBitmapField object
photoList_vector is the vector through which populate elements in
list field
WebBitmapField web = new WebBitmapField("http://www.image1.png");
photoList_vector.addElement(web);
web = new WebBitmapField("http://www.image2.png");
photoList_vector.addElement(web);
Now use this vector to work on your list field......
In the above lines we try to ensure that when we simultaneously send multiple requests to get the images then each image corresponds to a particular WebBitmapField Object.
Each object is then added to vector so that it can be added to the list field.
Each url send is tied to an object of WebBitmapField.
So though request is send in a separate thread it gets tied to its associated object only
Hope it helps
:)
I have worked on this problem, earlier, and I am posting my technique here, though its not ideal solution, as it was coupled very much with Screen class, but still might be helpful.
First in your screen class have one array for bitmaps having size equal to list field items.
public class TempScreen extends MainScreen{
Bitmap[] images=null;
String[] urls={"image1_url", "image2_url".....};
public TempScreen()
{
images=new Bitmap[urls.length];
}
now in drawListRow method of ListFieldCallBack, check for the following:
public void drawListRow(ListField list, Graphics g, int index, int y, int width){
if(bitmap[index]==null)
{
//Load placeholder image
}
else
//Load Bitmap
}
Now create a thread class to download the images:
public class ImageDownloader implements Runnable
{
public void run()
{
for(int i=0; i<size;i++)
{
if(images[i]==null)
{
images[i]=downloadImage(url[i]);//replace downloadImage method to whatever method you have to download the bitmap from url
UiApplication.getUiApplication().invokeLater(new Runnable(){
public void run()
{
list.invalidate()
}
});
}
}
}
}
Now in constructor of the screen class, after setting callback to listfield, start thread:
Thread downloader=new Thread(new ImageDownloader());
downloader.start();
Edit: Change TempScreen constructor to following:
public TempScreen()
{
images=new Bitmap[urls.length];
size = urls.length;
mylist = new ListField();
mylist.setCallback(this);
mylist.setSize(4);
mylist.setRowHeight(getFont().getHeight() * 3);
add(mylist);
Thread downloader=new Thread(new ImageDownloader());
downloader.start();
}
I am calling this class which is PopupScreen.
public class Custom_LoadingScreen extends PopupScreen {
private VerticalFieldManager vfm;
private Util_AnimateGifField anmtFldCycle = null;
private GIFEncodedImage gifImgCycle;
public Custom_LoadingScreen() {
super(new VerticalFieldManager());
Background bg = BackgroundFactory.createSolidTransparentBackground(
Color.BLACK, 190);
setBackground(bg);
setBorder(BorderFactory.createSimpleBorder(new XYEdges(),
Border.STYLE_TRANSPARENT));
gifImgCycle = (GIFEncodedImage) GIFEncodedImage
.getEncodedImageResource("LoadingSpinner.gif");
anmtFldCycle = new Util_AnimateGifField(gifImgCycle,
Field.FIELD_HCENTER);
vfm = new VerticalFieldManager(USE_ALL_WIDTH) {
protected void sublayout(int maxWidth, int maxHeight) {
super.sublayout(Display.getWidth(), Display.getHeight());
setExtent(Display.getWidth(), Display.getHeight());
}
};
int padding = (Display.getHeight() - 16) / 2;
if (padding > 0) {
anmtFldCycle.setPadding(padding, 0, 0, 0);
}
vfm.add(anmtFldCycle);
add(vfm);
}
//public void Popupscreen() {
//Main.getUiApplication().popScreen(this);
//}
public boolean keyDown(int keycode, int status) {
if (Keypad.key(keycode) == Keypad.KEY_ESCAPE) {
Main.getUiApplication().popScreen(this);
return true;
}
return super.keyDown(keycode, status);
}
}
In a button, I pushed it before goes to next screen.
financebtn = new Custom_ButtonField(finance, financeactive,
financeactive) {
protected boolean navigationClick(int status, int time) {
Main.getUiApplication().pushScreen(new Custom_LoadingScreen());
Main.getUiApplication().invokeLater(new Runnable() {
public void run() {
// Main.getUiApplication().popScreen();
Main.getUiApplication().pushScreen(
new Main_NewsDetail());
}
}, 1 * 1000, false);
return true;
}
};
add(financebtn);
The result give me Uncaught:ClassCastException. I can call another class which is similar to custom_loadingscreen also popupscreen. It work fine.
I also tried call this class in another button yet still same problem.
If you take a look at your Custom_LoadingScreen code, there's only one place where you are doing a cast:
gifImgCycle = (GIFEncodedImage) GIFEncodedImage
.getEncodedImageResource("LoadingSpinner.gif");
So, that's a good place to start looking. If you Google for "BlackBerry GIFEncodedImage ClassCastException", you'll find this thread:
http://supportforums.blackberry.com/t5/Java-Development/GIFEncodedImage-in-BlackBerry-OS7/td-p/1228959
The problem is that, for optimization, BlackBerry likes to convert images to the PNG format, which most smartphones work best with. So, what's happening here is that your GIF image is actually being converted to a PNG image. Therefore, when you call the getEncodedImageResource() method, the object you are getting back may actually be of type PNGEncodedImage, not GIFEncodedImage, and you get the exception. Sneaky, huh?
You can solve it a few ways.
In the Blackberry_App_Descriptor.xml file, you can uncheck the setting that specifies that images are converted to PNG (Build tab -> Convert image files to png)
You can trick the build system by renaming your GIF file to something like LoadingSpinner.agif. The toolset doesn't recognize the .agif extension, and therefore won't try to convert it. If you do this, of course, remember to change the filename in your Java code, too, when loading it.
You can change the code to use PNGEncodedImage, or test the object like this:
EncodedImage img = EncodedImage.getEncodedImageResource("LoadingSpinner.gif");
if (img instanceof GIFEncodedImage) {
// cast to GIFEncodedImage
} else if (img instanceof PNGEncodedImage) {
// cast to PNGEncodedImage
}
Number (1) will lose the non-PNG to PNG conversion optimization for all your non-PNG images, not just this one.
Number (2) does look a little ugly. The benefit of doing this, though, is that you can disable this behaviour for just this one image. If most of your images are not PNG images, it might be valuable to let BlackBerry optimize for you, for the other images. But, maybe this one needs to be a GIF. So, #2 lets you handle this one as a special case.
I'm just guessing that this image might be an animated GIF? Is that right? If so, you probably want to keep it as a GIF, so you won't want to do number (3), which lets it be converted to a PNG, and uses it as such.
So, I'm working on my paint application. Every time I make changes, the current screen state is copied and saved as a bitmap image on my disk (so I can use it in my paint event).
The problem occurs when I minimize and return the window to its normal state and then try to draw. This triggers my event reacting to changes, the program tries to save the image ---->>> kabooom.
It says "A generic error occurred in GDI+".. So, I've been surfing through various forums in search for the answer but none of them gave me true answer, they all mention wrong paths etc. but I'm pretty sure that's not the problem. Do I have to dispose bitmap or do something with the stream?
int width = pictureBox1.Size.Width;
int height = pictureBox1.Size.Height;
Point labelOrigin = new Point(0, 0); // this is referencing the control
Point screenOrigin = pictureBox1.PointToScreen(labelOrigin);
int x = screenOrigin.X;
int y = screenOrigin.Y;
Rectangle bounds = this.Bounds;
using (Bitmap bitmap = new Bitmap(width, height))
{
using (Graphics g = Graphics.FromImage(bitmap))
{
g.CopyFromScreen(new Point(x, y), Point.Empty, bounds.Size);
}
bitmap.Save(_brojFormi + ".bmp", System.Drawing.Imaging.ImageFormat.Bmp);
}
You're saving an image to disk so you can use it in another event? Wow.
Why not just use a class-global variable to store the bitmap?
class MyForm
{
Bitmap currentImage = null;
Graphics gfx = null;
private void btnLoad_Click(object sender, EventArgs e)
{
// ...
currentImage = new Bitmap(fileName);
gfx = Graphics.FromImage(currentImage);
}
private void pbEditor_Paint(object sender, PaintEventArgs e)
{
if (currentImage != null && gfx != null)
{
lock(currentImage) e.Graphics.DrawImage(currentImage, ...);
}
}
private void pbEditor_Click(object sender, MouseEventArgs e)
{
// quick example to show bitmap drawing
if (e.Button == MouseButtons.Left)
lock(currentImage) currentImage.SetPixel(e.Location.X, e.Location.Y, Colors.Black);
}
}