Titanium - Crop portion of image - image

How would you crop a small portion of a big image (e.g area of an imageview visible in a transparent frame) in appcelerator titanium for both iOS and android? imageAs** functions won't work as they aren't supported below android 3.0 . Here is my code:
var win=Ti.UI.createWindow({backgroundColor: 'white'})
var ImageView = Titanium.UI.createImageView({
width:200, height:200,
});
var cropView = Titanium.UI.createView({
width: 150,
height: 150,
borderColor: 'red',
borderWidth: 1,
zIndex: 1,
});
var button= Ti.UI.createButton({
bottom: 30,
width: 60,
title: 'OK',
zIndex: 1,
})
win.add(cropView)
Ti.Media.openPhotoGallery({
PhotoGalleryOptionsType : Ti.Media.MEDIA_TYPE_PHOTO,
success: function(e){
ImageView.image=e.media;
win.add(ImageView)
}, });
button.addEventListener('click',function(e)
{
// crop the visible area
})
I am using iOS 5 and android 2.2. Thanks for your help.

Add ImageView to cropView (rather than to win), position and size imageView so that the portion you want displayed is displayed (using negative values for left and top), and then call cropView.toImage(). You can use the resulting blob in a new image view, save it to a file, email it as an attachment, whatever you want.
Any portion of the image outside of its parents bounds will be cropped, leaving only the portion you specify.

I have done some small changes and now its all functional. Cheers!! :)
var win = Ti.UI.createWindow({
backgroundColor : 'white'
})
var orignal = Titanium.UI.createImageView({
width : Ti.UI.SIZE,
height : Ti.UI.SIZE,
left:5
});
var ImageView = Titanium.UI.createImageView({
width : 200,
height : 200
});
var cropView = Titanium.UI.createView({
top : 10,
width : 150,
height : 150,
borderColor : 'lime',
borderWidth : 1,
zIndex : 1,
left:150
});
var button = Ti.UI.createButton({
bottom : 30,
width : 60,
title : 'CROP',
zIndex : 1,
});
win.add(button);
Ti.Media.openPhotoGallery({
PhotoGalleryOptionsType : Ti.Media.MEDIA_TYPE_PHOTO,
success : function(e) {
ImageView.image = e.media;
orignal.image=e.media;
cropView.add(ImageView);
win.add(cropView);
win.add(orignal);
},
});
var CropedImageView = Titanium.UI.createImageView({
top : 200,
width : cropView.width,
height : cropView.height,
left:150
});
button.addEventListener('click', function(e) {
cropView.borderColor='transparent';
CropedImageView.image = cropView.toImage();
win.add(CropedImageView);
});
win.open();

I learnt some of this while my stay at Oodles Technologies.
Here's my contribution :
In this example you will see how to crop image in iOS Titanium.
To crop a image first create scroll view, define its maxZoomScale, minZoomScale.
maxZoomScale:-
Maximum Scaling factor of the scrollable region and its content.
minZoomScale:-
Minimum Scaling factor of the scrollable region and its content
maxZoomSale and minZoomScale we can adjust according to required.
then we have to add image view inside scrollview, then we can zoom in and zoom out image, to crop a image just need to click on crop button.
var window = Ti.UI.createWindow({
backgroundColor : 'white'
});
var scrollView = Ti.UI.createScrollView({
height : 260,
width : Ti.UI.FILL,
maxZoomScale : 4.0,
minZoomScale : 1.0,
zoomScale : 1.0,
});
window.add(scrollView);
var imageView = Ti.UI.createImageView({
height : scrollView.height,
width : scrollView.width,
backgroundColor : "transparent",
anchorPoint : {
x : 0.5,
y : 0.5
},
image : 'Default-568h#2x.png',
});
scrollView.add(imageView);
var button = Ti.UI.createButton({
top : 20,
title : 'Crop Button'
});
window.add(button);
button.addEventListener('click', function(e) {
button.hide();
var cropimage = scrollView.toImage();
var cropImageView = Ti.UI.createImageView({
top : 20,
height : 120,
width : 120,
image : cropimage
});
window.add(cropImageView);
});
window.open();

Related

Appcelerator - iOS : Animate view's opacity with animate method don't change the opacity property

