{ "id": "62291", "key": "TIMOB-1659", "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": "11240", "name": "Release 1.6.0 M07", "archived": true, "released": true, "releaseDate": "2011-01-31" } ], "resolution": { "id": "1", "description": "A fix for this issue is checked into the tree and tested.", "name": "Fixed" }, "resolutiondate": "2011-04-17T01:56:47.000+0000", "created": "2011-04-15T02:58:38.000+0000", "priority": { "name": "Low", "id": "4" }, "labels": [ "android", "defect", "release-1.6.0", "toimage", "ui" ], "versions": [], "issuelinks": [], "assignee": { "name": "nwright", "key": "nwright", "displayName": "Nolan Wright", "active": false, "timeZone": "America/Los_Angeles" }, "updated": "2011-04-17T01:56:47.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": "10202", "name": "Android", "description": "Android Platform" } ], "description": "{html}

Calling toImage seems to blow up. I've tried it on buttons and\nviews now and I get the same results. It seems to work fine on\niPhone. (iOS 4.0.2 and Titanium Mobile SDK 1.4.1 from GitHub.)

\n
\nvar appDirName = Titanium.Filesystem.applicationDataDirectory;\nvar imageFile = Titanium.Filesystem.getFile(appDirName, 'image.jpg');\n\nif (!imageFile.exists()) {\n    Titanium.API.debug(\"File \" + imageFile.name + \" does not exist yet.\");\n}\n\nvar button = Titanium.UI.createButton({\n    title:'Gargargar!',\n    height:40,\n    width:200,\n    top:10\n});\n\nimageFile.write(button.toImage()); // blows up on Android\n\nif (imageFile.exists()) {\n    // Note: Titanium.Filesystem.File.size attribute not mentioned in the API docs\n    Titanium.API.debug(imageFile.name + \" exists, size: \" + imageFile.size);\n}\n
\n

Android stack trace:

\n
\nD/TiAPI   (  569): (kroll$1) [880,926] File image.jpg does not exist yet.\nI/ActivityManager(   67): Displayed activity net.status.tstest/.TstestActivity: 4723 ms (total 4723 ms)\nW/TiAnalyticsSvc(  569): (Thread-10) [517,1443] Analytics Service Started\nD/AndroidRuntime(  569): Shutting down VM\nW/dalvikvm(  569): threadid=1: thread exiting with uncaught exception (group=0x4001d800)\nE/TiUncaughtHandler(  569): (main) [123,1566] Sending event: exception on thread: main msg:java.lang.IllegalArgumentException: width and height must be > 0\nE/TiUncaughtHandler(  569): java.lang.IllegalArgumentException: width and height must be > 0\nE/TiUncaughtHandler(  569):     at android.graphics.Bitmap.nativeCreate(Native Method)\nE/TiUncaughtHandler(  569):     at android.graphics.Bitmap.createBitmap(Bitmap.java:468)\nE/TiUncaughtHandler(  569):     at org.appcelerator.titanium.util.TiUIHelper.viewToImage(TiUIHelper.java:417)\nE/TiUncaughtHandler(  569):     at org.appcelerator.titanium.view.TiUIView.toImage(TiUIView.java:637)\nE/TiUncaughtHandler(  569):     at org.appcelerator.titanium.proxy.TiViewProxy.handleToImage(TiViewProxy.java:435)\nE/TiUncaughtHandler(  569):     at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:139)\nE/TiUncaughtHandler(  569):     at android.os.Handler.dispatchMessage(Handler.java:95)\nE/TiUncaughtHandler(  569):     at android.os.Looper.loop(Looper.java:123)\nE/TiUncaughtHandler(  569):     at android.app.ActivityThread.main(ActivityThread.java:4627)\nE/TiUncaughtHandler(  569):     at java.lang.reflect.Method.invokeNative(Native Method)\nE/TiUncaughtHandler(  569):     at java.lang.reflect.Method.invoke(Method.java:521)\nE/TiUncaughtHandler(  569):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)\nE/TiUncaughtHandler(  569):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)\nE/TiUncaughtHandler(  569):     at dalvik.system.NativeStart.main(Native Method)\nD/dalvikvm(  569): GC_FOR_MALLOC freed 6846 objects / 392464 bytes in 117ms\nD/TiApplication(  569): (main) [195,1761] Analytics Event: type=ti.crash\nD/TiApplication(  569):  event=ti.crash\nD/TiApplication(  569):  timestamp=2010-08-26T20:45:41.224-0800\nD/TiApplication(  569):  mid=9774d56d682e549c\nD/TiApplication(  569):  sid=715a773d-1c37-434d-b55d-09008336d89a\nD/TiApplication(  569):  aguid=2ac80eec-55c8-4d03-9478-1b6255458ea5\nD/TiApplication(  569):  isJSON=true\nD/TiApplication(  569):  payload={\"value\":\"thread_namemain\\nthread_id1\\nerror_msgjava.lang.IllegalArgumentException: width and height must be > 0\\n<<<<<<<<<<<<<<< STACK TRACE >>>>>>>>>>>>>>>\\nandroid.graphics.Bitmap.nativeCreate(Native Method)\\nandroid.graphics.Bitmap.createBitmap(Bitmap.java:468)\\norg.appcelerator.titanium.util.TiUIHelper.viewToImage(TiUIHelper.java:417)\\norg.appcelerator.titanium.view.TiUIView.toImage(TiUIView.java:637)\\norg.appcelerator.titanium.proxy.TiViewProxy.handleToImage(TiViewProxy.java:435)\\norg.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:139)\\nandroid.os.Handler.dispatchMessage(Handler.java:95)\\nandroid.os.Looper.loop(Looper.java:123)\\nandroid.app.ActivityThread.main(ActivityThread.java:4627)\\njava.lang.reflect.Method.invokeNative(Native Method)\\njava.lang.reflect.Method.invoke(Method.java:521)\\ncom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)\\ncom.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)\\ndalvik.system.NativeStart.main(Native Method)\\n\"}\nE/AndroidRuntime(  569): FATAL EXCEPTION: main\nE/AndroidRuntime(  569): java.lang.IllegalArgumentException: width and height must be > 0\nE/AndroidRuntime(  569):    at android.graphics.Bitmap.nativeCreate(Native Method)\nE/AndroidRuntime(  569):    at android.graphics.Bitmap.createBitmap(Bitmap.java:468)\nE/AndroidRuntime(  569):    at org.appcelerator.titanium.util.TiUIHelper.viewToImage(TiUIHelper.java:417)\nE/AndroidRuntime(  569):    at org.appcelerator.titanium.view.TiUIView.toImage(TiUIView.java:637)\nE/AndroidRuntime(  569):    at org.appcelerator.titanium.proxy.TiViewProxy.handleToImage(TiViewProxy.java:435)\nE/AndroidRuntime(  569):    at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:139)\nE/AndroidRuntime(  569):    at android.os.Handler.dispatchMessage(Handler.java:95)\nE/AndroidRuntime(  569):    at android.os.Looper.loop(Looper.java:123)\nE/AndroidRuntime(  569):    at android.app.ActivityThread.main(ActivityThread.java:4627)\nE/AndroidRuntime(  569):    at java.lang.reflect.Method.invokeNative(Native Method)\nE/AndroidRuntime(  569):    at java.lang.reflect.Method.invoke(Method.java:521)\nE/AndroidRuntime(  569):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)\nE/AndroidRuntime(  569):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)\nE/AndroidRuntime(  569):    at dalvik.system.NativeStart.main(Native Method)\n
\n

Here's what happens on iPhone (also see attached image.jpg).

\n
\n[DEBUG] File image.jpg does not exist yet.\n[DEBUG] image.jpg exists, size: 6311\n
{html}", "attachment": [ { "id": "18032", "filename": "app.js", "author": { "name": "opiecyrus", "key": "opiecyrus", "displayName": "Opie Cyrus", "active": true, "timeZone": "America/Chicago" }, "created": "2011-04-15T02:58:39.000+0000", "size": 1091, "mimeType": "application/x-javascript" }, { "id": "18031", "filename": "image.jpg", "author": { "name": "zcopley", "key": "zcopley", "displayName": "zcopley", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-04-15T02:58:39.000+0000", "size": 6311, "mimeType": "image/jpeg" } ], "flagged": false, "summary": "(Android) toImage functions blowing up with UI widgets", "creator": { "name": "zcopley", "key": "zcopley", "displayName": "zcopley", "active": true, "timeZone": "America/Los_Angeles" }, "subtasks": [], "reporter": { "name": "zcopley", "key": "zcopley", "displayName": "zcopley", "active": true, "timeZone": "America/Los_Angeles" }, "environment": null, "comment": { "comments": [ { "id": "126298", "author": { "name": "zcopley", "key": "zcopley", "displayName": "zcopley", "active": true, "timeZone": "America/Los_Angeles" }, "body": "{html}

Related issue? \nhttps://appcelerator.lighthouseapp.com/projects/32238/tickets/817-a...

{html}", "updateAuthor": { "name": "zcopley", "key": "zcopley", "displayName": "zcopley", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-04-15T02:58:39.000+0000", "updated": "2011-04-15T02:58:39.000+0000" }, { "id": "126299", "author": { "name": "dthorp", "key": "dthorp", "displayName": "Don Thorp", "active": true, "timeZone": "America/Los_Angeles" }, "body": "{html}

Looked into this a bit. toImage doesn't force the native control\nto be laid out in the case above since it hasn't been added to a\nwindow so it's layout methods aren't called. This will be a tricky\nissue to deal with in that regard.

{html}", "updateAuthor": { "name": "dthorp", "key": "dthorp", "displayName": "Don Thorp", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-04-15T02:58:40.000+0000", "updated": "2011-04-15T02:58:40.000+0000" }, { "id": "126300", "author": { "name": "opiecyrus", "key": "opiecyrus", "displayName": "Opie Cyrus", "active": true, "timeZone": "America/Chicago" }, "body": "{html}

(from [5d1f301879f66a1342901923c47b0cdd5ed0acf2])\n[#1659 state:fixed-in-qa] allow toImage to be\ncalled on elements not yet layed out

\n

Changed toImage call to force a measure on a UI element in order\nto get the needed width and height to be drawn even if it hasnt\nbeen laid out yet. If even after a measure the width and height are\ninvalid, a default value is set so the bitmap can be created and a\nerror is logged
\n\nhttps://github.com/appcelerator/titanium_mobile/commit/5d1f301879f6...

{html}", "updateAuthor": { "name": "opiecyrus", "key": "opiecyrus", "displayName": "Opie Cyrus", "active": true, "timeZone": "America/Chicago" }, "created": "2011-04-15T02:58:41.000+0000", "updated": "2011-04-15T02:58:41.000+0000" }, { "id": "126301", "author": { "name": "opiecyrus", "key": "opiecyrus", "displayName": "Opie Cyrus", "active": true, "timeZone": "America/Chicago" }, "body": "{html}

Please verify with the original test included with the first\npost.

{html}", "updateAuthor": { "name": "opiecyrus", "key": "opiecyrus", "displayName": "Opie Cyrus", "active": true, "timeZone": "America/Chicago" }, "created": "2011-04-15T02:58:41.000+0000", "updated": "2011-04-15T02:58:41.000+0000" }, { "id": "126302", "author": { "name": "dthorp", "key": "dthorp", "displayName": "Don Thorp", "active": true, "timeZone": "America/Los_Angeles" }, "body": "{html}

This no longer crashes, but it's failing to write the file. I\nupdated the test app to report both cases.

\n
\n\nvar appDirName = Titanium.Filesystem.applicationDataDirectory;\nvar imageFile = Titanium.Filesystem.getFile(appDirName, 'image.jpg');\n\nif (!imageFile.exists()) {\n    Titanium.API.debug(\"File \" + imageFile.name + \" does not exist yet.\");\n} else {\n    Titanium.API.debug(\"File \" + imageFile.name + \" EXISTS yet.\");  \n}\n\nvar button = Titanium.UI.createButton({\n    title:'Gargargar!',\n    height:40,\n    width:200,\n    top:10\n});\n\nimageFile.write(button.toImage()); // blows up on Android\n\nif (imageFile.exists()) {\n    // Note: Titanium.Filesystem.File.size attribute not mentioned in the API docs\n    Titanium.API.debug(imageFile.name + \" exists, size: \" + imageFile.size);\n} else {\n    Titanium.API.debug(\"File \" + imageFile.name + \" does not exist yet.\");\n}\n
{html}", "updateAuthor": { "name": "dthorp", "key": "dthorp", "displayName": "Don Thorp", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-04-15T02:58:41.000+0000", "updated": "2011-04-15T02:58:41.000+0000" }, { "id": "126303", "author": { "name": "opiecyrus", "key": "opiecyrus", "displayName": "Opie Cyrus", "active": true, "timeZone": "America/Chicago" }, "body": "{html}

(from [78001f43c0be0a0019079ca838a1475041a704da])\n[#1659 state:fixed-in-qa] fixed error causing\ntoImage file to actually be written

\n

Modified TiUIHelper to force layout on objects that had not yet\nbeen added to a view so toImage would corectly generate the image.\nFixed test to pass corect parameter to the write() call. Added\nexception to the write() call when the object passed in is\nunrecognized.
\n\nhttps://github.com/appcelerator/titanium_mobile/commit/78001f43c0be...

{html}", "updateAuthor": { "name": "opiecyrus", "key": "opiecyrus", "displayName": "Opie Cyrus", "active": true, "timeZone": "America/Chicago" }, "created": "2011-04-15T02:58:41.000+0000", "updated": "2011-04-15T02:58:41.000+0000" }, { "id": "126304", "author": { "name": "opiecyrus", "key": "opiecyrus", "displayName": "Opie Cyrus", "active": true, "timeZone": "America/Chicago" }, "body": "{html}

Please verify with the modified test client that now passes the\ncorrect value to the filesystem write call().

{html}", "updateAuthor": { "name": "opiecyrus", "key": "opiecyrus", "displayName": "Opie Cyrus", "active": true, "timeZone": "America/Chicago" }, "created": "2011-04-15T02:58:42.000+0000", "updated": "2011-04-15T02:58:42.000+0000" }, { "id": "126305", "author": { "name": "mculpepper", "key": "mculpepper", "displayName": "Marshall Culpepper", "active": true, "timeZone": "America/Los_Angeles" }, "body": "{html}

verified w/ test case on Nexus s 2.3.2

{html}", "updateAuthor": { "name": "mculpepper", "key": "mculpepper", "displayName": "Marshall Culpepper", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-04-15T02:58:42.000+0000", "updated": "2011-04-15T02:58:42.000+0000" } ], "maxResults": 8, "total": 8, "startAt": 0 } } }