I'm writing an app whose sole purpose is to periodically download some images and display them in a live tile. I want to be able to update the tile with 4-8 images every thirty minutes or so, so I need to use a CycleTile. Downloading the images and getting them into a live tile is pretty straight forward. The real kicker is adding text on each image.
If it was just two images, I would use a flip tile, displaying one on the front and one on the back. Then I would add the text by assigning a different tile title to the front and back. However, since I need to display more than 2 images, I need to use the CycleTile. And this approach won't work with the CycleTile. (but please, correct me if I'm wrong!)
So my next thought was to overlay a TextBlock on a WriteableBitmap. This could work, but i think it would get complicated quickly taking into account factors like: different image resolutions, medium/large tile layouts, and varying screen PPIs. I'm sure I could figure it out, but it seems... messy.
Is there a better way to do this? Are there some Tile features I'm overlooking?
To sum it up my requirements are:
Display 4-8 images using a live tile.
Each image needs to have some text associated with it.
Update the images every thirty minutes or so.
Needs to scale to wide tiles.
Needs to scale to phones with higher PPI screens.
For item one, you should be able to merge as many images together using the Blit method from the WriteableBitmapEx project. Since you can merge your images together in any way you want, you can ensure they cover wide tile widths and any ppi you need.
To cover the second item, the following will overlay text on an image:
private static ImageSource createBitmapImageWithImage(string text, int x, int y, Color textColor, BitmapSource bitmapSource)
{
using(var mem = new MemoryStream())
{
//Create Formatted Text
var textBlock = new TextBlock
{
Text = text,
Foreground = new SolidColorBrush(textColor),
FontFamily = new FontFamily("Courier New"),
FontSize = 40
};
//Moves an object two dimensionally
var tf = new TranslateTransform
{
X = x,
Y = y
};
//Overlay text on existing image
var bmpImage = new WriteableBitmap(bitmapSource);
bmpImage.Render(textBlock, tf);
bmpImage.Invalidate();
//Convert back into bitmap
bmpImage.SaveJpeg(mem, bmpImage.PixelWidth, bmpImage.PixelHeight, 0, 100);
mem.Seek(0, SeekOrigin.Begin);
var image = new BitmapImage();
image.SetSource(mem);
return image;
}
}
Of course you can pass in the text block too, or the options to configure the text block. But I wanted to show how you can format the text however you want.
Your third request is covered by background tasks. In your phone solution, add a new project and you can select background task. It is fairly straightforward to have this call your code to update the images. Nokia even created a walk through on how to add one with code examples.
Related
I am getting my feet wet with JavaFX, and have a simple drawing program which writes to a Canvas using a PixelWriter. The program draws a pixel at a time, reflecting each pixel over a number of axes to create a growing and evolving pattern centered on the canvas:
The Canvas is in the Center region of a BorderPane, and I have written the code to resize the canvas when the application window is resized. That works OK.
However, I would like to re-center the image on the new resized canvas so that the drawing can continue to grow on the larger canvas. What might be the best approach?
My ideas/attempts so far:
Capture a snapshot of the canvas and write it back to the resized canvas, but that comes out blurry (a couple of code examples below).
I dug into GraphicsContext translations, but that does not seem to move the existing image, just adjusts future drawing.
Maybe instead of resizing the canvas, I make a huge canvas bigger than I would expect my app window to be, and center it over the center region of the border pane (perhaps using a viewport of some kind?) I'm not thrilled about the whole idea of making some arbitrarily huge canvas that I think will be big enough though. I don't want to get into scaling - I am using PixelWriter so that I get the crispest image without antialiasing and other processing.
My snapshot attempt looked like this, but was blurry:
SnapshotParameters params = new SnapshotParameters();
params.setFill(Color.WHITE);
WritableImage image = canvas.snapshot(params, null);
canvas.getGraphicsContext2D().drawImage(image, 50, 50);
The 50, 50 offset above is just for my testing/learning - I'll replace it with a proper computed offset once I get the basic copy working. From the post How to copy contents of one canvas to another? I played with the setFill() parameter, to no effect.
From the post How to save a high DPI snapshot of a JavaFX Canvas I tried the following code. It was more clear, but I have not been able to figure out how to find or compute the pixelScale to get the most accurate snapshot (the value 10 is just some number I typed in bigger than 1 to see how it reacted):
int pixelScale = 10;
WritableImage image = new WritableImage((int)Math.rint(pixelScale * canvas.getWidth()),(int)Math.rint(pixelScale * canvas.getHeight()));
SnapshotParameters params = new SnapshotParameters();
params.setTransform(Transform.scale(pixelScale, pixelScale));
params.setFill(Color.WHITE);
canvas.snapshot(params, image);
canvas.getGraphicsContext2D().drawImage(image, 50, 50);
Thanks for any direction y'all can point me in!
I searching an days for this question.
I want to Crop Images like that, in flutter:
GIF Source: https://github.com/ArthurHub/Android-Image-Cropper
The closest lib for this solution is the Image Lib, that lib offers manipulate images and crop, but i want to crop images in UI level like this gif. All libs I found dont offers that.
There is no widget that performs all that for you. However, I believe that it is possible to write that natively in flutter now. I don't have time at this particular moment to do it for you, but I can definitely point you in the right direction.
You're going to need to load the image in such a way that you can either draw it onto a canvas or use a RawImage to draw it rather than using the Image widget directly.
You need to figure out a co-ordinate system relative to the image
You'll need to find a way of drawing the crop indicator - you could do this either by drawing directly on the canvas or possibly using some combination of GestureDetector/Draggable/DropTarget. I'd suggest that sticking to Canvas might be the easiest to start.
Once the user has selected a part of the image, you need to translate the screen co-ordinates to picture co-ordinates.
You then have to create an off-screen canvas to draw the cropped image to. There are various transforms you'll have to do to makes sure the image ends up in the right place.
Once you've made the off-screen crop, you'll have to display the new image.
All of that is quite a lot of work, and probably a lot of finessing to get right.
Here's examples for a couple of the steps you'll need to do, but you'll have to figure out how to put them together.
Loading an image:
var byteData = await rootBundle.load("assets/image.jpg");
Uint8List lst = new Uint8List.view(byteData.buffer);
var codec = await UI.instantiateImageCodec(lst);
var nextFrame = await codec.getNextFrame();
var image = frameInfo.image;
Displaying an image on a canvas:
https://docs.flutter.io/flutter/dart-ui/Canvas/drawImageRect.html
https://docs.flutter.io/flutter/rendering/CustomPainter-class.html
Writing an image to a off-screen canvas:
ui.Image getCroppedImage(Image image, Rect src, Rect dst) {
var pictureRecorder = new ui.PictureRecorder();
Canvas canvas = new Canvas(pictureRecorder);
canvas.drawImageRect(image, src, dst, Paint());
return pictureRecorder.endRecording().toImage(dst.width.floor(), dst.height.floor());
}
You'll probably need to do something like this answer for getting the local coordinates of mouse/touch gestures.
Some advice - I'd start as simple as possible, not thinking about performance to start (i.e. draw everything each paint if needed, etc). Then once you get the basics working you can start thinking of optimization (i.e. using a RawImage, Transform, and Stack for the image and only re-drawing the selector, etc).
If you need any additional help let me know in a comment and I'll do my best to answer. Now that I've been writing about this a bit it does make me slightly curious to try implementing it so I may try at some point, but it probably won't be soon as I'm quite low on time at the moment. Good luck =D
The image_cropper plugin does exactly what you are looking for.
I have an NSTextAttachment which contains an NSImage. What I would like to do is scale this image so that it's smaller in dimensions but will keeping the same number of pixels. Then moving it to the general pasteboard. Once it's pasted (into whatever app) I would like it to paste with the same dimensions I just set. The problem I am having is that pasting it in any other app always puts it at is original dimensions. I have tried the following things and none seem to fully work
First is simply resizing the image and then copying. This retains the proper dimensions (let's say 100 x 100 pt) but the image is very blurry and the resolution is 72 dpi.
//variable im is an NSImage object that is present
//variable newsize is an NSSize which is calculated to give the image proper resolution
im.lockFocus()
im.size = newsize
im.unlockFocus()
The second thing I have tried is use the techniques listed on this page. None of which do anything once I paste the TextAttachment to another app (such as Pages for example). Subclassing NSTextAttachment has no effect. Also changing the bounds of the attachment seems to have no effect once it's pasted.
The last thing I tried is after the iterating through the NSAttributedString which holds the attachments, and setting each one's bounds. Still no effect when pasting into other apps.
So the ultimate question: is there a way to have a scaled NSImage inside and NSTextAttachment copy to the clipboard?
func copy() {
let pboard = NSPasteboard.general()
pboard.clearContents()
let rtf = NSMutableAttributedString()
//self.images is an array that contains a bunch of images
//note that it is required that I use a RTF to copy/paste my images
//because there is text mixed with the images
//for simplicity I have removed the text from this code
//removing it from my app and doing the same code has no effect
for im in self.images {
let a = NSTextAttachment() //subclassing NSTextAttachment has no effect on pasted image size
a.image = im
a.bounds = NSMakeRect(0,0,100,100) //has no effect on pasted image size
//if I resize the image prior to copying (using the code above)
//the pasted image has correct dimensions but is very blurry.
let str = NSAttributedString(attachment: a)
rtf.append(str)
}
pboard.writeObjects([rtf])
}
Here goes my first question. I've embedded a youtube video (HTML5) in a panel created using the Panel API from Firefox SDK. The problem is that the video won't go fullscreen. It tries to, but goes back to normal size within the panel. I've also tried to use the method described here with a random div but the same thing happens. So, is this a limitation from the api or is there any way I could get it to work? Thanks.
I've just started experimenting with a floating YouTube player plugin using the Firefox sdk and ran in to the same issue. I did find a some what sloppy work around, that you might find suitable to use.
This method causes the panel to resize to the full screen. However, when resizing it, even with the border property set to 0, the panel will still show a bit of a border.
in the main document, "index.js"
var self = require('sdk/self');
var data = require("sdk/self").data;
let { getActiveView }=require("sdk/view/core");
let myPanel = require("sdk/panel").Panel({
contentURL: "./index.htm",
contentScriptFile: ["./youtube.js", "./index.js"]
});
var player = getActiveView(myPanel);
player.setAttribute("noautohide", true);
player.setAttribute("border", 0);
player.setAttribute('style', 'background-color:rgba(0,0,0,0);');
myPanel.show();
init();
myPanel.port.on('fullscreen', fullScreen);
function init(){
var size = 30,
width = size * 16,
height = size * 9;
myPanel.resize(width,height);
}
function fullScreen(width, height){
player.moveTo(3840, 0); // Need to moove the video to the top left
//of the monitor or else the resize only takes a potion of the screen.
//My left position is 3840 because i'm doing this on my right
//screen and the left is 4k so i need the offset.
myPanel.resize(width,height);
}
And in my content script file
var container = document.getElementById('container'),
overlay = document.getElementById('overlay');
overlay.addEventListener('click', fullscreen);
function fullscreen() {
var x = window.screen.availWidth,
y = window.screen.availHeight;
self.port.emit('fullscreen', x, y);
}
Some things I've noticed while experimenting is that when playing YouTube videos in the panel, the video has a tendency to lag, but the audio plays fine. The lag gets more apparent when moving the mouse over elements on other pages, and over the panel itself. The faster the movement the more apparent it becomes. I've found a workaround for mousing over the panel by placing an div that stretches over the video. The problem with this is that the default YouTube controls don't react to the mouse over, which would be possible to get around by using the YouTube api and creating custom controls. Also multiple monitor support would be hard to work with when positioning the video.
Edit:
Here's another way that does the same thing, but this one appears to deal with multi monitor support. It will position to the top left of whatever window firefox is currently on.
in the index.js file
function fullScreen(width, height){
myPanel.hide();
myPanel.show({position:{left:0,top:0}});
myPanel.resize(width,height);
}
Just first off I'll say that the context here is Actionscript 3.0 (IDE: Flashbuilder) along with the Starling Framework.
So, I want to create a Tile Map that could be used for a platformer or something similar.
I want to use 8x8 pixel tiles on an 800x600 pixel stage, and the problem I am having is that I don't know how to add these 7500+ tile objects to the stage without dramatically reducing the framerate.
I've found that the drop in performance comes from adding each tile to the stage, not from initializing each Tile object.
I know I'm not giving much specific information, but what I'm asking for is if there is a standardized way to draw thousands of static objects onto the stage without a loss of performance. I feel like there is a way, and I just have yet to find it.
Update:
After all of your kind help, I have found what seems to be a great solution. At first I wanted to implement Amy's solution, using copyPixels() and draw() to make one large bitmap data for the whole map and then render that to the screen. Then, though, I wanted to know if there was a Starling equivalent to this, because everything would be so much simpler if I didn't have to mix Starling with Native Flash.
Thanks to Amy again, I looked into Starling's RenderTexture class a bit more, and found that using it's "drawBundled()" and "draw()" methods, I could easily draw all of the tiles into a RenderTexture, and then put the RenderTexture into an Image (Starling's Image Class) and then just add that Image to the screen.
That solution is a million times faster than the silly slow solutions I tried before, with flattening sprites and such. Its faster both in it's initialization time and there seems to be no drop in framerate while the renderTexture's Image is on the screen.
The one thing I want to test with this is if it is easy to update the graphics of a tile during the gameplay. Say, if water spreads from a source (or something) and a "Grass" tile had to become a "Water" tile, would the RenderTexture and it's image be able to change their appearance without some sort of lag spike or performance hiccup. I will test this out soon.
Thank you all for your help!
Don't add that many objects to the stage. Instead, create a BitmpaData the size of your stage and use copyPixels() or draw() to draw onto it. Here's an article that should get you started. You can then take the concepts you learned in that post and learn anything specific you need to do that's not covered (flashandmath.com has a lot of good tutorials about pixel manipulation)
You need to manage the tiles that need to be added and removed as you move around the game. Only add to stage tiles that are with in 800 px of the center of the screen. Once the tile is beyond 800 px from center remove it. That should keep everything moving smoothly. Good luck.
or look into drawing/coping your tiles into one bitmap. You would be basically stamping your tiles onto the new bitmap. Here is an example from adobe:
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.geom.Rectangle;
import flash.geom.Point;
var bmd1:BitmapData = new BitmapData(40, 40, false, 0x000000FF);
var bmd2:BitmapData = new BitmapData(80, 40, false, 0x0000CC44);
var rect:Rectangle = new Rectangle(0, 0, 20, 20);
var pt:Point = new Point(10, 10);
bmd2.copyPixels(bmd1, rect, pt);
var bm1:Bitmap = new Bitmap(bmd1);
this.addChild(bm1);
var bm2:Bitmap = new Bitmap(bmd2);
this.addChild(bm2);
bm2.x = 50;
More Info on the bitmapData class. I think copyPixels is what you are after.