SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 30
  1. #1
    SitePoint Addict
    Join Date
    Aug 2005
    Posts
    330
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Getting Image Size in Javascript (IE/Moz)

    I have a photo gallery site where the visitor clicks on a thumbnail and it calls a Javascript function which opens a child window to display the fullsize image in.

    To determine the size of the child window to create it needs to get the size of the image. This works in IE, but returns h=0, w=0 in Mozilla :

    function open_a_window(caption, color, image)
    {

    img = new Image();
    img.src = image;
    w = img.width;
    h = img.height;


    . . . rest of function here

    I think it's a preloading problem because if I force the child window to open anyway at a fixed size and do a "view image" in it, the next time I try to open that image it gets the size just fine.

    Thanks in advance!

  2. #2
    SitePoint Wizard bronze trophy C. Ankerstjerne's Avatar
    Join Date
    Jan 2004
    Location
    The Kingdom of Denmark
    Posts
    2,702
    Mentioned
    7 Post(s)
    Tagged
    0 Thread(s)
    In stead of w and h, use something else, e.g. imgWidth and imgHeight. That'll fix the problem.
    Christian Ankerstjerne
    <p<strong<abbr/HTML/ 4 teh win</>
    <>In Soviet Russia, website codes you!

  3. #3
    SitePoint Addict
    Join Date
    Aug 2005
    Posts
    330
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by C. Ankerstjerne
    In stead of w and h, use something else, e.g. imgWidth and imgHeight. That'll fix the problem.
    Interesting. With that change it SOMETIMES gets the size on the first try in Mozilla, but still mostly not.

    Why should the variable name matter at all?

  4. #4
    SitePoint Wizard bronze trophy C. Ankerstjerne's Avatar
    Join Date
    Jan 2004
    Location
    The Kingdom of Denmark
    Posts
    2,702
    Mentioned
    7 Post(s)
    Tagged
    0 Thread(s)
    If you use a variable name which is also a function name, you'll get a conflict.
    Christian Ankerstjerne
    <p<strong<abbr/HTML/ 4 teh win</>
    <>In Soviet Russia, website codes you!

  5. #5
    SitePoint Addict
    Join Date
    Aug 2005
    Posts
    330
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by C. Ankerstjerne
    If you use a variable name which is also a function name, you'll get a conflict.
    I doubt the conflict would take the form of it only working the second time the image is loaded, but anyway this works the same . . .

    function open_a_window(caption, color, theImage)
    {
    img = new Image();
    img.src = theImage;
    theImageWidth = img.width;
    theImageHeight = img.height;

    alert("w="+theImageWidth +" h="+theImageHeight);

    . . . ETC . . .


    It gets the dimensions perfectly fine in IE but only gets them the SECOND time the image is accessed in Mozilla, which suggests a preloading problem. The first two lines in the function are the way most people attempt to do preloading but I'm told that it's not very reliable. There's an elaborate Javascript callback function someone wrote
    here
    . . . but it's overkill for my application because I have a grid of 32 thumbnails and I don't expect the user to try to look at all 32 fullsize images, and if we tried to preload all 32 fullsize images it would take a long time. I just want to preload the ONE image "theImage" before trying to get its dimensions.

  6. #6
    &#083;itePoint Aficionado JVLB's Avatar
    Join Date
    Jan 2002
    Location
    N 44 56.537' W 123 3.683'
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I don't believe preloading necessarily gives the image object any dimensions. If you display the image, even if it is hidden, I suspect you will more reliably be able to ascertain its aspects.

  7. #7
    SitePoint Addict
    Join Date
    Aug 2005
    Posts
    330
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by JVLB
    I don't believe preloading necessarily gives the image object any dimensions. If you display the image, even if it is hidden, I suspect you will more reliably be able to ascertain its aspects.
    What do you mean display it hidden? Where? If the user clicks on 8 (of the 32 thumbnails) do I end up with 8 hidden fullsize images?

    Also, are you saying that the only way to get the dimensions of an image in Javascript is to first display it?

  8. #8
    &#083;itePoint Aficionado JVLB's Avatar
    Join Date
    Jan 2002
    Location
    N 44 56.537' W 123 3.683'
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yes, you end up with 8 hidden images, which is little different than preloading. In each case one copy of the image goes into cache and is retrieved when that image is called. You can place the images in a hidden div, or whatever.

    Yes, I'm saying that the browser has not assigned height and width properties to the image object until it is displayed.

  9. #9
    SitePoint Addict
    Join Date
    Aug 2005
    Posts
    330
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by JVLB
    Yes, you end up with 8 hidden images, which is little different than preloading. In each case one copy of the image goes into cache and is retrieved when that image is called. You can place the images in a hidden div, or whatever.

    Yes, I'm saying that the browser has not assigned height and width properties to the image object until it is displayed.
    1. Are there any performance penalties to this approach? My images are quite large - typically 600x700 pixels, maybe 150K each. That means a user browsing photos on my site might end up with megabytes of hidden images without knowing it!

    2. IE doesn't seem to have this problem - is it unique to Mozilla?

    3. This is probably a newbie question (but I'm a javascript newbie or I wouldn't be asking this) , but just to be clear: when you talk about writing it to a DIV, do you mean to getElementByID of some DIV whose visibility is set to "hidden" and set its inner HTML to an <img src = .. the image?
    Last edited by plnelson; Jun 25, 2006 at 15:33.

  10. #10
    &#083;itePoint Aficionado JVLB's Avatar
    Join Date
    Jan 2002
    Location
    N 44 56.537' W 123 3.683'
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    However you download it, the image is the size it is and will use the bandwidth it will use. Once downloaded, the browser will cache it for as long as cache settings provide. It doesn't matter if JavaScript downloads it or the HTML page, it doesn't matter if it is visible, hidden, or pre-fetched, you'll take the performance hit. At 150K for 600x700, it sounds like your images could use some optimization. At Web-appropriate quality settings, a JPEG should come in well under a third that size. Have you tried the GIMP (Gnu Image Manipulation Program)? It does a remarkable job of preserving image quality while reducing image size.

    I did a quick test on Firefox, Opera, IE and Konqueror. Opera and IE read the height of a JavaScript cached image, neither FF nor K do. FF, O, & IE read the height of a hidden image, K (and, likely, Safari) does not. No relief was provided to K's conundrum by using: defaultView.getComputedStyle.getPropertyValue.ad_infinitum.et_cetera_&_so_forth

    Yeah, innerHTML should do, though purists go for the nodes.

  11. #11
    SitePoint Addict
    Join Date
    Aug 2005
    Posts
    330
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by JVLB
    At 150K for 600x700, it sounds like your images could use some optimization. At Web-appropriate quality settings, a JPEG should come in well under a third that size. Have you tried the GIMP (Gnu Image Manipulation Program)? It does a remarkable job of preserving image quality while reducing image size.
    I'm a photographer and I know how to recognize even subtle JPEG compression artifacts, and more importantly, so do other photographers and art directors who might visit my site. I could compress my images to maybe half the size they are now and probably 80% of the people look at them would never see any difference, but the people who matter would notice it in a second.

    ( BTW, GIMP is a nice suite for people on a budget but it's not in the same league with the full pro version of Adobe Photoshop. Numerous discussions on various professional photography groups I'm on agree that THE most wanted application on Linux by serious photographers is a full port of the pro version of Photoshop. I know many photog's who keep a mac or PC around for no other reason than to run Photoshop. )


    I did a quick test on Firefox, Opera, IE and Konqueror. Opera and IE read the height of a JavaScript cached image, neither FF nor K do. FF, O, & IE read the height of a hidden image, K (and, likely, Safari) does not. No relief was provided to K's conundrum by using: defaultView.getComputedStyle.getPropertyValue.ad_infinitum.et_cetera_&_so_forth
    So if Konqueror and Safari don't work on the hidden images, and FF doesn't work the way I was trying to do it, does thuis mean there is NO reliable way to do it?

    I know the size of my images, so I can always just add height and width parameters to the function that creates the window. OR I can embed the image in the name, e.g., "ImageABC600x700.jpg" and write a string parser in Javascript to extract it. Kludgy as those sound, they don't sound nearly as kludgy as what I might have to do to get the size of the image reliably the way we've been discussing.

    I appreciate all the time and thought you've put into this, but just out of curiosity, does anyone else on this forum have any opinions of this topic?

  12. #12
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The alternative to finding the size of the image and then opening a window that size, is to open a window at a small size, then resize it once the image is loaded. You can attach an onload event to an image tag, which would resize the window as needed.

    Douglas
    Hello World

  13. #13
    &#083;itePoint Aficionado JVLB's Avatar
    Join Date
    Jan 2002
    Location
    N 44 56.537' W 123 3.683'
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Actually, offsetHeight and offsetWidth should offer some relief. Applied to a hidden image, they appear to be consistent across the board.

    I've paid for highly-touted Photoshop plug-ins that don't do half the quality of compression job GIMP does. Whether its Adobe, Corel, Ulead, or the GIMP, each has its strengths, each has its weaknesses; each will do easily something the others will strain to accomplish. Dismiss a product at your own peril.

    On the other hand, if you're going to print . . .
    Last edited by JVLB; Jun 25, 2006 at 18:12.

  14. #14
    SitePoint Addict
    Join Date
    Aug 2005
    Posts
    330
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DougBTX
    The alternative to finding the size of the image and then opening a window that size, is to open a window at a small size, then resize it once the image is loaded. You can attach an onload event to an image tag, which would resize the window as needed.

    Douglas
    I was wondering about that! But I read somewhere that different browsers require different methods to do that, specifically that resizeTo() is interpreted differently in different browsers.

    There's an example of doing this from back in 2003 righthere on SitePoint, that has a special test for Netscape, but makes no allowance for other browsers (this was pre-Mozilla). I'm trying to avoid having all kinds of special case code for different browsers because that's a moving target.

    Can you suggest a good universal way to resize a child window that works with all major browsers?

    Thanks!

  15. #15
    SitePoint Addict
    Join Date
    Aug 2005
    Posts
    330
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DougBTX
    The alternative to finding the size of the image and then opening a window that size, is to open a window at a small size, then resize it once the image is loaded. You can attach an onload event to an image tag, which would resize the window as needed.
    Douglas
    I tried that but the onload event seems to get called prematurely. Or I'm doing something wrong . . .

    I load the image and set an onload event . . .

    ChildWin.document.images[ 'thisone' ].src = theImage;
    ChildWin.document.images[ 'thisone' ].onload = Loaded();

    and then in the Loaded() function I query height and width . . .
    theImageWidth = ChildWin.document.images[ 'thisone' ].width;
    theImageHeight = ChildWin.document.images[ 'thisone' ].height;

    and then have an alert() to display the results. Not only is the Height and Width 0, but you can see in the window that the image isn't loaded yet! It appears after I dismiss the alert box. With no alert box the result is the same - 0 height and width. But the NEXT time I try to load the image it comes up perfectly.

  16. #16
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by plnelson
    ChildWin.document.images[ 'thisone' ].onload = Loaded();
    The () after Loaded means that you are actually calling the function there, what you really want to do is assign the function itself, rather than the result of calling the function.

    Code:
    ChildWin.document.images[ 'thisone' ].onload = Loaded;
    Douglas
    Hello World

  17. #17
    SitePoint Addict
    Join Date
    Aug 2005
    Posts
    330
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DougBTX
    The () after Loaded means that you are actually calling the function there, what you really want to do is assign the function itself, rather than the result of calling the function.

    Code:
    ChildWin.document.images[ 'thisone' ].onload = Loaded;
    Douglas
    Oh, thank you. It shows what a complete javascript newbie I am.

  18. #18
    &#083;itePoint Aficionado JVLB's Avatar
    Join Date
    Jan 2002
    Location
    N 44 56.537' W 123 3.683'
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You will still need to use offsetHeight and offsetWidth if you want cross-browser compatibility.

  19. #19
    SitePoint Addict
    Join Date
    Aug 2005
    Posts
    330
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by JVLB
    You will still need to use offsetHeight and offsetWidth if you want cross-browser compatibility.
    Sorry, I'm too much of a newbie to know what this means.

  20. #20
    SitePoint Addict
    Join Date
    Aug 2005
    Posts
    330
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by plnelson
    Oh, thank you. It shows what a complete javascript newbie I am.
    So now it works perfectly in Mozilla. I have it set up to write into a hidden DIV in the HiddenLoad() function. In Mozilla that part works fine. If I turn the DIV's visibility on I can see it display. Then the loaded handler gets called and I set up my child window and all is good.

    But it does NOT work perfectly in IE!

    When the user clicks a thumbnail this gets called

    function open_a_window(caption, color, theImage)
    {
    gImage = theImage;
    gCaption = caption;
    gColor = color;
    alert ("open_a_window, Image ="+gImage);

    img = new Image();
    img.src = gImage;
    img.onload = Loaded; //specify an "onloaded" handler

    HiddenLoad();
    }


    I set some global variables for the "loaded" handler" to use - the image caption, background color, and the image filename itself (e.g., "foo.jpg"); I specify my onloaded handler, and I call my DIV loading function.

    In IE the onloaded handler SOMETIMES gets called and sometimes not! could understand if it never worked, but SOMETIMES?? I have an alert box there to check it.

    Also, in IE when I do create the child window it never makes it bigger than the parent. I set the size in the window.open call.

  21. #21
    &#083;itePoint Aficionado JVLB's Avatar
    Join Date
    Jan 2002
    Location
    N 44 56.537' W 123 3.683'
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The window.onload event is widely considered more reliable than the image.onload event. You will probably get better results if you can use it.

    offsetHeight and offsetWidth are properties of a rendered object, just like height and width. While height and width are CSS properties, the offset dimensions are supposed to be based in the actual display of the element and its content. The offset dimensions, as well as others like clientHeight, etc. are a convenience supported generally by browsers but not part of a standard. The syntax is the same as with width or height: document.getElementById('someElement').offsetWidth

  22. #22
    SitePoint Addict
    Join Date
    Aug 2005
    Posts
    330
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by JVLB
    The window.onload event is widely considered more reliable than the image.onload event. You will probably get better results if you can use it.
    Is there a good way to open the child cindow without displaying it?

    The reason why I did it the way I did was because when I opened it tiny and then resized it once I had the correct image size, the result was that I would see a tiny window flash on for an instant before seeing my full size one. So I wanted to compute the image size BEFORE opening the window.

    I had no idea when I started this thread that getting the pixel dimensions of a JPEG was this hard and tricky!

  23. #23
    &#083;itePoint Aficionado JVLB's Avatar
    Join Date
    Jan 2002
    Location
    N 44 56.537' W 123 3.683'
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If you want to avoid the jumpy window, you'll have to load the image into a hidden div or such to get the dimensions before you open the window at all. You can probably get the image onload to work better if you use it to trigger a short timeout before the size is read and the window launched. I suspect that the image onload is firing prematurely and that a few-millisecond timeout will overcome this.

  24. #24
    SitePoint Addict
    Join Date
    Aug 2005
    Posts
    330
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by JVLB
    You can probably get the image onload to work better if you use it to trigger a short timeout before the size is read and the window launched. I suspect that the image onload is firing prematurely and that a few-millisecond timeout will overcome this.
    God, this is getting hackier and hackier! Let's just forget it, OK? My dayjob is as a C++/C# sw engineer and I've never seen anything like this. We do NOT make programs work by embedding time-delays in them.

    I've made a new version where I just pass in the dimensions (since I know what they are, since they're my files) in the same function call where I pass in the filename, background color, and caption. So far it works perfectly.

    I appreciate everybody's help on this, but I never would have imagined that getting the dimensions of something as basic as a JPEG image - one of the staple ingrediants of web pages - would have been this hard and fraught with hacks and workarounds!

    I'm a newbie at Javascript - is EVERYTHING in Javascript like this?

  25. #25
    &#083;itePoint Aficionado JVLB's Avatar
    Join Date
    Jan 2002
    Location
    N 44 56.537' W 123 3.683'
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It is in the nature of synchronizing independent processes dependant on asynchronous communication that timing mismatches will occur. Sooner or later, if you are integrating such processes a timeout becomes a quick fix. Ideal? Perhaps not, but it has been a reality in the computing world for decades.

    It isn't fair to blame JavaScript for the limitations of the world it inhabits. That said, yes everything in the world of the browser is like this. It isn't just JavaScript, it's CSS and "legacy" behaviors, as well. When you code for the web you code for a myriad of browser implementations and versions running on manifold operating system flavors and versions. Meanwhile, it's your code that has to putty in the cracks of this edifice. A timeout of a few milliseconds is not the greatest price that has ever been paid to effect such cosmetic enhancement.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •