image displaying incorrectly

Posted on
  • I've been very thorough and I can't figure out what's going on here.
    The picture on the left shows my image (the minute hand of the clock) as it should look, the one on the right shows how it's coming out in the emulator. My second and hour hands are working fine, but for whatever reason, the minute hand image just looks crazy! All three images were created from the same photoshop file, using two colors plus transparency, and I've tried saving with every possible option and file type that supports transparency. For all three I used the "optimal 2 bit" option in the uploader, with transparency on. I can't figure out why the other two work just fine but not this one.

    g.drawImage(require("Storage").read("Min­Hand.png"),120,1333,{scale:1,rotate:0});­


    2 Attachments

    • image_2022-09-05_232222232.png
    • MinHandDay.png
  • Do you think you could post up the image (as base64) as well as the draw command so I can take a look?

    What's with 120,1333 though? 1333 should be well off the screen. Maybe that's causing an overflow or something.

    What if you do just g.drawImage(require("Storage").read("Min­Hand.png"),0,0); without rotation - does that work?

  • Thanks for the quick reply.

    Yes, it should read 133. I typed 1333 by accident when manually replacing my variable value to simplify things for this thread.

    I'll attach a picture of the results of g.drawImage(require("Storage").read("Min­Hand.png"),0,0); it is off to the left of the screen now, still looks weird.

    And here is the base64:

    atob("FrrCAP//Gq657wAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAFVQAAAAVVVQAAAVVVVAAAFVVV­QAAFVVVVAABVVVVQAAVVVVUAAFVVVVAABVVVVQAA­VVVVUAABVVVUAAAVVVVAAABVVVAAAABVUAAAAAFU­AAAAABVAAAAAAVQAAAAAFUAAAABVVVAAAAVVVQAA­AVVVVAAAFpBpQAABqQakAAAakGpAAAGpBqQAABqQ­akAAAakGpAAAGpBqQAABqQakAAAaUFpAAAGlBaQA­ABpAGkAABaQBpQAAWkAaUAAGpAGpAABqQBqQAAak­AakAAGpAGpAABqQBqQAAakAakAAGpAGpAABpQBaQ­AAaUAWkAAGlAFpAAFpQBaUABaQAGlAAakABqQAGp­AAakABqQAGpAAakABqQAGpAAakABqQAGpAAakABq­QAGlAAWkABpQAFpABaUABaUAWlAAWlAFpQAFpQBq­QAAakAakAAGpAGpAABqQBqQAAakAakAAGpAGpAAB­qQBqQAAakAaUAAFpAGlAABaQFpQAAWlBaUAAFpQW­lAABaUGpQAAWpBqQAABqQakAAAakGpAAAGpBqQAA­BqQakAAAakGpAAAGpBpQAABaQaUAAAWkWlVVVVpV­VVVVVVVVVVVVVVVaqqqqVRWqqqqlQVaqqqlUBWqq­qpUAFaqqpUABWqqqVAAFaqqVAABVqqVQAAFaqlQA­AAVqlQAAAFapUAAAAVpUAAAAFaVAAAAAVVAAAAAB­VAAAAAAVQAAAAABQAAAAAAUAAA")


    1 Attachment

    • screenshot (4).png
  • Just for kicks I tried using the base64 in my code, and that works fine. Is there a performance difference between doing that and calling up an image stored on the device?

  • Just for kicks I tried using the base64 in my code, and that works fine.

    Ahh, that's interesting, thanks! I just tried here and I can reproduce, and I think the issue is if you're using a paletted image and loading it from flash, it maybe calculates the image start offset wrong. I'll see if I can get a fix in for that.

    Is there a performance difference between doing that and calling up an image stored on the device?

    Yes - it's a hard one to quantify - but if you have the image in RAM all the time (eg as a global variable, rather than with the base64 inside the function that renders it) then it'll be much faster.

    Since you're using 'optimal 2 bit' the image should be pretty small, so I'd say maybe keep it (and the other hands too) in RAM, and it'll make the clock face update much faster.

    ... but I'll see what I can do about the image loading issue anyway

  • Quick update - it's actually a bug in the Web IDE's image uploader!

    It actually got fixed a while ago (https://github.com/espruino/EspruinoWebT­ools/pull/9) but unfortunately hasn't made it into the IDE yet. I'll try and get a release done soon...

    If you do:

    j=atob("FrrCAP//Gq657wAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA­AAAAAAAAAAAAAAAAAFVQAAAAVVVQAAAVVVVAAAFV­VVQAAFVVVVAABVVVVQAAVVVVUAAFVVVVAABVVVVQ­AAVVVVUAABVVVUAAAVVVVAAABVVVAAAABVUAAAAA­FUAAAAABVAAAAAAVQAAAAAFUAAAABVVVAAAAVVVQ­AAAVVVVAAAFpBpQAABqQakAAAakGpAAAGpBqQAAB­qQakAAAakGpAAAGpBqQAABqQakAAAaUFpAAAGlBa­QAABpAGkAABaQBpQAAWkAaUAAGpAGpAABqQBqQAA­akAakAAGpAGpAABqQBqQAAakAakAAGpAGpAABpQB­aQAAaUAWkAAGlAFpAAFpQBaUABaQAGlAAakABqQA­GpAAakABqQAGpAAakABqQAGpAAakABqQAGpAAakA­BqQAGlAAWkABpQAFpABaUABaUAWlAAWlAFpQAFpQ­BqQAAakAakAAGpAGpAABqQBqQAAakAakAAGpAGpA­ABqQBqQAAakAaUAAFpAGlAABaQFpQAAWlBaUAAFp­QWlAABaUGpQAAWpBqQAABqQakAAAakGpAAAGpBqQ­AABqQakAAAakGpAAAGpBpQAABaQaUAAAWkWlVVVV­pVVVVVVVVVVVVVVVVaqqqqVRWqqqqlQVaqqqlUBW­qqqpUAFaqqpUABWqqqVAAFaqqVAABVqqVQAAFaql­QAAAVqlQAAAFapUAAAAVpUAAAAFaVAAAAAVVAAAA­ABVAAAAAAVQAAAAABQAAAAAAUAAA");
    require("Storage").write("MinHand.png",j­);
    

    it'll write the correct image and it should then work for you

  • Oh, good to know about that last manual conversion/upload thing. And I actually haven't had a chance to test any of this on the physical js1 yet since I can't seem to find the charging cable.

    I did move all the hands to base64, but yeah the larger face images in base64 crashed the emulation.

    So for the larger images, if I declare them as global variables outside of the function, would I be better off declaring that variable as
    var image = require("Storage").read("image.img");
    or var image = atob("FrrCAP//Gq657wAA...AAAAA==")
    or does it matter at that point since either way it's in RAM?

    Or is it in RAM? We had previously discussed elsewhere that

    "if you store the background image as a file (uncompressed), drawImage
    can draw that file directly without ever loading it into RAM"

    Does that hold true for the global variables?

  • or does it matter at that point since either way it's in RAM? Or is it in RAM?

    :) As you say, var image = require("Storage").read("image.img"); just gives you a 'pointer' to the data in Flash memory, so it's not actually in RAM.

    However, while it is slower than RAM, it's still a lot faster than using require("Storage").read directly, since it's not having to scan the filesystem to find the file each time.

  • Am I right in thinking there is a difference between
    var image = require("Storage").read("image.img"); // pointer to image.img in flash
    and
    var image = atob("FrrCAP//Gq657wAA...AAAAA=="); // decoded image lives in RAM
    though?

    Offtopic: now I'm thinking about storing multiple images (uncompressed) into a single file, using either Graphics.drawImage(…, {frame:<frame>}) or Storage.read(…, <offset>,<length>), wondering if it might help with RAM usage of layouts that use a bunch of icons.

  • I have got good results using offsets and writing all image-data into one file in my imageclock app. The offsets/metadata are created beforehand in the customizer on watchface upload to allow different resolution images in the big file and stored in a specific json alongside the big resource file. On use they are converted to image objects in app.js#L84 and drawn in app.js#L287

  • Am I right in thinking there is a difference

    Yes :)

    I'm thinking about storing multiple images (uncompressed) into a single file

    If you're just using .read the difference in RAM usage will be minimal, and the extra code required will likely use more than you save.

    In @halemmerich's case he has loads of images - but for just 3 images I don't think it's really worth it

  • Well, I was also thinking about how it bugs me that images are now included as basically read-only binary strings, and how it would be nice to have some way to just add them as image to the repository, without having to update both the image and the string when editing.
    But I guess adding a "compile images" step to editing apps isn't really (newbie) user-friendly either :-(

  • I was also thinking about how it bugs me that images are now included as basically read-only binary strings

    The IDE can convert images as it uploads, so in theory the app loader could maybe allow images to be converted on the fly. The problem is to get the best performance you really need to choose what image type you need - there's no point storing black and white images in 16bpp.

    IMO hiding all that away makes it far more likely we end up with slower, more memory-inefficient apps

  • Yeah, I don't really see a good solution for it. (but I'll try to at least add the source images I use to the repo)

  • After some testing with the clock hands, I find that
    var image = require("Storage").read("image.img");
    does draw a little quicker than using the atob method

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

image displaying incorrectly

Posted by Avatar for NoMusicTuesdays @NoMusicTuesdays

Actions