Changeset 288

Show
Ignore:
Timestamp:
12/30/07 20:56:37 (12 months ago)
Author:
tom
Message:

added canvas.layer_pixels() and pixels.set_pixel()

Location:
libraries/coreimage
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • libraries/coreimage/__init__.py

    r235 r288  
    55 
    66__author__    = "Tom De Smedt" 
    7 __version__   = "1.9.1" 
     7__version__   = "1.9.2" 
    88__copyright__ = "Copyright (c) 2007 Tom De Smedt" 
    99__license__   = "MIT" 
     
    3737LAYER_LAYERS          = "layers" 
    3838LAYER_PATH            = "path" 
     39LAYER_PIXELS          = "pixels" 
    3940LAYER_CIIMAGEOBJECT   = "CIImageobject" 
    4041LAYER_NSIMAGEDATA     = "NSImageData" 
     
    321322        except: pass 
    322323         
     324        # Pixels 
     325        # A one-dimensional list of color objects. 
     326        try: 
     327            clr, w, h = data[0][0], data[1], data[2] 
     328            r, g, b, a = clr.r, clr.g, clr.b, clr.a 
     329            type = LAYER_PIXELS 
     330            return _add_layer(data, type, x, y, w, h) 
     331        except: pass 
     332         
    323333        # Core Image CIImage object. 
    324334        try: 
     
    420430         
    421431        return self.layer((path, background, foreground, stroke, strokewidth), LAYER_PATH, x, y, w, h, name) 
     432 
     433    def layer_pixels(self, colors, w, h, 
     434                     x=None, y=None, name=""): 
     435         
     436        """ Adds a new layer from a list of pixel colors. 
     437        """ 
     438         
     439        return self.layer((colors, w, h), LAYER_PIXELS, x, y, w, h, name) 
    422440     
    423441    def layer_bytes(self, data,  
     
    427445         
    428446        Creates an NSImage from the data. 
    429         This method is should go somewhere because it references Cocoa. 
     447        This method should go somewhere else because it references Cocoa. 
    430448         
    431449        """ 
     
    580598    def is_file(self)            : return (self.type == LAYER_FILE) 
    581599    def is_fill(self)            : return (self.type == LAYER_FILL)     
    582     def is_gradient(self)        : return (self.type == LAYER_LINEAR_GRADIENT)     
     600    def is_gradient(self)        : return (self.type == LAYER_LINEAR_GRADIENT or 
     601                                           self.type == LAYER_RADIAL_GRADIENT)     
    583602    def is_linear_gradient(self) : return (self.type == LAYER_RADIAL_GRADIENT) 
    584603    def is_radial_gradient(self) : return (self.type == LAYER_LINEAR_GRADIENT)     
    585604    def is_path(self)            : return (self.type == LAYER_PATH) 
     605    def is_pixels(self)          : return (self.type == LAYER_PIXELS) 
     606    def is_group(self)           : return (self.type == LAYER_LAYERS) 
    586607    def has_layers(self)         : return (self.type == LAYER_LAYERS) 
    587608    def is_mask(self)            : return (self.canvas._parent != None and  
     
    661682        if self.type == LAYER_PATH: 
    662683            data = (self.data[0].copy(), Color(self.data[1]), Color(self.data[2]), Color(self.data[3]), self.data[4]) 
     684        if self.type == LAYER_PIXELS: 
     685            data = self.data 
    663686        if self.type == LAYER_CIIMAGEOBJECT: 
    664687            data = self.data 
     
    14181441                path.stroke()             
    14191442            img.unlockFocus() 
     1443            img = img.TIFFRepresentation() 
     1444            img = CIImage.alloc().initWithData_(img) 
     1445         
     1446        if type == LAYER_PIXELS: 
     1447             
     1448            # The layer's source is a list of pixel colors. 
     1449            # Duane Bailey, http://nodebox.net/code/index.php/shared_2007-12-28-23-34-57 
     1450            # If there is more width*height than there are pixels, 
     1451            # the bitmap will be completed with transparent pixels. 
     1452             
     1453            p, w, h = data 
     1454            import Numeric 
     1455            raw = Numeric.array([0] * w*h*4, typecode='c') 
     1456            for i in range(len(p)): 
     1457                raw[i*4+0] = p[i].r * 255 
     1458                raw[i*4+1] = p[i].g * 255 
     1459                raw[i*4+2] = p[i].b * 255 
     1460                raw[i*4+3] = p[i].a * 255 
     1461            raw = (raw, None, None, None, None) 
     1462            img = NSBitmapImageRep.alloc().initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bytesPerRow_bitsPerPixel_( 
     1463                raw, w, h, 8, 4, True, False, NSDeviceRGBColorSpace, w * 4, 32 
     1464            ) 
    14201465            img = img.TIFFRepresentation() 
    14211466            img = CIImage.alloc().initWithData_(img) 
     
    24162461        self._img = self._img.TIFFRepresentation() 
    24172462        self._img = NSBitmapImageRep.imageRepWithData_(self._img) 
    2418          
    2419         raw = self._img.bitmapData() 
    2420         a = Numeric.fromstring(raw, Numeric.UnsignedInt8) 
    2421          
     2463 
    24222464        self.channels = self._img.samplesPerPixel() 
    2423         self.pixels = Numeric.reshape(a, (self.w*self.h, self.channels)) 
    2424          
    2425         if self.is_rgb(): 
    2426             self.r = self.pixels[:,0]  
    2427             self.g = self.pixels[:,1] 
    2428             self.b = self.pixels[:,2] 
    2429             self.a = None 
    2430             if self.has_alpha(): self.a = self. pixels[:,3] 
    2431      
     2465 
    24322466    def is_rgb(self): 
    24332467         
     
    24402474    def get_pixel(self, x, y): 
    24412475         
    2442         """ Returns color values for the pixel at x, y. 
    2443         """ 
    2444          
    2445         if 0 <= x < self.w and 0 <= y < self.h: 
    2446             return list(self.pixels[x+y*self.w]) 
    2447         else: 
    2448             return None 
    2449      
    2450     def min(self, transparency=False, treshold=0): 
     2476        """ Returns color for the pixel at x, y. 
     2477        """ 
     2478         
     2479        return _ctx.color(self._img.colorAtX_y_(x, y)) 
     2480         
     2481    def set_pixel(self, x, y, clr): 
     2482         
     2483        """ Sets the pixel at x, y with the given color. 
     2484        """ 
     2485         
     2486        self._img.setColor_atX_y_(clr._rgb, x, y) 
     2487 
     2488    def update(self): 
     2489         
     2490        """ Updates the layer with the changes from set_pixel(). 
     2491        """ 
     2492         
     2493        self.layer.data = self._img.TIFFRepresentation() 
     2494        self.layer.type = LAYER_NSIMAGEDATA 
     2495 
     2496    def _array(self, int=8): 
     2497         
     2498        """ All the pixel color values as a lists of integers. 
     2499        """ 
     2500         
     2501        bytes = self._img.bitmapData() 
     2502        a = Numeric.fromstring(bytes, Numeric.UnsignedInt8) 
     2503        a = Numeric.reshape(a, (self.w*self.h, self.channels)) 
     2504        if int == 32: 
     2505            a = a.astype(Numeric.UnsignedInt32) 
     2506         
     2507        return a 
     2508     
     2509    def min(self, transparency=False, threshold=0): 
    24512510         
    24522511        """ Returns the lowest color values in the image. 
    24532512         
    24542513        By default, transparent pixels (alpha=0) are 
    2455         not searched. The treshold defines the cutoff, 
    2456         for example treshold=100 means that all pixels with alpha 
    2457         less than 100 are not taken into account. 
    2458          
    2459         """ 
    2460  
    2461         a = self.pixels.astype(Numeric.UnsignedInt32) 
     2514        not searched. The threshold defines the cutoff, 
     2515        for example threshold=0.1 means that all pixels with alpha 
     2516        less than 10% are not taken into account. 
     2517         
     2518        """ 
     2519 
     2520        if isinstance(threshold, int):  
     2521            threshold /= 255.0 
     2522             
     2523        a = self._array(int=32) 
    24622524        if transparency == False and self.has_alpha(): 
    2463             i = Numeric.nonzero(Numeric.greater(self.a, treshold)) 
     2525            i = Numeric.nonzero(Numeric.greater(self.a, threshold)) 
    24642526            a = Numeric.take(a, i) 
    24652527         
     
    24682530        for j in range(self.channels): 
    24692531            v.append(a[i[j]][j]) 
    2470         return v 
    2471      
    2472     def max(self, transparency=False, treshold=0): 
     2532         
     2533        # Return a color object: 
     2534        clr = _ctx.color(0) 
     2535        clr.r, clr.g, clr.b = v[0]/255.0, v[1]/255.0, v[2]/255.0 
     2536        if self.has_alpha():  
     2537            clr.a = v[3]/255.0 
     2538        return clr 
     2539     
     2540    def max(self, transparency=False, threshold=0): 
    24732541 
    24742542        """ Returns the highest color values in the image. 
    24752543        """ 
    24762544 
    2477         a = self.pixels.astype(Numeric.UnsignedInt32) 
     2545        if isinstance(threshold, int):  
     2546            threshold /= 255.0 
     2547         
     2548        a = self._array(int=32) 
    24782549        if transparency == False and self.has_alpha(): 
    2479             i = Numeric.nonzero(Numeric.greater(self.a, treshold)) 
     2550            i = Numeric.nonzero(Numeric.greater(self.a, threshold)) 
    24802551            a = Numeric.take(a, i) 
    24812552         
     
    24842555        for j in range(self.channels): 
    24852556            v.append(a[i[j]][j]) 
    2486         return v 
    2487          
    2488     def average(self, transparency=False, treshold=0): 
     2557         
     2558        # Return a color object: 
     2559        clr = _ctx.color(0) 
     2560        clr.r, clr.g, clr.b = v[0]/255.0, v[1]/255.0, v[2]/255.0 
     2561        if self.has_alpha():  
     2562            clr.a = v[3]/255.0 
     2563        return clr 
     2564         
     2565    def average(self, transparency=False, threshold=0): 
    24892566         
    24902567        """ Returns the average color values in the image. 
    24912568        """ 
    24922569         
    2493         a = self.pixels.astype(Numeric.UnsignedInt32) 
    2494         n = len(self.pixels) 
    2495          
     2570        a = self._array(int=32) 
     2571        n = len(a) 
     2572         
     2573        if isinstance(threshold, int):  
     2574            threshold /= 255.0 
    24962575        if transparency == False and self.has_alpha(): 
    2497             i = Numeric.nonzero(Numeric.greater(self.a, treshold)) 
     2576            i = Numeric.nonzero(Numeric.greater(self.a, threshold)) 
    24982577            a = Numeric.take(a, i) 
    24992578            n = len(i) 
     
    25042583        for i in range(self.channels): 
    25052584            v.append(int(a[i])) 
    2506         return v 
     2585         
     2586        # Return a color object: 
     2587        clr = _ctx.color(0) 
     2588        clr.r, clr.g, clr.b = v[0]/255.0, v[1]/255.0, v[2]/255.0 
     2589        if self.has_alpha():  
     2590            clr.a = v[3]/255.0 
     2591        return clr 
    25072592         
    25082593    def histogram(self, channel=None, helper=False): 
     
    25172602        """ 
    25182603         
     2604        a = self._array() 
     2605         
    25192606        bins = Numeric.arange(1, 255, 1) 
    25202607        v = [] 
    25212608        for i in range(self.channels): 
    2522             p = self.pixels[:,i] 
     2609            p = a[:,i] 
    25232610         
    25242611            # From the NumPy searchsorted() documentation. 
     
    29032990    c.draw() 
    29042991 
     2992# 1.9.2 
     2993# Added layers_pixels() to Canvas. 
     2994# Added set_pixel() to CoreImagePixels. 
     2995# All of the CoreImagePixels methods, except histogram(), 
     2996# now use color() objects instead of lists of R,G,B values. 
     2997 
    29052998# 1.9.0 
    29062999# Layers from bytes (e.g. download stream) can be created with Canvas.layer_bytes(). 
  • libraries/coreimage/coreimage-example5.py

    r181 r288  
    1 size(500, 500) 
     1# Coffee dynamics. 
    22 
    33try:  
     
    77    reload(coreimage) 
    88 
     9size(500, 500) 
    910speed(30) 
    1011def setup(): 
     
    2425     
    2526    # The bottom layer is a brownish fill color. 
    26     l = canvas.layer_fill(color(0.2,0.15,0)) 
     27    l = canvas.layer_fill(color(0.07,0.05,0)) 
    2728 
    2829    if not copy: 
     
    3031        # construct a layer from an outlined text path. 
    3132        fontsize(100) 
    32         p = textpath("SMOKE", 0, 50) 
    33         copy = canvas.layer_path(p, foreground=color(1)) 
     33        p = textpath("COFFEE", 0, 50) 
     34        copy = canvas.layer_path(p, foreground=color(1,1,0.95)) 
    3435    else: 
    3536        # During the next frames of the animation, 
  • libraries/coreimage/coreimage-example6.py

    r234 r288  
    5050c.draw() 
    5151 
    52 """ 
     52 
    5353# Some fun converting pixels to curves. 
    5454# Uncomment the code below to grow grass on a sphere. 
    55  
     55""" 
    5656l.adjust_contrast(1.1) 
    5757 
    5858p = l.pixels() 
    5959 
    60 colormode(RGB, 255) 
    6160nofill() 
    6261strokewidth(0.25) 
     
    7372        # more requires to much processing and clogs the image. 
    7473        if random() > 0.5: 
    75             r,g,b,a = p.get_pixel(i,j) 
     74            clr = p.get_pixel(i,j) 
    7675             
    7776            # We don't draw curves on black pixels. 
    78             if not (r == g == b == 0): 
     77            if not (clr.r == clr.g == clr.b == 0): 
    7978                 
    8079                # The actual location of the curve 
     
    8887                dy = y-l.y 
    8988                dh = 20 
    90                  
    91                 c = color(r, g, b) 
    92                 c.b += random(1.5) 
    93                 stroke(c) 
    94                  
     89 
     90                stroke(clr) 
    9591                beginpath(x, y) 
    9692                curveto(x+random(dh),