If you have your own tutorials or open source and would like to share your Director knowledge please send them to info@shocksites.com. We will review them, post it and give full credit to the developer.
Current Open Source and Tutorials

MENU

  1. Intro
  2. DUPLICATE
  3. SETTING THE IMAGE OF A MEMBER
  4. PRE-STORING RECT VALUES
  5. DRAWING TO THE STAGE


Optimizing Imaging Lingo:
Provided by Zevan Renteren


A few rules that will speed up your imaging lingo projects.


This tutorial assumes that you have knowledge of basic imaging lingo.


We're going to be doing speed tests throughout this tutorial. For this reason I am using my slower computer with an 866 mhz processor. If your computer is extremly fast you may not see the speed difference. If this is the case, just throw in a repeat loop or alter the number of times we are repeating a specific action and you'll see the result.


DUPLICATE

One of the more important things to do when using imaging lingo is to use duplicate() with cast member image objects. If you want to make changes to a cast members image object, make a duplicate and store it in a variable, make your alterations and then copy it back. Working directly with a members image is slower than working with an image object in ram.

Here is a simple test that will display the difference in milleseconds. Create a bitmap member and name it "myImageMember". Run this lingo on a framescript:


property myImage
property _start,_end

on beginSprite me

  
   -- with duplicate
   _start= the milliseconds

  myImage = member("myImageMember").image.duplicate()

  repeat with i = 0 to 1200
     myImage.setPixel(random(50,50),random(50,50),rgb(random(100),0,0))
   end repeat

  _end= the milliseconds

  put "with duplicate", _end - _start

  -- without duplicate

  _start= the milliseconds

  myImage = member("myImageMember").image

  repeat with i = 0 to 1200
     myImage.setPixel(random(50,50),random(50,50),rgb(random(100),0,0))
   end repeat

  _end= the milliseconds

  put "without duplicate", _end - _start

end

On my 866 mhz processor, the results are:

-- "with duplicate " 8
-- "without duplicate " 19


SETTING THE IMAGE OF A MEMBER

When setting the image of a member, its faster to use copyPixels than to set it using the member's image property:

Create a bitmap member and name it "myImageMember". Run this lingo on a framescript:


property myImage
property _start,_end

on beginSprite me

  myImage=image(100,100,32)

  -- create a gradient type graphic
   repeat with _x = 0 to 100
     repeat with _y = 0 to 100
       myImage.setPixel(_x,_y,rgb(_x,_y,0))
     end repeat
   end repeat

  -- using copyPixels
   _start= the milliseconds

  repeat with i = 0 to 100
     myImage.copyPixels(myImage,rect(0,0,100,100),rect(0,0,100,100))
   end repeat

  
   _end= the milliseconds

  put "with copyPixels ", _end - _start

  -- using image property
   _start= the milliseconds

  repeat with i = 0 to 100
     member("myImageMember").image = myImage
   end repeat

  
   _end= the milliseconds

  put "without copyPixels ", _end - _start

end

Here are the results:

-- "with copyPixels " 5
-- "without copyPixels " 16


PRE-STORING RECT VALUES

Instead of continually reading the rect property of a member, it makes sense to either hard code the rect value or store it in a variable. So:

property myImage

on beginSprite me

myImage=member("myImageMember").image.duplicate()

end

on prepareFrame me

(the stage).image.copyPixels(myImage,myImage.rect,myImage.rect)

end

would become:

property myImage, myImageRect

on beginSprite me

myImage=member("myImageMember").image.duplicate()

myImageRect = myImage.rect

end

on prepareFrame me

(the stage).image.copyPixels(myImage,myImageRect,myImageRect)

end

Speed Test:


-- with pre-storing
on prepareFrame me
   _start = the milliseconds
   repeat with i = 0 to 2000
     (the stage).image.copyPixels(myImage,myImageRect,myImageRect)
   end repeat
   _end = the milliseconds

  put _end - _start
end

-- without pre-storing
on prepareFrame me
   _start = the milliseconds
   repeat with i = 0 to 2000
     (the stage).image.copyPixels(myImage,myImage.rect,myImageRect.rect)
   end repeat
   _end = the milliseconds

  put _end - _start
end

The one with pre-storing takes 124 milliseconds and the one with out pre-storing takes 139. This isn't a huge difference, but it certainly doesn't hurt to implement it.


DRAWING TO THE STAGE

Something I see a good deal in imaging lingo source is an "imageBuffer" image object. Lingo programmers draw everything to this image object and then copy it to the stage. This is entirely uneccessary. There are times when it might make sense to create buffers, but it is definately not needed in all cases. I guess this tendancy comes from working with java or c/c++? Whatever the reason, its much faster in director to draw directly to the stage:

SLOW:

property myImage, buffer

property stageRect,myImageRect

property _start, _end


on beginSprite me

  myImage=member("myImageMember").image.duplicate()

  -- pre-store rects
   myImageRect = myImage.rect
   stageRect = (the stage).image.rect

  -- create image buffer
   buffer=image((the stage).image.width,(the stage).image.height,32)

end

on prepareFrame me

  _start = the milliseconds

  -- create a quick grid
   repeat with _x in [0,100,200,300]
     repeat with _y in [0,100,200,300]
       -- draw to buffer
       buffer.copyPixels(myImage,rect(_x,_y,100+_x,100+_y),myImageRect)
     end repeat
   end repeat

  -- draw buffer to stage
   (the stage).image.copyPixels(buffer,stageRect,stageRect)

  _end = the milliseconds

  put _end - _start

end

You'll see how long each frame is taking to draw in the message window. On my computer I see:

-- 12
-- 11
-- 13

Now, if we get rid of the extra step of drawing to a buffer we see a drastic speed improvement:

FAST:

property myImage

property stageRect,myImageRect

property _start, _end


on beginSprite me

  myImage=member("myImageMember").image.duplicate()

  -- pre-store rects
   myImageRect = myImage.rect
   stageRect = (the stage).image.rect

end

on prepareFrame me

  _start = the milliseconds

  -- create a quick grid
   repeat with _x in [0,100,200,300]
     repeat with _y in [0,100,200,300]
       -- draw to stage
       (the stage).image.copyPixels(myImage,rect(_x,_y,100+_x,100+_y),myImageRect)
     end repeat
   end repeat
 

  _end = the milliseconds

  put _end - _start

end

My message window now shows:

-- 3
-- 3
-- 3
-- 3
-- 3
-- 4
-- 3

Wow. This is a huge difference.

Thats about it. Of course, its not always neccessary to abide by these rules. I don't usually pre-store rects when I am setting up my image objects and sometimes I won't develop a project with all these optimizations in mind. I'll create the project and then go back and optimize where I feel its necessary. If anyone has additional imaging lingo optimizations, shoot me an e-mail and I'll ad them to this tutorial.