Clipping an ImageSnapshot in Flex - flex4

I'm using the ImageSnapshot.captureImage() method to screen capture a map image which is 2305 pixels high and 1134 pixels wide. I'm then trying to clip that image to one which is 1100 pixels high and 775 pixels wide.
public function grabScreenMapImage2():void {
// use ppi of 100 for testing
var ppi = 100;
var mapHeightInPixels = 1100
var mapWidthInPixels = 775
var snapImage:ImageSnapshot = ImageSnapshot.captureImage(myMap, ppi, new JPEGEncoder());
var bitmapData:BitmapData = new BitmapData(mapWidthInPixels, mapHeightInPixels);
var pixels:ByteArray = new ByteArray();
pixels = snapImage.data;
pixels.position = 0;
var clipRect:Rectangle = new Rectangle(0,0,mapWidthInPixels, mapHeightInPixels);
bitmapData.setPixels(clipRect, pixels);
}
However, I'm getting an error #2030 - end of file was encountered on my call to setPixels(), and cannot for the life of me work out why.
Any help greatly appreciated!
Thanks,
DrBacchus

This works for me. I zoom in on the original bitmap, then crop it into a new image the same size as the old one.
var myScaleFactor:Number = 1/3;
var zoomArea:Rectangle = bitmapData.rect;
zoomArea.inflate(zoomArea.width * imageScale, zoomArea.height * myScaleFactor);
var croppedImage = new BitmapData(zoomArea.width ,zoomArea.height,false,0xCCCCCC);
croppedImage.copyPixels(imageData,zoomArea,new Point(0,0));
var newImage = new BitmapAsset(croppedImage);

Related

How to extract pixel value from geometry points in shp format (2500 points) starting from an Image Collection resempled

I'm trying to extract the value of each single band of Sentinel-2 after resampling the bands from 10 meters to 30 meters using the resolution of the Landsat-8 (I didn't know how to do this in another way)
This is the code using band 4 as an example. When I try to export the values ​​in a table the running time is infinite and I was not able to extract even the value for a single point.
N.B. my area is very large, it corresponds to all of southern europe
thank you !
function maskS2clouds(image) {
var qa = image.select('QA60');
var cloudBitMask = 1 << 10;
var cirrusBitMask = 1 << 11;
var mask = qa.bitwiseAnd(cloudBitMask).eq(0).and(qa.bitwiseAnd(cirrusBitMask).eq(0));
return image.updateMask(mask).divide(10000).select("B.*").copyProperties(image, ["system:time_start"]);
}
var start = '2012-01-01';
var end = '2022-12-31';
var cld_max = 30;
var s2 = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED")
.filterBounds(Eur)
.filterDate(start,end)
.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE',60))
.map(maskS2clouds);
var land8 = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR').filterBounds(Eur)
var b4 = land8.select('B4').filterBounds(Eur); // 30-m resolution
var b4s = s2.select('B4').filterBounds(Eur); // 10-m resolution
var proj_10m = b4.first()
.projection();
function resample(image) {
var b4s = image.select('B4');
var b4s_res = b4s.resample('bilinear').reproject(proj_10m);
return b4s_res;
}
var b4s_res =b4s.map(resample).filterBounds(Eur);
//original code
var pts = b4s_res.map(function(img) {
var obs = img.reduceRegion(
{geometry: points , reducer: ee.Reducer.median(), scale: 80});
return img.set('B4', obs.get('B4'));
});
Export.table.toDrive({
collection: pts,
description: 'table_csv',
folder: 'earth_engine_demos',
fileFormat: 'CSV'
});
//test with geometry composed of two single points
var pts2 = b4s_res.map(function(img) {
var obs2 = img.reduceRegion(
{geometry: geometry , reducer: ee.Reducer.median(), scale: 80});
return img.set('B4', obs2.get('B4'));
});
Export.table.toDrive({
collection: pts2,
description:'prova_csv',
folder: 'earth_engine_demos',
fileFormat: 'CSV'
});
Is it possible to find a faster way to extract the value of the points (2500 random points) in the table? Do you also know another way to apply a resampling on all bands simultaneously and extract the corresponding value of each point for each single band?

Problem with synchronization of Potree viewer / camera with Cesium camera