Change the view's opacity with animate({}) method don't change the opacity property of the view.
It's normal?
Related ticket on jira
Test code
var win = Ti.UI.createWindow({
backgroundColor: "white"
});
var view = Ti.UI.createView({
width : 100,height : 100,backgroundColor : "red",opacity : 1.0
});
var label = Ti.UI.createLabel({
width : Ti.UI.FILL,top : 30,color : "red",textAlign : "center",font : {fontSize : 20}
});
var buttons = Ti.UI.iOS.createTabbedBar({
bottom : 30,labels : ["Without animate","With animate"],index : 0,tintColor : "red"
});
var temp = true;
setInterval(function(e){
if(temp){
if(buttons.index == 0)
view.opacity = 0.0;
else
view.animate({ opacity : 0.0 , duration : 0});
}else{
if(buttons.index == 0)
view.opacity = 1.0;
else
view.animate({ opacity : 1.0 , duration : 0});
}
temp = !temp;
label.text = "view opacity: " + view.opacity;
},200);
win.add(label,view,buttons);
win.open();
Everything is working as expected. All you need to know is little bit more info about how animations work in any platform, be it native Android, iOS or Titanium itself.
Doing animations on a View, Button, etc. moves only the rendered pixels on the screen of that element, but their properties' values remains same.
So, if you want, then you can set the View's original left value = 10 and then animate it to 100, and you will find that after completion of this animation - the left is still = 10 (not 100).
Therefore, you need to manually set those properties yourself at the end of the animation by passing a callback in animate() method.
Do remember that any UI element's properties do have their own getter & setter methods which changes the rendering of the element, but vice-versa is not true.
Here's your code (little modified) to play with which will give you what you wanted to see.
var win = Ti.UI.createWindow({
backgroundColor: "white"
});
var view = Ti.UI.createView({
width : 100,height : 100,backgroundColor : "red",opacity : 1.0,
left : 10
});
var label = Ti.UI.createLabel({
width : Ti.UI.FILL,top : 30,color : "red",textAlign : "center",font : {fontSize : 20}
});
var buttons = Ti.UI.iOS.createTabbedBar({
bottom : 30,labels : ["Without animate","With animate"],index : 0,tintColor : "red"
});
var temp = true;
setTimeout(function () {
view.animate({
left : 100,
duration : 1000
}, function () {
view.left = 100; // commenting this line will give you left = 10
label.text = "view left: " + view.left;
});
}, 1000);
win.add(label,view,buttons);
win.open();

How to dynamically remove imageViews stacked up on one another

I have tried the following code, the task I am trying to do is to first populate the window with an image stack and then every time you click on one, it removes it one by one.
var colors = ['red', 'blue', 'yellow', 'green', 'gray', 'black'];
for (var i in colors) {
var image = Titanium.UI.createImageView({
backgroundColor : colors[i],
top : 50,
left : 30,
width : 200,
height : 200
});
$.win.add(image);
}
image.addEventListener('click', function(e) {
alert(e);
alert(JSON.stringify(e.source));
$.win.remove(image);
});
and then when they click on each image, it gets removed from the window - the next one is then shown.
The event listener works fine for the first image view, but then stops working with the underlying ones.
I know that this can easily be done with a scrollableView, but I would like to try and do this using an image View stack.
Cheers.
You have to put the event listener inside the loop !
var colors = ['red', 'blue', 'yellow', 'green', 'gray', 'black'];
for (var i in colors) {
var image = Titanium.UI.createImageView({
backgroundColor : colors[i],
top : 50,
left : 30,
width : 200,
height : 200
});
//this is what you should do
image.addEventListener('click', function(e) {
alert(e); alert(JSON.stringify(e.source)); $.win.remove(image);
});
$.win.add(image);
}
Try this:
var colors = ['red', 'blue', 'yellow', 'green', 'gray', 'black'];
function imageHandler(_imgObj,_win)
{
_imgObj.addEventListener('click', function(e) {
alert(e);
alert(JSON.stringify(e.source));
_win.remove(image);
});
}
for (var i in colors) {
var image = Titanium.UI.createImageView({
backgroundColor : colors[i],
top : 50,
left : 30,
width : 200,
height : 200
});
imageHandler(image,$.win);
$.win.add(image);
}
What this does is remove the handler separates the handler and gives you more control. Through each iteration in the for-loop, each image has it's own handler defined and this should work.

Kineticjs - can not control scaled image

