A grid of rectangles

Visuals, audio, animation. Blended, not stirred. If LiveCode is part of your rich media production toolbox, this is the forum for you.

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller

capellan
Posts: 654
Joined: Wed Aug 15, 2007 11:09 pm

A grid of rectangles

Post by capellan » Sun Oct 09, 2016 7:14 am

Hi All,

Look this stack with a script to create a grid
of colored rectangles.

How could we make this script much faster
for grids of greater size? (like 256 or 512)

Thanks in advance!

Alejandro
Create_GRID.livecode.zip

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3999
Joined: Sun Jan 07, 2007 9:12 pm
Location: Bochum, Germany

Re: A grid of rectangles

Post by bn » Sun Oct 09, 2016 8:58 am

Hi Alejandro,

try this script for the "Create Grid" button

Code: Select all

on mouseUp
   set the cursor to busy
   send "mouseup" to button "Erase Grid"
   lock screen
   put 170 into hLoc
   put 20 into vLoc
   put the label of button "myGridspacing" of this card into tgridSpacing
   put the label of button "myGridsize" of this card into tgridSize
   set the width of the templateGraphic to tGridSpacing
   set the height of the templateGraphic to tGridSpacing
   set the filled of the templateGraphic to true
   set the lineSize of the templateGraphic to empty
   lock messages
   repeat with j = 1 to tgridSize
      repeat with k = 1 to tgridSize
         set the backcolor of the templateGraphic to any item of "red,green,blue,yellow,orange,purple,white"
         set the loc of the templateGraphic to hLoc + (k * tgridSpacing),vLoc
         create graphic 
      end repeat
      put vLoc + tgridSpacing into vLoc
   end repeat
   
   unlock messages
   unlock screen
end mouseUp
and this for the "Erase Grig" button

Code: Select all

on mouseUp
   set the cursor to busy
   lock screen
   lock messages
   repeat with h = the number of graphics of this card down to 1
      delete graphic h of this card
   end repeat
   lock messages
   unlock screen
end mouseUp
Kind regards
Bernd

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3999
Joined: Sun Jan 07, 2007 9:12 pm
Location: Bochum, Germany

Re: A grid of rectangles

Post by bn » Sun Oct 09, 2016 9:15 am

Hi Alejandro,