Im trying to synchronize Potree camera with Cesium camera, like in this briliant example, but in oposite way (moves of Cesium camera control Potree camera).
function syncPotreeWithCesium() {
//lets get camera position and direction in Cesium
var newCamCoordinatesWC = cesiumViewer.scene.camera.positionWC;
var newDirectionCoordinatesWC = cesiumViewer.scene.camera.directionWC;
//as potree works in declaredEPSG, lets transform Cesium WC to declaredEPSG
var positionCartographicWC = Cesium.Ellipsoid.WGS84.cartesianToCartographic(newCamCoordinatesWC);
var directionCartographicWC = Cesium.Ellipsoid.WGS84.cartesianToCartographic(newDirectionCoordinatesWC);
var camPosXY = proj4(declaredEPSG,[(positionCartographicWC.longitude * (180/Math.PI)),(positionCartographicWC.latitude * (180/Math.PI))]);
var camDirXY = proj4(declaredEPSG,[(directionCartographicWC.longitude * (180/Math.PI)),(directionCartographicWC.latitude * (180/Math.PI))]);
//set Potree camera coordinates and direciton
potreeViewer.scene.view.position.set(camPosXY[0], camPosXY[1], positionCartographicWC.height);
potreeViewer.scene.view.lookAt(camDirXY[0], camDirXY[1], directionCartographicWC.height);
//"aspect" part from mentioned example seems to be applicable almost 1:1
var cesiumAspect = cesiumViewer.scene.camera.aspectRatio;
if(cesiumAspect < 1){
let fovy = Math.PI * (cesiumViewer.camera.frustum.fov / 180);
potreeViewer.scene.getActiveCamera().fov = fovy;
}else{
let fovy = Math.PI * (cesiumViewer.camera.frustum.fov / 180);
let fovx = Math.atan(Math.tan(0.5 * fovy) * cesiumAspect) * 2
potreeViewer.scene.getActiveCamera().fov = fovx;
}
//not sure if this part is needed in this simplified example
let camera = potreeViewer.scene.getActiveCamera();
camera.updateProjectionMatrix();
}
cesiumViewer.camera.changed.addEventListener(syncPotreeWithCesium);
`
As a result point cloud "dances" around desirable place in closeup, and gets even worse when zoomed out.
Except position and direction Cesium also needs „up” vector to set camera with this method, like here:
cesiumViewer.camera.setView({
destination : cameraPositon,
orientation : {
direction : dirVector,
up : upVector
}
And I do not see such setting in Potree camera/view settings. Is that causing a problem ?
Or am I missing more pieces to do it properly ??? Any help would be appreciated.

Amcharts4: How to add an image to an axis (valueAxis) label?

With amcharts4, I would like to add an image to a ValueAxis's label. Is this possible? I've found out, how to add an SVG image to a bullet (see demo). But is it possible to do something similar with the label of the ValueAxis?
Here is an example of such an image, I would like to add next to the number:
Currently, the value axis looks like this and it should have an icon next to the label:
EDIT:
Thanks to #zeroin's answer, I found a solution. However, there seems to be a strange bug when using an axis bullet with a template. Not every bullet is hidden even though its label is hidden. Here's the relevant code, a screenshot and a codepen to reproduce.
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.min = 0;
valueAxis.max = 800;
valueAxis.renderer.minGridDistance = 30;
valueAxis.renderer.opposite = true;
valueAxis.renderer.labels.template.dx = 13;
valueAxis.strictMinMax = true;
var image = new am4core.Image();
image.href = "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-160/man-user.svg";
image.width = 12;
image.horizontalCenter = "middle";
image.verticalCenter = "middle";
image.dx = 13;
image.dy = -0.5;
image.opacity = 0.3;
valueAxis.dataItems.template.bullet = image;
EDIT2:
This bug seems to be fixed in the current release of amcharts (4.5.14). It works now as expected.
Your question is right on time - in a version released today (4.5.9) we added bullet property to AxisDataItem. So you can add image or any other sprite to all axis labels via template or create axis range at a value you need and add bullet there, like:
var range = valueAxis.axisRanges.create();
range.value = 1500;
//range.label.text = "1500";
var image = new am4core.Image();
image.href = "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-160/man-user.svg";
image.width = 15;
image.horizontalCenter = "middle";
image.verticalCenter = "middle";
image.dx = -55;
range.bullet = image;
https://codepen.io/team/amcharts/pen/JgXqvp

How to achieve high quality cropped images from canvas?

I am desperately searching for a good cropping tool. There are a bunch out there, for example:
Croppic
Cropit
Jcrop
The most important thing that I am trying to find is a cropping tool, that crops images without making the cropped image low in resolution. You can hack this by using the canvas tag by resizing the image. This way the image itself stays native, only the representation is smaller.
DarkroomJS was also something near the solution, but, unfortunately, the downloaded demo did not work. I'll try to figure out whats wrong. Does someone know some great alternatives, or how to get the cropped images in...let's say "native" resolution?
Thanks in advance!
You are relying on the cropping tool to provide an interface for the users. the problem is that the image returned is sized to the interface and not the original image. Rather than me sifting through the various API's to see if they provide some way of controlling this behaviour (I assume at least some of them would) and because it is such a simple procedure I will show how to crop the image manually.
To use JCrop as an example
Jcrop provides various events for cropstart, cropmove, cropend... You can add a listener to listen to these events and keep a copy of the current cropping interface state
var currentCrop;
jQuery('#target').on('cropstart cropmove cropend',function(e,s,crop){
currentCrop = crop;
}
I don't know where you have set the interface size and I am assuming the events return the crop details at the interface scale
var interfaceSize = { //you will have to work this out
w : ?,
h : ?.
}
Your original image
var myImage = new Image(); // Assume you know how to load
So when the crop button is clicked you can create the new image by scaling the crop details back to the original image size, creating a canvas at the cropped size, drawing the image so that the cropped area is corectly positioned and returning the canvas as is or as a new image.
// image = image to crop
// crop = the current cropping region
// interfaceSize = the size of the full image in the interface
// returns a new cropped image at full res
function myCrop(image,crop,interfaceSize){
var scaleX = image.width / interfaceSize.w; // get x scale
var scaleY = image.height / interfaceSize.h; // get y scale
// get full res crop region. rounding to pixels
var x = Math.round(crop.x * scaleX);
var y = Math.round(crop.y * scaleY);
var w = Math.round(crop.w * scaleX);
var h = Math.round(crop.h * scaleY);
// Assume crop will never pad
// create an drawable image
var croppedImage = document.createElement("canvas");
croppedImage.width = w;
croppedImage.height = h;
var ctx = croppedImage.getContext("2d");
// draw the image offset so the it is correctly cropped
ctx.drawImage(image,-x,-y);
return croppedImage
}
You then only need to call this function when the crop button is clicked
var croppedImage;
myButtonElement.onclick = function(){
if(currentCrop !== undefined){ // ensure that there is a selected crop
croppedImage = myCrop(myImage,currentCrop,interfaceSize);
}
}
You can convert the image to a dataURL for download, and upload via
imageData = croppedImage.toDataURL(mimeType,quality) // quality is optional and only for "image/jpeg" images

Why are transparent pixels showing up black in my image?

I am saving an image bytes array as a thumbnail. The problem is that the transparent background color is black in my image.
Below is my code:
MemoryStream memoryStream = new MemoryStream(pbytImageByteArray);
System.Drawing.Image imgImageSource = System.Drawing.Image.FromStream(memoryStream);
double dblOrgnWidth = imgImageSource.Width;
double dblOrgnHeight = imgImageSource.Height;
double dblRatio = (dblOrgnWidth / dblOrgnHeight) * 100;
double dblScaledWidth = pintWidth;
double dblScaledHeight = 0;
dblScaledHeight = (dblScaledWidth / dblRatio) * 100;
System.Drawing.Bitmap bitmapImage = new System.Drawing.Bitmap(System.Convert.ToInt32(dblScaledWidth), System.Convert.ToInt32(dblScaledHeight));
bitmapImage.SetResolution(imgImageSource.HorizontalResolution, imgImageSource.VerticalResolution);
System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(bitmapImage);
graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
ImageAttributes imageAttributes = new ImageAttributes();
graphics.DrawImage(imgImageSource, new System.Drawing.Rectangle(0, 0, System.Convert.ToInt32(dblScaledWidth), System.Convert.ToInt32(dblScaledHeight)), 0, 0, System.Convert.ToInt32(dblOrgnWidth), System.Convert.ToInt32(dblOrgnHeight), System.Drawing.GraphicsUnit.Pixel);
MemoryStream outputMemoryStream = new MemoryStream();
bitmapImage.Save(outputMemoryStream, System.Drawing.Imaging.ImageFormat.Jpeg);
bitmapImage.GetThumbnailImage(System.Convert.ToInt32(dblScaledWidth), System.Convert.ToInt32(dblScaledHeight), null, IntPtr.Zero);
imgImageSource.Dispose();
bitmapImage.Dispose();
graphics.Dispose();
return outputMemoryStream.ToArray();
JPEG doesn't support transparency. Save as a PNG.
Alternatively, if you know the background color that this will be on, you could set the transparent pixels to that color. If you are using semi-transparent pixels, then you would have to blend the pixels with that color.
Here is an article that explains alpha blending:
http://www.c-sharpcorner.com/UploadFile/mahesh/DrawTransparentImageUsingAB10102005010514AM/DrawTransparentImageUsingAB.aspx
If you are interested in a commercial solution for that (Disclaimer: I work for Atalasoft), DotImage Photo has a class, FlattenAlphaCommand, that can do this in a couple of lines of code.

Resources