when you drag images you can control their moving with dragBoundFunc. Is there something similar when you scaling? I want to set an image area in "part of a stage" and when i setScale for this image and make it bigger, i don't want to see parts which is bigger than image area i've set before. is it possible? Here is my fiddle..
var stage = new Kinetic.Stage({
container : 'canvas',
width : 620,
height : 236
});
var layer = new Kinetic.Layer();
var leftImage = new Image();
leftImage.src = "http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg";
var leftImg = new Kinetic.Image({
x : stage.getWidth() - 480,
y : stage.getHeight() - 126,
image : leftImage,
width : 190,
height : 124,
offset : [95, 62],
draggable : true,
dragBoundFunc: function(pos) {
var x=stage.getWidth() - 480;
var y=stage.getHeight() - 126;
var radius = 50;
var scale = radius/ Math.sqrt(Math.pow(pos.x - x, 2) + Math.pow(pos.y - y, 2));
if(scale < 1)
return {
y: Math.round((pos.y - y) * scale + y),
x: Math.round((pos.x - x) * scale + x)
};
else
return pos;
}
});
var rectLeft = new Kinetic.Rect({
x : 38,
y : 20,
width : 232,
height : 184,
stroke:'red',
listening:false
});
var rectRight = new Kinetic.Rect({
x : 350,
y : 20,
width : 232,
height : 184,
stroke:'green',
listening:false
});
layer.add(leftImg);
layer.add(rectLeft);
layer.add(rectRight);
stage.add(layer);
document.getElementById('larger').addEventListener('click', function() {
leftImg.setScale(leftImg.getScale().x + 1.5);
layer.draw();
}, false);
Sure.
You can clip your scaled image into a fixed area of the stage by wrapping your image in a group and setting the clip property of that group to your fixed area.
If you set the clip property on a group like this:
var group=new Kinetic.Group({
x:100,
y:100,
width: originalImageWidth,
height: originalImageHeight,
clip: [0,0,originalImageWidth,originalImageHeight]
});
Then the image you put in the group will be clipped to stage #100,100 and size == original image size.
If you later scale the image larger, the clipping area will act as a "viewport" into part of the larger image.

Weird and unpredictable behavior by Views and Images from remote URL?

Here is my
APP.js
var win = Ti.UI.createWindow({
navBarHidden : true,
className : 'window',
backgroundColor : "#efefef"
});
var header = Ti.UI.createView({
height : 20,
width : 303,
top : 0,
backgroundColor : "#abc"
});
win.add(header);
var scroll = Ti.UI.createScrollView({
top : 44,
bottom : 44,
layout : 'vertical'
});
win.add(scroll);
header.addEventListener('click', function(evt) {
fetch_images();
});
win.open();
function fetch_images() {
var xhr = Ti.Network.createHTTPClient({
onload : function() {
myjson = JSON.parse(this.responseText);
for ( i = 0; i < myjson.length; i++) {
Ti.API.debug(i);
var look = new looks(myjson[i])
scroll.add(look);
}
},
onerror : function(e) {
Ti.API.debug("STATUS: " + this.status);
Ti.API.debug("TEXT: " + this.responseText);
Ti.API.debug("ERROR: " + e.error);
if (Titanium.Network.online) {
alert('No reponse from server.');
} else {
alert('Please Check your Internet connectivity.');
}
},
timeout : 5000
});
xhr.open('GET', 'http://xxxxxxx.com/xxxxxxx.json?api_token=xxxxxxxx');
xhr.send();
}
function looks(image_details) {
var look_container = Ti.UI.createView({
height : 325,
width : 303,
top : 10,
layout : 'horizontal',
backgroundColor : "#cac"
});
var look_image = i.UI.createImageView({
width : 303,
top : 0,
left : 0,
right : 0,
image : image_details.image_medium
});
look_container.add(look_image);
return look_container;
}
I am about to pull my hairs from my head.
Working with this for around last 4-5 hours.
Acc. to the code Image should be something like this
But it appears like this.
Any guess whats wrong !! Any help would be grateful ??
As per the code Image should be aligned to top (0px from top). But Image is always down the line in the view and dont stick to the top... ??
-------------------------EDIT---------------------------
I editted my code to check for static JPG images
and its same even for the Images in the resources directory
check this question developer.appcelerator.com/question
code
var win = Ti.UI.createWindow({
navBarHidden : true,
className : 'window',
backgroundColor : "#efefef"
});
var my_container = Ti.UI.createView({
height : 325,
width : 303,
top : 30,
backgroundColor : "#cac",
layout : "horizontal"
});
var my_image = Ti.UI.createImageView({
width : '100%',
top : 0,
left : 0,
right : 0,
image : 'hello.jpg'
});
my_container.add(my_image);
win.add(my_container);
my_container.addEventListener('click', function() {
my_image.top = my_image.top - 25;
})
win.addEventListener('click', function() {
my_image.top = my_image.top + 5;
})
win.open();
and image url for the image to be used.
The problem is not the layout properties, it is image scaling! Note first that you are passing a larger image than the view, so Titanium does some scaling under the sheets.
So when you define the width of that ImageView, if the image you pass is bigger than the view, Titanium scales it using its own mechanism, which obviously, is not what you want, since it has been causing you to tear your hair out the past few days. I believe they scale images from the bottom up, causing your weird problem.
To fix this, you need to take control of the image scaling from Titanium, and pass a new, resized image
To do this, we need to get the original height and width of the image, to preserve the aspect ratio, then figure out a new size, resize the image, and pass it to the imageView.
To get the height and width of the image you kind of have to hack around a bit, here is how I did it with SDK 2.1.1.GA:
Get Height and Width of a Blob / Image
// Load the image as a blob to get height information
var imageFile = Ti.Filesystem.getFile('hello.png');
var blobOfImage = imageFile.read();
// Put it in a imageView, since It wont let me get height from a blob for some reason
var imageView1 = Titanium.UI.createImageView({
image: blobOfImage,
width: 'auto',
height: 'auto',
});
// This is the important part, toImage this view and you get the height and width of this image
// For some reason we cant get this from a Blob in SDK 2.1.1.GA
var heightOfImage = imageView1.toImage().height;
var widthOfImage = imageView1.toImage().width;
Now we calculate the aspect ratio for the width (screen size for iPhone of 320).
Aspect Ratio
var aspectRatio = heightOfImage / widthOfImage;
And now we can create the new resized image in the imageview.
New Image!
var my_container = Ti.UI.createView({
height : 325,
width : 303,
top : 30,
backgroundColor : "#cac",
layout : "horizontal"
});
var my_image = Ti.UI.createImageView({
top : 0,
left : 0,
right : 0,
image : blobOfImage.imageAsResized(320, 320*aspectRatio) // Note the resize call to the image blob
});
Here is the final output :
So I guess the lesson is dont trust Titanium to scale your images for you.

