2 summary:: image component
4 related:: Classes/SCImageFilter, Classes/SCImageKernel
8 SCImage is an image component for the Mac OS X supercollider client. SCImage is currently a wrapper around different models : you can use it for bitmap operations, image embedding for custom UI and for more advanced image processing as applying filters and kernels, both provided with the CoreImage framework.
10 SCImage currently supports most formats including tiff, bmp, gif, jpeg, png, tga...ect.. for reading. But for for writing it supports only those in code::SCImage.formats::.
13 link::Classes/GUI:: Issue : since it is OS X only, be sure to call code::GUI.cocoa:: before any SCImage.call
18 PRIVATE::initClass, prFromWindowRect, prFreeAll
21 Creates a new SCImage instance. multiple stands here for multiple arguments.
26 ## link::Classes/Number:: to create an strong::empty:: image of size multiple as width and height
28 i = SCImage.new(400); // Create a 400x400 pixels SCimage.
32 i = SCImage.new(400,200); // Create a 400x200 pixels SCimage.
36 ## link::Classes/Point:: to create an strong::empty:: image of size multiple.x as width and multiple.y as height
38 i = SCImage.new(400@200); // Create a 400x200 pixels SCimage.
42 ## link::Classes/String:: to create an image from a strong::local file:: or from an strong::URL:: (http://, ftp://, file:///)
45 i = SCImage.new("/Library/Desktop Pictures/Ripples Blue.jpg");
46 [i.width, i.height].postln;
49 // URL string - http:// or ftp:// - blocks until image is downloaded
50 i = SCImage.new("http://www.google.com/intl/en_ALL/images/logo.gif");
58 Creates a new SCImage instance filled with the specified color.
60 i = SCImage.color(400, 200, Color.blue(0.9,0.1));
61 i.plot(freeOnClose:true);
65 multiple arguments. the last argument should be a valid link::Classes/Color::
68 Creates a new SCImage instance from the local file at strong::path::.
71 i = SCImage.open("/Library/Desktop Pictures/Ripples Blue.jpg");
72 i.plot(freeOnClose:true);
78 Creates a new SCImage instance from a valid image at the specified URL strong::path::.
80 i = SCImage.openURL("file:///Library/Desktop%20Pictures/Ripples%20Blue.jpg");
82 w = i.plot(freeOnClose:true);
86 Creates a new SCImage instance from another SCImage.
88 i = SCImage.new(SCDoc.helpSourceDir +/+ "images/vduck2.jpg");
89 j = SCImage.fromImage(i);
97 Creates a new SCImage from a portion of a SCWindow. this can be used to capture either a window or a specific SCView.
101 // First create a window and draw inside of it
104 w.front; // comment this to copy offscreen window
105 w.view.background_(Color.white);
107 SCPen.translate(100, 100);
110 SCPen.color = Color.blue(rrand(0.0, 1), rrand(0.0, 0.5));
111 SCPen.addWedge((100.rand)@(100.rand), rrand(10, 100), 2pi.rand, 2pi.rand);
112 SCPen.perform([\stroke, \fill].choose);
118 // then grab the window
120 i = SCImage.fromWindow(w);
122 i.plot(freeOnClose:true);
125 // VIEW Capture Example:
126 // First create a window and add some views inside of it
128 w = SCWindow.new.front;
130 c = SCNumberBox(w, Rect(20, 20, 60, 40));
131 a = SCSlider(w, Rect(20, 80, 100, 40))
132 .focusColor_(Color.red(alpha:0.2))
134 c.value_(b.map(a.value).round(0.01))
135 // round the float so it will fit in the SCNumberBox
139 // then grab the window
141 i = SCImage.fromWindow(w, a.bounds);
143 i.plot(freeOnClose:true);
151 optional. the constrained rect to capture inside the SCWindow. By default, it is the window size.
153 SUBSECTION::Class variables and attributes
156 returns all the valid image formats as an link::Classes/Array::
161 METHOD::compositingOperations
162 returns all the valid compositing operations you can use when drawing an SCImage as an link::Classes/Array::
164 SCImage.compositingOperations;
167 METHOD::interpolations
168 returns an link::Classes/Array:: of the different levels of interpolation you can specify when drawing an SCImage.
170 SCImage.interpolations;
173 METHOD::closeAllPlotWindows
174 close all the SCImage plot windows currently opened.
178 PRIVATE::prLockFocus, prDrawAtPoint, prSync, prApplyFilters, prTileInRect, prUpdatePixelsInRect, prGetPixel, prInit, prSetInterpolation, prFree, prSetPixel, prLoadPixels, prSetBackground, prApplyKernel, prUpdatePixels, prWriteToFile, prUnlockFocus, prInitFromURL, prSetColor, prGetColor, prSetName, prGetInterpolation, prDrawInRect
180 SUBSECTION::commons / general attributes
183 returns or set the width of the receiver
186 returns or set the height of the receiver
189 set the size of the receiver
192 returns the bounds of the receiver.
195 deallocate the receiver. this method is useful if you want to manage and reclaim yourself resources. otherwise you do not need to call this method since each object is automatically garbage collected.
197 i = SCImage.new("/Library/Desktop Pictures/Ripples Blue.jpg");
203 METHOD::scalesWhenResized
204 flag to tell or set if the receiver should update its bitmap representation to scale when a resize operation if performed
207 i = SCImage.new("/Library/Desktop Pictures/Ripples Blue.jpg");
208 i.bounds.postln; // getting the dimensions
212 // changing the size of an image
214 i.scalesWhenResized_(true);
215 i.setSize(400, 400 / (i.width / i.height));
219 a.close; w.close; i.free;
224 returns or set the url of the receiver. Returning only if any where supplied at creation, otherwise returns nil. Setting may be used for different purpose but try to supply a valid one since it is used for archiving the image as an object.
226 i = SCImage.new("http://www.google.com/intl/en_ALL/images/logo.gif");
233 if true, the receiver currently use the CoreImage model, possibly caching its data on GPU, if not the bitmap model. Set it to switch representation.
235 this method should never be used directly unless you know perfectly what you are doing. Since the SCImage will switch internally and manage itself the syncronization between representations.
238 METHOD::interpolation
239 get or set the level of interpolation used when rendering the image - it has not effect when the SCImage is accelerated. see link::#*interpolations:: for a valid range of values.
242 i = SCImage.new(SCDoc.helpSourceDir +/+ "images/vduck2.jpg");
244 i.interpolation; // get the image currrent interpolation mode
248 i.interpolation = 'none'; // experiment with interpolation modes
253 i.interpolation = 'low';
258 i.interpolation = 1; // same as 'low'
263 i.interpolation = 'high';
268 i.interpolation = 'default';
273 i.accelerated_(true);
274 i.interpolation = 'none'; // does not work on coreimage accelerated image
281 SUBSECTION::saving and archiving
284 write the SCImage to a file.
286 i = SCImage.new("/Library/Desktop Pictures/Ripples Blue.jpg");
288 i.write("~/Desktop/my_image.png");
291 // storeOn / asCompileString
292 i = SCImage.new("/Library/Desktop Pictures/Ripples Blue.jpg");
295 i.writeArchive("~/Desktop/my_image.scd".standardizePath);
300 Document.open("~/Desktop/my_image.scd".standardizePath);
302 i = Object.readArchive("~/Desktop/my_image.scd".standardizePath);
308 the location where to save it
311 (optional) format to use. see SCImage.formats for supported formats. If nil, it will get the format depending on the path extension.
313 SUBSECTION::rendering
316 plots the image in a SCWindow.
318 i = SCImage.new("/Library/Desktop Pictures/Ripples Blue.jpg");
322 w = i.plot(showInfo:false);
326 // other option - image will be automatically freed when closed
327 SCImage.new("/Library/Desktop Pictures/Ripples Blue.jpg").plot("Hello", freeOnClose:true);
331 the title of the SCWindow. may be nil.
334 the bounds of the SCWindow. may be nil.
336 ARGUMENT::freeOnClose
337 flag to tell if the SCWindow should free the SCImage when closed.
340 additional background to apply to the SCWindow. may be useful for artifacts due to alpha / compositing...
343 shows pixel coordinates while the mouse is over the image's plot window.
346 sets the receiver as the current graphic context. So you can use SCPen to draw inside of it.
349 restore the graphic context state. the receiver is not anymore the current graphic context.
352 j = SCImage.new(400,300);
356 SCPen.translate(100, 100);
359 SCPen.color = Color.green(rrand(0.0, 1), rrand(0.0, 0.5));
360 SCPen.addAnnularWedge(
361 (100.rand)@(100.rand),
367 SCPen.perform([\stroke, \fill].choose);
374 j.write("~/Desktop/my_drawing.png"); // write the image
379 shortcut for drawing inside an image. equivalent to :
381 ## receiver.lockFocus
383 ## receiver.unlockFocus
387 j = SCImage.new(400,300);
390 SCPen.translate(100, 100);
393 SCPen.color = Color.green(rrand(0.0, 1), rrand(0.0, 0.5));
394 SCPen.addAnnularWedge(
395 (100.rand)@(100.rand),
401 SCPen.perform([\stroke, \fill].choose);
403 }).plot(freeOnClose:true);
406 // String drawing support on the image
407 // drawStringAtPoint(string, point, font, color);
409 j = SCImage.new(150,50);
411 j.drawStringAtPoint("Hello, world!", 10@10, Font("Lucida Grande", 24), Color.black);
416 j.write("~/Desktop/hello.png");
420 METHOD::drawStringAtPoint
421 renders *correctly* a String inside an SCImage :) code::// to fix to have a compliant interface::
424 var width, height, tgHeight, ratio, str, font, color, strb, targetWidth=400, shadowColor, run = true;
425 shadowColor = Color.black;
427 color = Color.gray(0.8);
428 str = "I Love Pixels";
429 font = Font("Monaco", 10);
430 strb = str.bounds(font);
432 height = strb.height;
433 ratio = height / width;
434 i = SCImage(width@(height));
436 SCPen.smoothing_(false);
437 i.drawStringAtPoint(str, 0@0, font, color);
439 i.interpolation_(\none);
440 tgHeight = targetWidth * ratio;
441 w = SCWindow.new("", Rect(400,400, 450, 150)).drawFunc_({
442 SCPen.setShadow(2@2, 0.4, color:Color.red);
443 i.drawInRect(Rect(5,5,targetWidth, tgHeight));
446 w.view.background_(Color.white);
447 w.onClose_({run = false; i.free;});
453 render the image or a portion of it in the current graphic context.
456 var operation='sourceOver', fraction=1.0, i, w;
459 // "http://supercollider.sourceforge.net/theme/sc01/icon.supercollider.gif"
460 // SCDoc.helpSourceDir +/+ "images/duck_alpha.png"
461 SCDoc.helpSourceDir +/+ "images/Swamp.png"
464 w = SCWindow.new("SCImage", Rect(120, 400, 360, 180)).front;
466 SCSlider.new(w, Rect(10, 150, 150, 16))
473 SCPopUpMenu.new(w, Rect(170, 150, 100, 16))
474 .items_( SCImage.compositingOperations.collect({ arg i; i.asString }) )
477 operation = SCImage.compositingOperations.at(pm.value);
481 w.onClose_({ i.free }); // free the image when the window is closed
485 i.drawAtPoint(10@10, nil, operation, fraction);
492 the link::Classes/Point:: where to draw it
495 the portion of the SCImage to use
498 the compositing operation to use. code::'sourceOver':: is the default.
501 the opacity to use, ranging from 0.0 (fully transparent) to 1.0 (fully opaque)
504 render the image or a portion of it in a specified rectangle of the current graphic context. This may stretch the image depending on the destination rect.
508 // "http://supercollider.sourceforge.net/theme/sc01/icon.supercollider.gif"
509 SCDoc.helpSourceDir +/+ "images/icon.supercollider.png"
512 w = SCWindow.new("SCImage", Rect(120, 400, 360, 180)).front;
513 w.onClose_({ i.free }); // free the image when the window is closed
515 i.drawInRect(Rect(10,10,50,50), Rect(10,10,50,50), 2, 1.0); // only a section
521 the link::Classes/Rect:: where to draw it
524 the portion of the SCImage to use
527 the compositing operation to use. code::'sourceOver':: is the default.
530 the opacity to use, ranging from 0.0 (fully transparent) to 1.0 (fully opaque)
533 tile the image or a portion of it in a specified rectangle of the current graphic context. This may stretch the image depending on the destination rect.
537 // "http://supercollider.sourceforge.net/theme/sc01/icon.supercollider.gif"
538 SCDoc.helpSourceDir +/+ "images/icon.supercollider.png"
541 w = SCWindow.new("SCImage", Rect(120, 400, 360, 180)).front;
542 w.onClose_({ i.free }); // free the image when the window is closed
544 i.tileInRect(w.view.bounds, nil, 2, 1.0); // all image contents
550 the link::Classes/Rect:: where to draw it
553 the portion of the SCImage to use
556 the compositing operation to use. code::'sourceOver':: is the default.
558 Compositing operations are currently disabled for tileInRect
562 the opacity to use, ranging from 0.0 (fully transparent) to 1.0 (fully opaque)
564 SUBSECTION::Instance Methods / accessing and setting pixels
567 fill a pixel located at x @ y.
569 i = SCImage.color(60, 60, Color.blue(0.1,0.1));
571 i.setPixel([255,0,0,255].asRGBA, 0, 0); // setting red
573 ("pixel at 0 @ 0:"+i.getPixel(0,0).rgbaArray).postln;
577 ARGUMENT::rgbaInteger
578 an 32 bit link::Classes/Integer:: containing color information packed as 8bit RGBA
581 retrieve the pixel value at x @ y as a RGBA integer
583 // A simple example on how to manipulate pixels with SCImage
585 Integer.fromRGBA(255,0,0,255), // red
586 Integer.fromRGBA(0,255,0,255), // green
587 Integer.fromRGBA(0,0,255,255), // blue
588 Integer.fromRGBA(255,0,255,255) // purple
591 b[0].red; // 255 see Integer.red
592 b[0].green; // 0 see Integer.green
593 b[0].blue; // 0 see Integer.blue
594 b[0].alpha; // 255 see Integer.alpha
596 a = SCImage.new(b.size@1).pixels_(b).interpolation_(\none);
601 a.setPixel([255, 0, 255, 128].asRGBA /* create an Integer from 0-255 integer rgba value */, 0, 0).plot;
609 // now another important example
610 a.setPixel([255, 0, 255, 0].asRGBA, 1, 0).plot; // clear color -> alpha is 0
613 p.red; // you expect 255 but you get 0 ??? Why = because SCImage uses premultiplied color component value internally
614 // meaning all Red, Green, and Blue component are premultiplied by the alpha
615 // if alpha is 0 you get 0 back for all components.
621 p = a.getColor(1,0); // more explicit - but same here
625 fill the pixel located at x @ y with the specified strong::color::.
628 retrieve the pixel value at x @ y as a link::Classes/Color::.
631 retrieve or set all the pixels of the receiver.
633 Carefull: the returned Array is a link::Classes/Int32Array:: of size receiver.width * receiver.height containing all pixel values as 32bit Integer
637 an link::Classes/Int32Array:: of size receiver.width * receiver.height containing all pixel values as 32bit Integer
640 load all the pixels of the receiver in an array. it is better and faster to call this function instead of link::#-pixels:: if you plan to retrieve frequently the pixel data (since it won't allocate a new array everytime !)
642 // exec one line at a time
644 // "http://supercollider.sourceforge.net/theme/sc01/icon.supercollider.gif"
645 SCDoc.helpSourceDir +/+ "images/icon.supercollider.png"
648 // first grab the pixels
651 // do some mods - here invert
654 // reload directly in my array - do not need to call i.pixels again
661 the array that will be filled. Should be an link::Classes/Int32Array:: of size receiver.width * receiver.height.
664 the targeted rectangular region. (nil by default, meaning full size)
667 the start index of the array.
670 set the pixels in a specific portion of the receiver.
673 i = SCImage.new(20@20);
675 Int32Array.fill(i.width * i.height, {
676 Integer.fromRGBA(255.rand,127.rand,255.rand,255)
679 //i.interpolation_(\none); // uncomment to see the difference
680 w = i.plot(freeOnClose:true);
685 i = SCImage.color(50@50, Color.white);
687 Int32Array.fill(20*20,{Integer.fromRGBA(255.rand, 127.rand, 255.rand, 255)}),
690 i.interpolation_(\none); // uncomment to see the difference
691 w = i.plot(freeOnClose:true);
697 an link::Classes/Int32Array:: of size strong::rect::.width * strong::rect::.height containing all pixel values as 32bit Integer
700 a rectangle defining the portion to update in the receiver. By default strong::rect:: is nil, meaning full image size.
703 the array start index.
705 SUBSECTION::Instance Methods / Attributes for SCImageFilter support
707 see link::Classes/SCImageFilter:: for more info
710 apply an array of link::Classes/SCImageFilter:: to the image. this should be considered as an in place operation, meaning the SCImage is altered after it.
712 // ******** Built In CoreImage Generators ********
713 // Generators are not filters, they actually create an image but do not need an input image
714 // you just have to create an image of a new size
715 // ** The Simple Random Filter **
717 f = SCImageFilter.new(\CIRandomGenerator);
718 a = SCImage.new(500@500);
720 w = a.plot(freeOnClose:true, background:Color.black);
724 // ** The StarShine example **
726 var width=500, height=500, centerVector;
728 centerVector = [ width*0.5, height*0.5 ];
729 a = SCImage.new(500@500);
730 f = SCImageFilter.new(\CIStarShineGenerator);
732 f.center_(centerVector);
733 f.radius_(width*0.05);
734 f.color_(Color.blue);
737 f.crossOpacity_(-4.0);
740 w = a.plot(freeOnClose:true, background:Color.gray); // change background to see
744 // ** Starshine + Pixellate + ZoomBlur **
746 var width=500, height=500, centerVector;
748 centerVector = [ width*0.5, height*0.5 ];
749 a = SCImage.new(500@500);
751 f = SCImageFilter.new(\CIStarShineGenerator);
752 g = SCImageFilter.new(\CIPixellate);
753 h = SCImageFilter.new(\CIZoomBlur);
755 f.center_(centerVector);
756 f.radius_(width*0.05);
757 f.color_(Color.blue);
760 f.crossOpacity_(-4.0);
761 g.center_(centerVector);
762 h.center_(centerVector);
765 a.applyFilters([f, g, h]);
766 w = a.plot(freeOnClose:true, background:Color.black);
771 a SCImageFilter or an array of link::Classes/SCImageFilter:: to be applied
774 the crop region to finally use. This may be required for extending bounds since some SCImageFilter / CoreImageFilters require to set a wider region (to be applied correctly) or may create a huge image. Setting crop to nil sets no crop region. In case the current maximum size of a filtered SCImage is 4096 / 4096. Any larger size will be clipped. by default crop is constrained to the receiver bounds.
778 supported only in Mac OS 10.5 and later.
780 option to constrain the filter to a specific region IN the SCImage.
783 returns a new SCImage, copy of the receiver filtered with an array of SCImageFilter. arguments are the same as link::#-applyFilters:: (except for strong::region::).
785 Beware: you are responsible for freeing the newly created SCImage !!!
789 filters is the instance variable that holds the array of SCImageFilter attached to the receiver. This is a convenient for applying filters out place and changing the SCImageFilter's attributes. see link::#-addFilter::, link::#-removeFilter::
791 see link::Classes/SCImageFilter:: for an example on how to use the strong::filters:: array.
794 you can also attach filters to the receiver for real-time changing operations. In this case the receiver will create a cache before each rendering to maintain his previous state, and allowing you to use filters without applying them in place. The cache is managed directly by the receiver. you can add several filters to the receiver, the first filter in the array is the first applied in the rendering chain.
796 see link::Classes/SCImageFilter:: for an example on how to use strong::addFilter::.
799 a SCImageFilter to apply before rendering of the image
803 see link::Classes/SCImageFilter:: for an example on how to use strong::removeFilter::.
806 the SCImageFilter to remove from the rendering chain.
809 if link::#-filters:: is not zero sized, this method will apply all those filters in place. if the image is accelerated this method force a bitmap representation of the receiver.
815 i = SCImage.new("/Library/Desktop Pictures/Ripples Blue.jpg");
817 i.plot(freeOnClose:true);
825 i = SCImage.new("/Library/Desktop Pictures/Ripples Blue.jpg");
826 i.crop( Rect(10,10,120,100) );
827 i.plot(freeOnClose:true);
834 SUBSECTION::Instance Methods / Attributes for SCImageKernel support
836 see link::Classes/SCImageKernel:: for examples and more info.
839 apply a Kernel in place. the receiver is modified after this call.
842 a link::Classes/SCImageKernel::
846 SUBSECTION::Views addition
848 you can now use a SCImage as a valid view background. 16 drawing modes are defined to behave differently.
851 ## tileMode values: ||
853 ## 1 || fixed to left, fixed to top
854 ## 2 || horizontally tile, fixed to top
855 ## 3 || fixed to right, fixed to top
856 ## 4 || fixed to left, vertically tile
857 ## 5 || horizontally tile, vertically tile
858 ## 6 || fixed to right, vertically tile
859 ## 7 || fixed to left, fixed to bottom
860 ## 8 || horizontally tile, fixed to bottom
861 ## 9 || fixed to right, fixed to bottom
863 ## 11 || center, center (scale)
864 ## 12 || center , fixed to top
865 ## 13 || center , fixed to bottom
866 ## 14 || fixed to left, center
867 ## 15 || fixed to right, center
868 ## 16 || center, center (no scale)
871 ## SCView:backgroundImage_ ||
873 strong::image:: - the SCImage to use
875 strong::tileMode:: - the mode to use. by default fixed to left, fixed to top
877 strong::alpha:: - opacity 0 < x < 1
879 strong::fromRect:: - the portion of the image to use. by default use the full image.
884 a = SCImage.new(SCDoc.helpSourceDir +/+ "images/vduck2.jpg");
885 r = Rect(20,3,40,40);
886 w = SCWindow.new("SCImage background" /*, textured:false*/ );
887 w.view.background_(Color.gray);
888 w.view.backgroundImage_(a, 5, b, r);
892 // monte carlo :) exec every line to test
893 // r = nil; // uncomment for full image
894 w.view.backgroundImage_(a, 1, b, r);
895 w.view.backgroundImage_(a, 2, b, r);
896 w.view.backgroundImage_(a, 3, b, r);
897 w.view.backgroundImage_(a, 4, b, r);
898 w.view.backgroundImage_(a, 5, b, r);
899 w.view.backgroundImage_(a, 6, b, r);
900 w.view.backgroundImage_(a, 7, b, r);
901 w.view.backgroundImage_(a, 8, b, r);
902 w.view.backgroundImage_(a, 9, b, r);
903 w.view.backgroundImage_(a, 10, b, r);
904 w.view.backgroundImage_(a, 11, b, r); // find best ratio - move to see
905 w.view.backgroundImage_(a, 12, b, r);
906 w.view.backgroundImage_(a, 13, b, r);
907 w.view.backgroundImage_(a, 14, b, r);
908 w.view.backgroundImage_(a, 15, b, r);
909 w.view.backgroundImage_(a, 16, b, r);
911 // this is safe even if window is still open because Background object holds the SCImage
917 a = SCImage.new("/Library/Desktop Pictures/Ripples Blue.jpg");
918 w = SCWindow.new("SCImage background");
919 l = SC2DSlider.new(w, Rect(10,10,200,200))
920 .backgroundImage_( a, 5, 1, Rect(0,0,10,10) );
926 var bounds = Rect(10,10,150,18);
927 a = SCImage.new("/Library/Desktop Pictures/Ripples Blue.jpg");
928 w = SCWindow.new("SCImage background");
929 l = SCSlider.new(w, bounds)
930 .backgroundImage_(a);