{ "id": "112587", "key": "TIMOB-13497", "fields": { "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false }, "project": { "id": "10153", "key": "TIMOB", "name": "Titanium SDK/CLI", "projectCategory": { "id": "10100", "description": "Titanium and related SDKs used in application development", "name": "Client" } }, "fixVersions": [ { "id": "15486", "description": "2013 Sprint 10 API", "name": "2013 Sprint 10 API", "archived": true, "released": true, "releaseDate": "2013-05-20" }, { "id": "15108", "description": "2013 Sprint 10", "name": "2013 Sprint 10", "archived": true, "released": true, "releaseDate": "2013-05-20" } ], "resolution": { "id": "2", "description": "The problem described is an issue which will never be fixed.", "name": "Won't Fix" }, "resolutiondate": "2013-05-14T21:13:56.000+0000", "created": "2013-04-09T17:35:40.000+0000", "priority": { "name": "High", "id": "2" }, "labels": [ "SupportTeam", "triage" ], "versions": [], "issuelinks": [], "assignee": { "name": "vduggal", "key": "vduggal", "displayName": "Vishal Duggal", "active": false, "timeZone": "America/Los_Angeles" }, "updated": "2017-03-22T22:55:28.000+0000", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "components": [ { "id": "10206", "name": "iOS", "description": "iOS Platform" } ], "description": "h2. Problem Description\r\nSample app taking pictures with camera and adding them in a ScrollView crashes on iPhone 4 after 7-8 images are added. The log shows a \"Memory warning\" message. No issues found with iPhone 5.\r\n\r\nh2. Test code\r\n{code}\r\nvar damageImages = [];\r\nvar win = Ti.UI.createWindow({\r\n backgroundColor : '#fff'\r\n});\r\n\r\nvar imageView = Ti.UI.createView({\r\n layout : 'horizontal',\r\n width : Ti.UI.FILL,\r\n height : Ti.UI.SIZE\r\n });\r\n\r\nvar successCallBack = function(e) {\r\n if (e.mediaType != Ti.Media.MEDIA_TYPE_PHOTO) {\r\n takePhotoBtn.enabled = true;\r\n pickPhotoBtn.enabled = true;\r\n return false;\r\n }\r\n\r\n var filename = (new Date().getTime()) + \".jpg\";\r\n var newImageWrapperView = Ti.UI.createView({\r\n backgroundColor : '#000',\r\n left : '8dp',\r\n top : '10dp',\r\n height : '96dp',\r\n width : '96dp',\r\n isImage : true\r\n });\r\n newImageWrapperView.id = filename;\r\n var newImageView = Ti.UI.createImageView({\r\n isImage : true,\r\n zIndex : 10\r\n });\r\n newImageView.opacity = 0.5;\r\n newImageWrapperView.add(newImageView);\r\n\r\n var bgImage = Titanium.Filesystem.getFile(Titanium.Filesystem.applicationDataDirectory, filename);\r\n newImageView.image = bgImage.getNativePath();\r\n\r\n //I need this for let use..\r\n damageImages.push({\r\n \"id\" : bgImage.getNativePath(),\r\n \"name\" : filename,\r\n \"description\" : \"\"\r\n });\r\n\r\n //resizing code also removed\r\n /*\r\n var imageModify = Ti.UI.createImageView({\r\n image : e.media\r\n });\r\n var width = imageModify.toImage().width\r\n var height = imageModify.toImage().height\r\n imageModify = null;\r\n var scaledImage = require('lib/utils').resizeKeepAspectRatioNewWidth(e.media, width, height, Config.imageMaxWidth);\r\n */\r\n bgImage.write(e.media);\r\n //scaledImage = null;\r\n bgImage = null;\r\n imageView.add(newImageWrapperView);\r\n\r\n takePhotoBtn.enabled = true;\r\n pickPhotoBtn.enabled = true;\r\n};\r\n\r\nvar errorCallBack = function(e) {\r\n takePhotoBtn.enabled = true;\r\n pickPhotoBtn.enabled = true;\r\n alert(L('erroronselectimage', 'Error while selecting image'));\r\n};\r\nvar cancelCallBack = function(e) {\r\n takePhotoBtn.enabled = true;\r\n pickPhotoBtn.enabled = true;\r\n};\r\n\r\n\r\nvar takePhotoBtn = Titanium.UI.createButton({\r\n style : Titanium.UI.iPhone.SystemButtonStyle.BORDERED,\r\n title : 'Take Photo'\r\n});\r\n\r\ntakePhotoBtn.addEventListener('click', function(e) {\r\n Ti.Media.showCamera({\r\n success : successCallBack,\r\n error : errorCallBack,\r\n cancel : cancelCallBack,\r\n allowEditing : false,\r\n saveToPhotoGallery : true,\r\n mediaTypes : [Ti.Media.MEDIA_TYPE_PHOTO]\r\n });\r\n takePhotoBtn.enabled = false;\r\n pickPhotoBtn.enabled = false;\r\n});\r\n\r\nvar pickPhotoBtn = Titanium.UI.createButton({\r\n style : Titanium.UI.iPhone.SystemButtonStyle.BORDERED,\r\n title : 'Pick Photo'\r\n});\r\n\r\npickPhotoBtn.addEventListener('click', function(e) {\r\n Ti.Media.openPhotoGallery({\r\n success : successCallBack,\r\n error : errorCallBack,\r\n cancel : cancelCallBack,\r\n allowEditing : false,\r\n mediaTypes : [Ti.Media.MEDIA_TYPE_PHOTO]\r\n });\r\n takePhotoBtn.enabled = false;\r\n pickPhotoBtn.enabled = false;\r\n});\r\n\r\nvar flexSpace = Titanium.UI.createButton({systemButton : Titanium.UI.iPhone.SystemButton.FLEXIBLE_SPACE});\r\n\r\nvar toolbar = Ti.UI.iOS.createToolbar({\r\n borderTop : true,\r\n borderBottom : false,\r\n height : 45,\r\n zIndex : '100',\r\n bottom : '0dp'\r\n });\r\ntoolbar.items = [flexSpace, takePhotoBtn, pickPhotoBtn, flexSpace];\r\n\r\n\r\nvar scrollView = Ti.UI.createScrollView({\r\n layout : 'vertical',\r\n top : 0,\r\n bottom : 45\r\n });\r\n scrollView.add(imageView);\r\n win.add(scrollView);\r\n win.add(toolbar);\r\n\r\nwin.open();\r\n{code}\r\n", "attachment": [], "flagged": false, "summary": "iOS: app crashing on iPhone 4 when adding images to ScrollView", "creator": { "name": "dcassenti", "key": "dcassenti", "displayName": "Davide Cassenti", "active": true, "timeZone": "Europe/Berlin" }, "subtasks": [], "reporter": { "name": "dcassenti", "key": "dcassenti", "displayName": "Davide Cassenti", "active": true, "timeZone": "Europe/Berlin" }, "environment": "SDK 3.0.2\r\niOS 6.1", "comment": { "comments": [ { "id": "246659", "author": { "name": "dcassenti", "key": "dcassenti", "displayName": "Davide Cassenti", "active": true, "timeZone": "Europe/Berlin" }, "body": "During tests, devices even crashed entirely (e.g. reboot).", "updateAuthor": { "name": "dcassenti", "key": "dcassenti", "displayName": "Davide Cassenti", "active": true, "timeZone": "Europe/Berlin" }, "created": "2013-04-09T17:39:57.000+0000", "updated": "2013-04-09T17:39:57.000+0000" }, { "id": "246816", "author": { "name": "nagaharish", "key": "nagaharish", "displayName": "Naga harish M", "active": true, "timeZone": "Asia/Kolkata" }, "body": "Hi,\r\n\r\nI tested with iPhone 4s and app is crashing most of the cases after taking 6-8 images using camera.\r\nI don't think this is problem with adding to Scrollview. Because app is crashing when we open the camera using `showCamera` only.\r\nCan you please make this high Priority.\r\nThank you.", "updateAuthor": { "name": "nagaharish", "key": "nagaharish", "displayName": "Naga harish M", "active": true, "timeZone": "Asia/Kolkata" }, "created": "2013-04-10T05:38:16.000+0000", "updated": "2013-04-10T05:38:16.000+0000" }, { "id": "246841", "author": { "name": "anigam", "key": "anigam", "displayName": "Ashish Nigam", "active": true, "timeZone": "Asia/Kolkata" }, "body": "HI,\r\n Verified The issue with iPhone 5 also and Crashes on that also but number of images taken are quite high approx 30 to 35.\r\n**Device Crash Log**\r\n{code}\r\nIncident Identifier: DD9157D8-314E-4EA2-825A-957D681B5A2D\r\nCrashReporter Key: bd158f36569796279d86b0f6c5ca6b83e9c330f3\r\nHardware Model: iPhone5,1\r\nOS Version: iPhone OS 6.0 (10A405)\r\nKernel Version: Darwin Kernel Version 13.0.0: Sun Aug 19 00:31:06 PDT 2012; root:xnu-2107.2.33~4/RELEASE_ARM_S5L8950X\r\nDate: 2013-04-10 14:55:31 +0530\r\nTime since snapshot: 1306 ms\r\n\r\nFree pages: 2738\r\nActive pages: 1306\r\nInactive pages: 19709\r\nThrottled pages: 84705\r\nPurgeable pages: 251\r\nWired pages: 149309\r\nLargest process: conceptTest\r\n\r\nProcesses\r\n Name rpages recent_max [reason] (state)\r\n\r\n assetsd <53881b88f0bf3948871456faf8fe5587> 1522 1522 [vm] (daemon) (idle)\r\n MobileMail <7ddddc607bec3f1f9ac5212a22279714> 1355 1355 (resume) (continuous)\r\n MobilePhone <3fefa53221ce3ccc867ade7d0f2b743a> 1300 1300 (resume) (continuous)\r\n kbd <98304e71b044348cbbc1fd3a7f0cda5a> 591 591 (daemon)\r\n tccd <96c9594f71b53a7fb5db7bd63ca52c90> 285 285 (daemon)\r\n conceptTest <33514e224eeb36d182595067e925de72> 159731 160082 [per-process-limit] (frontmost) (resume)\r\n ptpd 1094 1094 (daemon)\r\n dataaccessd <0db5b1392b6c391496eaa9eff8122088> 1089 1089 (daemon)\r\n syslogd <76c7ece27e1930ccba213a9ed4d6ead0> 187 187 (daemon)\r\n wifid <3c1b8ae2bd1f3453b8a34769c57a800a> 636 636 (daemon)\r\n iaptransportd <589c47b3c06c3c8bb33b4044c6a94321> 355 355 (daemon)\r\n locationd <5cca2615d1c23508808fd442ccf28470> 1263 1263 (daemon)\r\n mediaserverd <80947eda91eb396d841f65d9deac2d76> 28835 28835 (daemon)\r\n timed <8984d2e17535329cbfd4baf3a9b8f963> 410 410 (daemon)\r\n lsd 356 356 (daemon)\r\n SpringBoard 5622 5622 \r\n backboardd <29faa2a7d1f1304c87418beb50a7e458> 5607 5607 (daemon)\r\n fairplayd.N41 <185d84e38a5230ffaaa6b21cdcbb4754> 326 326 (daemon)\r\n fseventsd 351 351 (daemon)\r\n imagent 436 436 (daemon)\r\n mDNSResponder <8a128a0397f93f6f8ede1df8f60759a5> 354 354 (daemon)\r\n lockdownd <66d819d22a643069b42aa2dbd7229db2> 396 396 (daemon)\r\n powerd 240 240 (daemon)\r\n UserEventAgent <4df6d63523a138f19d67bd59137827e1> 744 744 (daemon)\r\n softwareupdated 292 292 (daemon)\r\n mobileassetd 427 427 (daemon)\r\nsoftwareupdatese 630 630 (daemon)\r\nspringboardservi 0 0 (daemon)\r\n DTMobileIS <9d4add29c730382583f03d7a8df474cc> 0 0 (daemon)\r\n absinthed.N41 <7d9923eda625387ba90685167a49c661> 139 139 (daemon)\r\n mediaremoted <4f79c3873e8b35a3ab9c14b88131fc15> 398 398 (daemon)\r\nfilecoordination <5ca98b31b5d93b26a26c5011bc724908> 225 225 (daemon)\r\nnotification_pro <2dca4ba7b48c36e1a80c191034c70f70> 225 225 (daemon)\r\n afcd <58855a00a1dc3c99be7453efe0b5dfc7> 191 191 (daemon)\r\n distnoted <79d66cd42c243074afe7bab01d31f354> 213 213 (daemon)\r\n apsd <6f919f4ed7a3353b89304db1493a6ffd> 449 449 (daemon)\r\n networkd <305a7d187fce35d0bc48d0fbed74813e> 298 298 (daemon)\r\n aggregated <756a686c7ee2314e8891549847e28db8> 132 132 (daemon)\r\n BTServer 419 419 (daemon)\r\n configd 532 532 (daemon)\r\n CommCenter 795 795 (daemon)\r\n notifyd <81c20c784ece3554a7a4bf7944a450ff> 230 230 (daemon)\r\n ReportCrash <41677a971e73356db9dd24f1a6814432> 380 380 (daemon)\r\n\r\n**End**\r\n\r\n{code}", "updateAuthor": { "name": "anigam", "key": "anigam", "displayName": "Ashish Nigam", "active": true, "timeZone": "Asia/Kolkata" }, "created": "2013-04-10T09:32:46.000+0000", "updated": "2013-04-10T09:35:58.000+0000" }, { "id": "246844", "author": { "name": "anigam", "key": "anigam", "displayName": "Ashish Nigam", "active": true, "timeZone": "Asia/Kolkata" }, "body": "Hi,\n This particular line is interesting here, in the above device log.\n**conceptTest <33514e224eeb36d182595067e925de72> 159731 160082 [per-process-limit] (frontmost) (resume)**", "updateAuthor": { "name": "anigam", "key": "anigam", "displayName": "Ashish Nigam", "active": true, "timeZone": "Asia/Kolkata" }, "created": "2013-04-10T10:00:51.000+0000", "updated": "2013-04-10T10:00:51.000+0000" }, { "id": "251907", "author": { "name": "vduggal", "key": "vduggal", "displayName": "Vishal Duggal", "active": false, "timeZone": "America/Los_Angeles" }, "body": "The way the code is written the imageView loads the entire image into memory. The RGB data of the image occupies about 30 MB in VM (Use VM tracker on Instruments)\r\nSo once you have taken about 8 photographs the app gets killed due to lack of memory.\r\n\r\nGiven that the imageView is going to be at most 96x96 in size, it would be better to resize the image (keeping aspect ratio intact) and then use the resized image in the thumbnail view. The original image can be loaded later when needed.\r\n\r\nCode is attached below to show loading of scaled images. App no longer crashes.\r\n\r\nScaling Logic\r\n{code}\r\n var imgWid = e.media.width;\r\n var imgHt = e.media.height;\r\n \r\n var scaleW;\r\n var scaleH;\r\n if (imgWid > imgHt) {\r\n scaleW = 96;\r\n scaleH = Math.floor((imgHt * 96)/imgWid);\r\n } else {\r\n scaleH = 96;\r\n scaleW = Math.floor( (imgWid*96) /imgHt);\r\n }\r\n \r\n Ti.API.info(imgWid+' '+imgHt+' '+scaleW+' '+scaleH);\r\n newImageView.image = e.media.imageAsResized(scaleW, scaleH);\r\n{code}\r\n\r\nFull Code \r\n\r\n{code}\r\nvar damageImages = [];\r\nvar win = Ti.UI.createWindow({\r\n backgroundColor : '#fff'\r\n});\r\n \r\nvar imageView = Ti.UI.createView({\r\n layout : 'horizontal',\r\n width : Ti.UI.FILL,\r\n height : Ti.UI.SIZE\r\n });\r\n \r\nvar successCallBack = function(e) {\r\n if (e.mediaType != Ti.Media.MEDIA_TYPE_PHOTO) {\r\n takePhotoBtn.enabled = true;\r\n pickPhotoBtn.enabled = true;\r\n return false;\r\n }\r\n \r\n var filename = (new Date().getTime()) + \".jpg\";\r\n var newImageWrapperView = Ti.UI.createView({\r\n backgroundColor : '#000',\r\n left : '8dp',\r\n top : '10dp',\r\n height : '96dp',\r\n width : '96dp',\r\n isImage : true\r\n });\r\n newImageWrapperView.id = filename;\r\n var newImageView = Ti.UI.createImageView({\r\n isImage : true,\r\n zIndex : 10\r\n });\r\n newImageView.opacity = 0.5;\r\n newImageWrapperView.add(newImageView);\r\n \r\n var bgImage = Titanium.Filesystem.getFile(Titanium.Filesystem.applicationDataDirectory, filename);\r\n //newImageView.image = bgImage.getNativePath();\r\n\r\n //I need this for let use..\r\n damageImages.push({\r\n \"id\" : bgImage.getNativePath(),\r\n \"name\" : filename,\r\n \"description\" : \"\"\r\n });\r\n\r\n var imgWid = e.media.width;\r\n var imgHt = e.media.height;\r\n\r\n var scaleW;\r\n var scaleH;\r\n if (imgWid > imgHt) {\r\n scaleW = 96;\r\n scaleH = Math.floor((imgHt * 96)/imgWid);\r\n } else {\r\n scaleH = 96;\r\n scaleW = Math.floor( (imgWid*96) /imgHt);\r\n }\r\n\r\n Ti.API.info(imgWid+' '+imgHt+' '+scaleW+' '+scaleH);\r\n newImageView.image = e.media.imageAsResized(scaleW, scaleH);\r\n\r\n \r\n //resizing code also removed\r\n /*\r\n var imageModify = Ti.UI.createImageView({\r\n image : e.media\r\n });\r\n var width = imageModify.toImage().width\r\n var height = imageModify.toImage().height\r\n imageModify = null;\r\n var scaledImage = require('lib/utils').resizeKeepAspectRatioNewWidth(e.media, width, height, Config.imageMaxWidth);\r\n */\r\n bgImage.write(e.media);\r\n //scaledImage = null;\r\n bgImage = null;\r\n imageView.add(newImageWrapperView);\r\n \r\n takePhotoBtn.enabled = true;\r\n pickPhotoBtn.enabled = true;\r\n};\r\n \r\nvar errorCallBack = function(e) {\r\n takePhotoBtn.enabled = true;\r\n pickPhotoBtn.enabled = true;\r\n alert(L('erroronselectimage', 'Error while selecting image'));\r\n};\r\nvar cancelCallBack = function(e) {\r\n takePhotoBtn.enabled = true;\r\n pickPhotoBtn.enabled = true;\r\n};\r\n \r\n \r\nvar takePhotoBtn = Titanium.UI.createButton({\r\n style : Titanium.UI.iPhone.SystemButtonStyle.BORDERED,\r\n title : 'Take Photo'\r\n});\r\n \r\ntakePhotoBtn.addEventListener('click', function(e) {\r\n Ti.Media.showCamera({\r\n success : successCallBack,\r\n error : errorCallBack,\r\n cancel : cancelCallBack,\r\n allowEditing : false,\r\n saveToPhotoGallery : false,\r\n mediaTypes : [Ti.Media.MEDIA_TYPE_PHOTO]\r\n });\r\n takePhotoBtn.enabled = false;\r\n pickPhotoBtn.enabled = false;\r\n});\r\n \r\nvar pickPhotoBtn = Titanium.UI.createButton({\r\n style : Titanium.UI.iPhone.SystemButtonStyle.BORDERED,\r\n title : 'Pick Photo'\r\n});\r\n \r\npickPhotoBtn.addEventListener('click', function(e) {\r\n Ti.Media.openPhotoGallery({\r\n success : successCallBack,\r\n error : errorCallBack,\r\n cancel : cancelCallBack,\r\n allowEditing : false,\r\n mediaTypes : [Ti.Media.MEDIA_TYPE_PHOTO]\r\n });\r\n takePhotoBtn.enabled = false;\r\n pickPhotoBtn.enabled = false;\r\n});\r\n \r\nvar flexSpace = Titanium.UI.createButton({systemButton : Titanium.UI.iPhone.SystemButton.FLEXIBLE_SPACE});\r\n \r\nvar toolbar = Ti.UI.iOS.createToolbar({\r\n borderTop : true,\r\n borderBottom : false,\r\n height : 45,\r\n zIndex : '100',\r\n bottom : '0dp'\r\n });\r\ntoolbar.items = [flexSpace, takePhotoBtn, pickPhotoBtn, flexSpace];\r\n \r\n \r\nvar scrollView = Ti.UI.createScrollView({\r\n layout : 'vertical',\r\n top : 0,\r\n bottom : 45\r\n });\r\n scrollView.add(imageView);\r\n win.add(scrollView);\r\n win.add(toolbar);\r\n \r\nwin.open();\r\n{code}", "updateAuthor": { "name": "vduggal", "key": "vduggal", "displayName": "Vishal Duggal", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2013-05-14T21:12:46.000+0000", "updated": "2013-05-14T21:16:37.000+0000" }, { "id": "415176", "author": { "name": "lmorris", "key": "lmorris", "displayName": "Lee Morris", "active": false, "timeZone": "America/Los_Angeles" }, "body": "Closing ticket as \"Won't Fix\".", "updateAuthor": { "name": "lmorris", "key": "lmorris", "displayName": "Lee Morris", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2017-03-22T22:55:28.000+0000", "updated": "2017-03-22T22:55:28.000+0000" } ], "maxResults": 6, "total": 6, "startAt": 0 } } }