Titanium mobile - addEventListener on a view

i'm making a scrollable menu using common JS.
An item of the menu is a view that contains 2 others components :
a imageView for the icon, and a label for the text of this menu.
The comportement is strange and not the same on the android and ios simulator.
On the android, if a click is done on the label or on the imageview, that gives an : "uncaught TypeError: Cannot Read property..."
On iphone, that just don't launch anything.
If i click somewhere else (still into the view item) but not on image or on the labal, for example on an edge, that works just perfect!!
here is the code:
function menuIcons(itemTab) {
var menuMain = Ti.UI.createView({
layout : 'vertical',
backgroundColor : '#333333',
height : 125,
bottom : 10,
left : 10,
right : 10,
borderRadius : 5.0
});
var menuFirstLine = Ti.UI.createScrollView({
scrollType : 'horizontal',
contentHeight : 120,
contentWidth : 'auto',
layout : 'horizontal',
height : 120,
marginLeft : 5
});
var items = [];
var menuIconsItem = require('view/module/menuIconsItem');
for(var i in itemTab) {
var page = itemTab[i].page;
items[i] = new menuIconsItem(itemTab[i]);
(function(itemsEvent) {
itemsEvent.id = itemTab[i].id;
itemsEvent.addEventListener('click', function(e) {
Ti.App.fireEvent('main_menu_' + itemsEvent.id, {
id : e.source.id
});
})
})(items[i]);
menuFirstLine.add(items[i]);
}
menuMain.add(menuFirstLine);
return menuMain;
}
module.exports = menuIcons;
and the code of the items that is required (var menuIconsItem = require('view/module/menuIconsItem');) :
function menuIconsItem(item) {
// path for images on Android besoin de centraliser tout ca
var pathImages = '';
var itemImage = Ti.UI.createImageView({
image : item.imageLink,
width : 64,
height : 64,
top : 15
});
var itemLabel = Ti.UI.createLabel({
color : '#afafaf',
text : item.text,
font : {
textAlign : 'center'
},
height : 40,
top : 80
});
var menuItem = Ti.UI.createView({
width : 120,
height : 120,
backgroundColor : '#424242',
top : 5,
left : 5
});
menuItem.add(itemImage);
menuItem.add(itemLabel);
return menuItem;
}
module.exports = menuIconsItem;
You have to set the id for the label and image view as well.

Resources