Help, fast image manipulation

Hi guys, I am struggeling with a slow image manipluation as reading and writing each pixel take a long time.

This script gets the viewport image and sets all RED values to 255, but it takes like 5 seconds to recalculate a 1000x500 pixel viewport.

import scriptcontext
import System
import rhinoscriptsyntax as rs

# Capture the active view to a System.Drawing.Bitmap
bitmap = scriptcontext.doc.Views.ActiveView.CaptureToBitmap()

### --- modify bitmap
### --- make new bitmap
format = System.Drawing.Imaging.PixelFormat.Format32bppRgb
Width= bitmap.Size.Width
Height=bitmap.Size.Height

print Width,str("x"),Height, str("pixels.  Total = "), Width*Height

bitmapNew = System.Drawing.Bitmap(Width, Height, format)

for iW in range(Width):
    for iH in range(Height):
        pixel=System.Drawing.Bitmap.GetPixel(bitmap,iW,iH)
        RGB = (255, pixel.G, pixel.B)
        color = rs.CreateColor(RGB)
        System.Drawing.Bitmap.SetPixel(bitmapNew, iW,iH, color)

Is there anything I can easily do to speed this up?

1 Like

– Dale

Hi Jørgen,

I did some optimization without the bitlocking Dale suggested. I think that will be even faster but I have no time to check that out.

What I did was create a new color directly from the pixelcolor.

640 x 407 pixels.  Total =  260480
JH_version : 8.17264556885
640 x 407 pixels.  Total =  260480
WD_version : 2.88730621338
import scriptcontext
import System
import rhinoscriptsyntax as rs

import time


def JH_version():

    # Capture the active view to a System.Drawing.Bitmap
    bitmap = scriptcontext.doc.Views.ActiveView.CaptureToBitmap()
    
    ### --- modify bitmap
    ### --- make new bitmap
    format = System.Drawing.Imaging.PixelFormat.Format32bppRgb
    Width= bitmap.Size.Width
    Height=bitmap.Size.Height
    
    print Width,str("x"),Height, str("pixels.  Total = "), Width*Height
    
    bitmapNew = System.Drawing.Bitmap(Width, Height, format)
    
    for iW in range(Width):
        for iH in range(Height):
            pixel=System.Drawing.Bitmap.GetPixel(bitmap,iW,iH)
            RGB = (255, pixel.G, pixel.B)
            color = rs.CreateColor(RGB)
            System.Drawing.Bitmap.SetPixel(bitmapNew, iW,iH, color)
            
            
def WD_version():
    
    # Capture the active view to a System.Drawing.Bitmap
    bitmap = scriptcontext.doc.Views.ActiveView.CaptureToBitmap()
    
    ### --- modify bitmap
    ### --- make new bitmap
    format = System.Drawing.Imaging.PixelFormat.Format32bppRgb
    Width= bitmap.Size.Width
    Height=bitmap.Size.Height
    
    print Width,str("x"),Height, str("pixels.  Total = "), Width*Height
    
    bitmapNew = System.Drawing.Bitmap(Width, Height, format)
    
    for iW in range(Width):
        for iH in range(Height):
            pixel=System.Drawing.Bitmap.GetPixel(bitmap,iW,iH)
            color = pixel.FromArgb(255,pixel.G, pixel.B)
            bitmapNew.SetPixel(iW,iH, color)

    #bitmapNew.Save('C:\\test.jpg')




            
def main():
    
    stime = time.time()
    JH_version()
    print 'JH_version time : {}'.format( time.time() - stime )
    
    
    stime = time.time()
    WD_version()
    print 'WD_version time : {}'.format( time.time() - stime )

main()
2 Likes

Wow, that was a quite nice optimization that still is easy for my mind to understand!
THANKS!

1 Like

For fast anti aliased line drawing I ended using classical array and not Bitmap
It was for this project
https://www.grasshopper3d.com/m/discussion?id=2985220%3ATopic%3A1764237

1 Like