if you don`t mind to create the graphics in a group then deletion of the graphics would be much faster.

Here are the scripts

for "Create Grid" button

Code: Select all

on mouseUp
   set the cursor to busy
   lock screen
   lock messages
   if there is a group "checkerBoard" then delete group "checkerBoard"
   reset the templateGraphic
   
   put 170 into hLoc
   put 20 into vLoc
   put the label of button "myGridspacing" of this card into tgridSpacing
   put the label of button "myGridsize" of this card into tgridSize
   set the width of the templateGraphic to tGridSpacing
   set the height of the templateGraphic to tGridSpacing
   set the filled of the templateGraphic to true
   set the lineSize of the templateGraphic to empty
   create group "checkerBoard"
   
   repeat with j = 1 to tgridSize
      repeat with k = 1 to tgridSize
         set the backcolor of the templateGraphic to any item of "red,green,blue,yellow,orange,purple,white"
         set the loc of the templateGraphic to hLoc + (k * tgridSpacing),vLoc
         create graphic in group "checkerBoard"
      end repeat
      put vLoc + tgridSpacing into vLoc
   end repeat
   
   reset the templateGraphic
   unlock messages
   unlock screen
end mouseUp
for "Erase Grid" button

Code: Select all

on mouseUp
   set the cursor to busy
   lock screen
   lock messages
   if there is a group "checkerBoard" then delete group "checkerBoard"
   lock messages
   unlock screen
end mouseUp
If you use the templateGraphic approach then you should reset the templateGraphic before using it and reset the templateGraphic again after you used it. I did that in this post, forgot to add it in the previous one.

Kind regards
Bernd

jmburnod
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 2718
Joined: Sat Dec 22, 2007 5:35 pm
Location: Genève
Contact:

Re: A grid of rectangles

Post by jmburnod » Sun Oct 09, 2016 9:56 am

Hi Alejandro and Bernd,
I began with a clone approach but Bernd's way is faster, like its author.
1268 milliseconds for a 64X64 grid (7505 with the first version)
Kind regards
https://alternatic.ch

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3999
Joined: Sun Jan 07, 2007 9:12 pm
Location: Bochum, Germany

Re: A grid of rectangles

Post by bn » Sun Oct 09, 2016 2:01 pm

Salut Jean-Marc,

@Alejandro,

if you don't necessarily need graphics for the grid then here is a version that does an image with the same appearence as the graphics grid. The advantage is that you don't create a gazillion graphics but only one image. Of course it then is, well, just an image.

Kind regards

Bernd

Edit: I forgot to mention that the coloname to RGB conversion is in a custom property of the card as an array. This means you can use any valid colorName in the variable for colors to fill the grid.
Attachments
Create Grid Image.livecode.zip
(7.48 KiB) Downloaded 283 times

[-hh]
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 2262
Joined: Thu Feb 28, 2013 11:52 pm
Location: Göttingen, DE

Re: A grid of rectangles

Post by [-hh] » Sun Oct 09, 2016 8:21 pm

Hi all,
that's an impressive demo of using "the template graphic" here.

Bernd, your first script runs here much faster than your 'grouping-script', using for deletion the following:

Code: Select all

-- delete all graphics
-- button "Erase Grid"
on mouseUp
  lock screen; lock messages
  repeat the num of grcs -- of this card
    delete grc 1
  end repeat
  unlock messages; unlock screen
end mouseUp

Code: Select all

-- Bernd's script slightly modified
-- button "Create Grid"
on mouseUp
  put the millisecs into m1
  put 120 into hLoc
  put 20 into vLoc
  
  set cursor to watch
  lock screen; lock messages
  -- in case you test with grouping
  if there is a grp "checkerboard" then delete grp "checkerboard"
  set the randomseed to the seconds

  ---use now a simple deletion 'inline':
  repeat the num of grcs -- of this card
    delete grc 1
  end repeat
  ---
  reset the templateGraphic
  
  put the label of button "myGridspacing" into tgridSpacing
  put the label of button "myGridsize" into tgridSize
  set the width of the templateGraphic to tGridSpacing
  set the height of the templateGraphic to tGridSpacing
  set the lineSize of the templateGraphic to 0
  set the filled of the templateGraphic to true
  --set the style of the templateGraphic to "rectangle"
  -- Try this, looks nice:
  set the style of the templateGraphic to "oval"
  --   set the style of the templateGraphic to "regular"
  --   set the polysides of the templateGraphic to "3"
  --   set the angle of the templateGraphic to "-90"
  repeat with j = 1 to tgridSize
    repeat with k = 1 to tgridSize
      set the backcolor of the templateGraphic to any item of \
            "red,green,blue,yellow,orange,purple,white"
      set the loc of the templateGraphic to hLoc + (k * tgridSpacing),vLoc
      -- create graphic in grp "checkerboard" -- slower
      create graphic
    end repeat
    add tgridSpacing to vLoc
  end repeat
  reset the templateGraphic
  put the millisecs-m1 into fld "info"
  unlock messages; unlock screen
end mouseUp
This script, using as parameters
= a grid size of 64 (= 64*64 = 4096 objects)
= a gridspacing of 20
runs here, on a medium fast machine (2.5 GHz),
in 80 millisecs with LC 7/8, in 40 millisecs with LC 6.

So, creating objects in a group is much slower. But the grouping possibly has several advantages later on, when working with the objects. TMHO it still depends on the project, what's *effectively* better/faster.

EDIT. WARNING.
If you choose a gridSize of 256 or more then you exceed with the number of objects (256^2 or more) the "limit of LiveCode" which is 65535 (=2^16-1). This is still in LC 8 and will 'silently' not execute (parts of) the above scripts.

Then you should replace in both scripts:

Code: Select all

--replace the lines:
  repeat the num of grcs -- of this card
    delete grc 1 -- of this card
  end repeat
 
-- with the slower but safer lines:
  repeat while there is a grc 1 -- of this card
    delete grc 1 -- of this card
  end repeat
shiftLock happens

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3999
Joined: Sun Jan 07, 2007 9:12 pm
Location: Bochum, Germany

Re: A grid of rectangles

Post by bn » Sun Oct 09, 2016 9:43 pm

Hi Hermann,

that looks very nice, your effects.

I did not really benchmark this, it was benchmarking by feeling.
what got me to use a group was twofold: first the original deletion was really slow. Deleting a group is nearly instantaneous.

I use

Code: Select all

repeat with h = the number of graphics of this card down to 1
      delete graphic h of this card
   end repeat
instead of your

Code: Select all

repeat the num of grcs -- of this card
    delete grc 1
  end repeat
your code is a lot faster than mine.
apparently livecode reevaluates the number of graphics each time when doing

Code: Select all

repeat with h = the number of graphics
Your observation that creating a graphic in a group is much slower than directly to the card surprises me by the magnitude of the effect.
The net effect of deleting the group, recreating it and placing the graphics into the group was a lot faster than the old deletion handler.
That is why I did not notice the stark difference in execution time for creating graphics in a group.
Again I did what Alejandro said: make it much faster. :) And so it was.

A second argument for a group was that it makes it a lot easier to move around. Although dragging a group in the IDE with that many graphics is very slow.

I think Alejandro should say what the use case is and if he really needs graphics. He speaks of up to 512 * 512 cells. That this will probably choke Livecode. So I looked again into doing this using ImageData. I will post below my improved version which creates a 64 by 64 grid with cell width 20 in around 130 milliseconds. This compares quite favorably with using graphics.
A 256 by 256 grid cell size 20 take about 2100 milliseconds and does not choke Livecode. All time for 8.1.1 RC 1 on 2.5 MHz Intel core i5.


Thanks for looking into this.
Kind regards

Bernd

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3999
Joined: Sun Jan 07, 2007 9:12 pm
Location: Bochum, Germany

Re: A grid of rectangles

Post by bn » Sun Oct 09, 2016 9:46 pm

Here is an improved grid using imageData and an image.

It is about 30 percent faster than the former one. Posted above. The rest is identical.
The faster code is in button "Create GridImageII".

Kind regards
Bernd
Attachments
Create Grid Image II.livecode.zip
hurry, hurry, make an image
(7.85 KiB) Downloaded 294 times

[-hh]
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 2262
Joined: Thu Feb 28, 2013 11:52 pm
Location: Göttingen, DE

Re: A grid of rectangles

Post by [-hh] » Sun Oct 09, 2016 10:22 pm

Bernd,

your first graphic script I used above is here still faster than "Create GridImage II"?
[for gridsize 256, gridspacing 20 at about 1 second]
Obviuosly the gridspacing has by enlarging the size of the image more impact than in the graphics solution.

Perhaps: If you make a one-pixel grid (temporary gridspacing=1), set the resizeQuality of your image to "normal", and then resize by factor gridspacing?
This should result in an identical output, but may result in a faster runtime?

Hermann

Edit. Set the resizeQuality of the image to "good" and we have, with slightly more cpu-time, this well-known nice blur-effect (see also http://forums.livecode.com/viewtopic.ph ... 51#p141051 and the link there).
Attachments
grid.jpg
shiftLock happens

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3999
Joined: Sun Jan 07, 2007 9:12 pm
Location: Bochum, Germany

Re: A grid of rectangles

Post by bn » Sun Oct 09, 2016 11:55 pm

Hermann,

Button "Create ImageII" roughly 2100 milliseconds.
Producing a 5120 by 5120 pixel image.

Button "Create Grid" -> graphic roughly 1500 milliseconds for 65536 graphics. I noticed I could not delete the graphics with your button unless I deleted 1 graphic manually.

But at "reasonable" dimensions image is still quite fast.

Your idea to reduce the cellSize to 1 and then rescale is brilliant.

It reduces the time for a 256 by 256 gridSize with a cell size of 20 to roughly 350 milliseconds from 2100. No discernible difference in image Quality.

Here is the script I used

Code: Select all

on mouseUp
   set the cursor to busy
   lock screen
   lock messages
   put the milliseconds into tTime
   
   if not (there is an image "testImg") then create image "testImg"
   
   local tAlpha
   put numToByte(255) into tAlpha
   
   put the cColorNameToRGB of this card into tTranslateColorA
   
   -- get RGB values
   local tColorNames
   put "red,green,blue,yellow,orange,purple,white" into tColorNames
   
   local tColorA
   local tR; local tG; local tB; local tTriplet
   
   repeat for each item aColor in tColorNames
      put tTranslateColorA[aColor] into tTriplet
      put numToByte(item 1 of tTriplet) into tR
      put numToByte(item 2 of tTriplet) into tG
      put numToByte(item 3 of tTriplet) into tB
      put tAlpha & tR & tG & tB into tColorA[aColor]
   end repeat
   
   
   put the label of button "myGridspacing" into tCellWidth
   put the label of button "myGridsize" into tNoOfCells
   put tCellWidth * tNoOfCells into tPixelWidth
   put 1 into tempCellWidth
   put the keys of tColorA into tKeys
   
   local tOneLIneOfCellA
   
   repeat for each key aColorByte in tColorA
      repeat tCellWidth
         put tColorA[aColorByte] after tOneLineOfCellA[aColorByte]
      end repeat
   end repeat
   
   put "" into tAllPixel
   repeat tNoOfCells
      put giveOnCellHeightData(tNoOfCells, tempCellWidth, tOneLineOfCellA) into tOneCellHeight
      put tOneCellHeight after tAllPixel
      put ""  into tOneCellHeight
   end repeat
   
   set the width of image "testImg" to tPixelWidth
   set the height of image "testImg" to tNoOfCells
   
   set the imageData of img "testImg" to tAllPixel
   
   set the height of img "testImg" to tPixelWidth
   set the topLeft of image "testImg" to 150,30
   unlock messages
   unlock screen
   put the milliseconds - tTime
end mouseUp

private function giveOnCellHeightData @tNoOfCells, @tempCellWidth, @tOneLineOfCellA
   put the keys of tOneLineOfCellA into tKeys
   repeat tNoOfCells
      put "" into tCell1PxHeightColor
      put any line of tKeys into tKey
      put tOneLineOfCellA[tKey] after tCell1PxHeightColor
      put tCell1PxHeightColor after t1PixLine
   end repeat
   repeat tempCellWidth
      put t1PixLine after tOneCellHeight
   end repeat
   return tOneCellHeight
end giveOnCellHeightData
make a new button with this script in stack "Create Image II"

Kind regards
Bernd

capellan
Posts: 654
Joined: Wed Aug 15, 2007 11:09 pm

Re: A grid of rectangles

Post by capellan » Mon Oct 10, 2016 12:36 am

Hi Bernd and Hermann,

This script that I posted was created with a purely didactic purpose. It's part of a stack that explain visually (and step-by-step) the kind of mathematical operations used to create and modify bitmap images.

I am grateful surprised by the optimizations that two LiveCode professionals could make to a simple handler.

Lock messages is the kind of optimization that always slips out of my mind. I have to test if this code would optimize the creation of graphics in the stack EpsImportv05c.

After watching how fast your scripts could handle the creation of bitmaps, I just keep wondering if the results posted in this old thread are still valid and current:
http://forums.livecode.com/viewtopic.php?f=6&t=8918

In 2016, LiveCode is much faster than 5 years ago and it's source code have been optimized many times since then. For example, the problem exposed in this another thread was solved in LiveCode 6.5.x and now renders as the Lingo and Photoshop example.

Test this by yourself. Download the file named "Image_Effects.zip" from a message in page 1 of this thread and test the stack using LiveCode 6.5.x.or later.

I found no differences, using a Posterization of 6, with the Photoshop and Director's image posted in page 1 of this thread: http://forums.livecode.com/viewtopic.php?f=32&t=8993

Al
Last edited by capellan on Mon Oct 10, 2016 1:36 am, edited 1 time in total.

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3999
Joined: Sun Jan 07, 2007 9:12 pm
Location: Bochum, Germany

Re: A grid of rectangles

Post by bn » Mon Oct 10, 2016 1:21 am

Hi Alejandro,

this is a special case of imageData manipulation that lends itself to optimization.
Unfortunately not all imageData operation are faster in 8.x compared to 6.x. Iterating over every pixel is slower than it used to be. And in most cases of image manipulation you have to do that. Certain optimizations are possible on a case by case basis. This has to be done differently for every type of image manipulation.
The "worst case" is convolve where you are forced to go through byteToNum and numToByte over and over again.
But in many cases a little optimization helps.
The script may not be so obvious afterwards though...

Kind regards
Bernd

[-hh]
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 2262
Joined: Thu Feb 28, 2013 11:52 pm
Location: Göttingen, DE

Re: A grid of rectangles

Post by [-hh] » Mon Oct 10, 2016 1:49 am

bn wrote:The "worst case" is convolve where you are forced to go through byteToNum and numToByte over and over again.
Use imageJIT ...
http://forums.livecode.com/viewtopic.ph ... 32#p143932
shiftLock happens

capellan
Posts: 654
Joined: Wed Aug 15, 2007 11:09 pm

Re: A grid of rectangles

Post by capellan » Mon Oct 10, 2016 1:52 am

I understand. Looks like a little help from LiveCode Engine could help a great length in bitmap edition and creation.

If both of you could add to LC Engine just one function for bitmap manipulation,
Which would you choose?

1) A function to replace the pixels of the imagedata of an image
with the pixels of another image (starting at any location within
the imagedata). (i.e. paste an image into other image)

2) A function to copy (and distort) the pixels of the imagedata of an image
within four coordinates (like a trapezoid) or three points (like a triangle)
of another image.

Al

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 3999
Joined: Sun Jan 07, 2007 9:12 pm
Location: Bochum, Germany

Re: A grid of rectangles

Post by bn » Mon Oct 10, 2016 2:33 am

1) A function to replace the pixels of the imagedata of an image
with the pixels of another image (starting at any location within
the imagedata). (i.e. paste an image into other image)

2) A function to copy (and distort) the pixels of the imagedata of an image
within four coordinates (like a trapezoid) or three points (like a triangle)
of another image.
neither really. More basic. A speed-up in byte iteration would go a long way.

as far as your question is concerned:
1. is not that hard to do and quite fast since you could insert wholesale imagedate. Or just use snapshots, that is the easiest and fastest.
see this topic: http://forums.livecode.com/viewtopic.ph ... +watermark
2. is a special case with little use to me.

Kind regards
Bernd

Post Reply

Return to “Multimedia”