Class: UIImage
- Defined in:
- lib/sugarcube-image/uiimage.rb,
lib/sugarcube-568/uiimage.rb,
lib/sugarcube-pipes/pipes.rb,
lib/sugarcube-color/uiimage.rb,
lib/sugarcube-uikit/uiimage.rb,
lib/sugarcube-nsdata/uiimage.rb
Overview
Constant Summary collapse
- SugarCube568_TallSuffix =
'-568h@2x'
Class Method Summary collapse
-
.canvas(options_or_size = {}, more_options = {}, &block) ⇒ Object
Easily create a UIImage by using this factory method, and do your drawing in a block.
-
.imageNamed(name) ⇒ Object
now we've got imageNamed568 and imageNamed_old to load the respective versions.
- .imageNamed568(name) ⇒ Object
- .imageNamed_old ⇒ Object
Instance Method Summary collapse
-
#<<(image) ⇒ Object
Merges the two images.
-
#alignment_rect(insets = UIEdgeInsetsZero) ⇒ Object
| | imageWithAlignmentRectInsets |.
-
#apply_filter(filter) ⇒ Object
Returns a CIImage with the filter applied to the receiver.
- #at_scale(scale) ⇒ Object
- #avg_color ⇒ Object
-
#canvas(options_or_size = {}, more_options = {}, &block) ⇒ Object
the first argument can be a size, or an options dict.
-
#cgimage ⇒ Object
Returns a CGImageRef.
-
#ciimage ⇒ Object
Returns a CIImage.
-
#color_at(point) ⇒ Object
Oddly enough, this method doesn't seem to have retina support.
-
#crop(rect) ⇒ Object
Returns a cropped UIImage.
-
#darken(options = {}) ⇒ Object
Accepts two options: brightness (default: 0.0) and saturation (default: 0.0) Returns a darkened version of the image.
-
#draw(options = {}, &block) ⇒ Object
Using the image as the background, you can use this method to draw anything on top, like text or other images.
-
#gaussian_blur(*args) ⇒ Object
Apply a gaussian filter.
-
#in_rect(rect) ⇒ UIImage
This method is used to crop an image.
-
#masked(mask_image) ⇒ Object
| | CGImageCreateWithMask | The mask image cannot have ANY transparency.
-
#merge(image, options = {}) ⇒ Object
Draw an image on top of the receiver.
-
#nsdata(format = :png, compression = 0.9) ⇒ NSData
An NSData object in PNG or JPG format.
-
#overlay(color) ⇒ Object
Apply a color overlay to the image (very practical with PNG button images).
-
#rotate(angle_or_direction) ⇒ Object
| | rotate images |.
-
#rounded(corner_radius = 5) ⇒ Object
| | image modifications |.
-
#scale_to(new_size, background: background) ⇒ UIImage
Scales an image to fit within the given size.
-
#scale_to_fill(new_size, position: position, scale: scale) ⇒ UIImage
Scales an image to fit within the given size, stretching one or both dimensions so that it completely fills the area.
-
#scale_within(new_size) ⇒ Object
This method is similar to
scale_to, except it doesn't pad the image, it just scales the image so that it will fit inside the new bounds. - #stretchable(insets = UIEdgeInsetsZero) ⇒ Object
-
#tileable(insets = UIEdgeInsetsZero) ⇒ Object
| | resizableImageWithCapInsets |.
- #uicolor(alpha = nil) ⇒ UIColor
- #uiimage ⇒ Object
- #uiimageview ⇒ UIImageView
-
#|(filter) ⇒ Object
Operator shorthand for
apply_filter, or coerces the image into other formats.
Class Method Details
.canvas(options_or_size = {}, more_options = {}, &block) ⇒ Object
Easily create a UIImage by using this factory method, and do your drawing in a block. The core graphics context will be passed to the block you provide. To create a canvas based on an image, use the instance method.
:size is required, :scale defaults to the screen scale, and :opaque is false by default.
The first argument can be a size, or an options dict
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/sugarcube-image/uiimage.rb', line 25 def canvas(={}, ={}, &block) if .is_a?(NSDictionary) = size = [:size] else = size = end raise ":size is required in #{self.name}##canvas" unless size scale = [:scale] || UIScreen.mainScreen.scale opaque = .fetch(:opaque, false) UIGraphicsBeginImageContextWithOptions(size, opaque, scale) block.call(UIGraphicsGetCurrentContext()) if block new_image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return new_image end |
.imageNamed(name) ⇒ Object
now we've got imageNamed568 and imageNamed_old to load the respective versions
28 29 30 |
# File 'lib/sugarcube-568/uiimage.rb', line 28 def imageNamed(name) imageNamed568(name) || imageNamed_old(name) end |
.imageNamed568(name) ⇒ Object
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/sugarcube-568/uiimage.rb', line 5 def imageNamed568(name) @may_use_taller_images ||= CGSizeEqualToSize(CGSizeMake(320, 568), UIScreen.mainScreen.bounds.size) if ( @may_use_taller_images && name.length > 0 && name.rangeOfString(SugarCube568_TallSuffix).location == NSNotFound ) # Check if is there a path extension or not test_name = name; if test_name.pathExtension.length > 0 test_name = test_name.stringByDeletingPathExtension.stringByAppendingString(SugarCube568_TallSuffix).stringByAppendingPathExtension(name.pathExtension) else test_name = test_name.stringByAppendingString(SugarCube568_TallSuffix + ".png") end image = imageNamed_old(test_name) if image return self.imageWithCGImage(image.CGImage, scale:2.0, orientation:image.imageOrientation) end end return nil end |
.imageNamed_old ⇒ Object
25 |
# File 'lib/sugarcube-568/uiimage.rb', line 25 alias :imageNamed_old :imageNamed |
Instance Method Details
#<<(image) ⇒ Object
Merges the two images. The target is drawn first, image is drawn on top.
The two images are centered, and the maximum size is used so that both
images fit on the canvas.
49 50 51 |
# File 'lib/sugarcube-image/uiimage.rb', line 49 def <<(image) self.merge(image, at: :center, stretch: true) end |
#alignment_rect(insets = UIEdgeInsetsZero) ⇒ Object
516 517 518 |
# File 'lib/sugarcube-image/uiimage.rb', line 516 def alignment_rect(insets=UIEdgeInsetsZero) imageWithAlignmentRectInsets(insets) end |
#apply_filter(filter) ⇒ Object
Returns a CIImage with the filter applied to the receiver. The return value
is a CIImage object, which also defines | to work the same way, so filters
can be chained.
401 402 403 404 |
# File 'lib/sugarcube-image/uiimage.rb', line 401 def apply_filter(filter) filter.setValue(self.ciimage, forKey: 'inputImage') return filter.valueForKey('outputImage') end |
#at_scale(scale) ⇒ Object
599 600 601 602 603 604 605 606 607 608 609 610 611 612 |
# File 'lib/sugarcube-image/uiimage.rb', line 599 def at_scale(scale) if scale == self.scale return self end new_size = self.size new_size.width = new_size.width * self.scale / scale new_size.height = new_size.height * self.scale / scale return self.canvas(size: new_size, scale: scale) do thumbnail_rect = CGRect.new([0, 0], new_size) self.drawInRect(thumbnail_rect) end end |
#avg_color ⇒ Object
577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 |
# File 'lib/sugarcube-image/uiimage.rb', line 577 def avg_color colorSpace = CGColorSpaceCreateDeviceRGB() rgba = Pointer.new(:uchar, 4) context = CGBitmapContextCreate(rgba, 1, 1, 8, 4, colorSpace, KCGImageAlphaPremultipliedLast | KCGBitmapByteOrder32Big) CGContextDrawImage(context, CGRectMake(0, 0, 1, 1), self.CGImage) if rgba[3] > 0 alpha = rgba[3] / 255.0 multiplier = alpha / 255.0 return UIColor.colorWithRed(rgba[0] * multiplier, green:rgba[1] * multiplier, blue:rgba[2] * multiplier, alpha:alpha) else return UIColor.colorWithRed(rgba[0] / 255.0, green:rgba[1] / 255.0, blue:rgba[2] / 255.0, alpha:rgba[3] / 255.0) end end |
#canvas(options_or_size = {}, more_options = {}, &block) ⇒ Object
the first argument can be a size, or an options dict
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 |
# File 'lib/sugarcube-image/uiimage.rb', line 625 def canvas(={}, ={}, &block) if .is_a?(NSDictionary) = else = [:size] = end unless [:size] [:size] = self.size end unless [:scale] = .merge(scale: self.scale) end self.class.canvas() do |context| block.call(context) if block end end |
#cgimage ⇒ Object
Returns a CGImageRef. Alias for CGImage.
407 408 409 |
# File 'lib/sugarcube-image/uiimage.rb', line 407 def cgimage return self.CGImage end |
#ciimage ⇒ Object
Returns a CIImage.
412 413 414 |
# File 'lib/sugarcube-image/uiimage.rb', line 412 def ciimage return CIImage.imageWithCGImage(self.CGImage) end |
#color_at(point) ⇒ Object
Oddly enough, this method doesn't seem to have retina support
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 |
# File 'lib/sugarcube-image/uiimage.rb', line 546 def color_at(point) point = SugarCube::CoreGraphics::Point(point) point.x *= self.scale point.y *= self.scale # First get the image into your data buffer cgimage = self.CGImage width = CGImageGetWidth(cgimage) height = CGImageGetHeight(cgimage) bytes_per_pixel = 4 bits_per_component = 8 bytes_per_row = bytes_per_pixel * width @raw_data || begin color_space = CGColorSpaceCreateDeviceRGB() @raw_data = Pointer.new(:uchar, height * width * 4) context = CGBitmapContextCreate(@raw_data, width, height, bits_per_component, bytes_per_row, color_space, KCGImageAlphaPremultipliedLast | KCGBitmapByteOrder32Big) CGContextDrawImage(context, CGRectMake(0, 0, width, height), cgimage) end # Now @raw_data contains the image data in the RGBA8888 pixel format. xx = point.x.round yy = point.y.round byte_index = (bytes_per_row * yy) + xx * bytes_per_pixel red = @raw_data[byte_index] green = @raw_data[byte_index + 1] blue = @raw_data[byte_index + 2] alpha = @raw_data[byte_index + 3] return [red, green, blue].uicolor(alpha / 255.0) end |
#crop(rect) ⇒ Object
Returns a cropped UIImage. The easiest way is to check for a CGImage backing, but if this image uses a CIImage backing, we draw a new (cropped) image.
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/sugarcube-image/uiimage.rb', line 121 def crop(rect) rect = SugarCube::CoreGraphics::Rect(rect) if self.CGImage if self.scale > 1.0 rect = CGRectMake(rect.origin.x * self.scale, rect.origin.y * self.scale, rect.size.width * self.scale, rect.size.height * self.scale) end cgimage = CGImageCreateWithImageInRect(self.CGImage, rect) return UIImage.imageWithCGImage(cgimage, scale:self.scale, orientation:self.imageOrientation) else return self.canvas(size: rect.size) do |context| self.drawAtPoint(CGPoint.new(-rect.origin.x, -rect.origin.y)) end end end |
#darken(options = {}) ⇒ Object
Accepts two options: brightness (default: 0.0) and saturation (default: 0.0) Returns a darkened version of the image.
418 419 420 421 422 423 424 425 426 427 |
# File 'lib/sugarcube-image/uiimage.rb', line 418 def darken(={}) = { 'inputSaturation' => [:saturation] || 0, 'inputBrightness' => [:brightness] || 0, } darken_filter = CIFilter.color_controls() output = self.apply_filter(darken_filter) return UIImage.imageWithCIImage(output, scale:self.scale, orientation:self.imageOrientation) end |
#draw(options = {}, &block) ⇒ Object
Using the image as the background, you can use this method to draw anything on top, like text or other images.
616 617 618 619 620 621 622 |
# File 'lib/sugarcube-image/uiimage.rb', line 616 def draw(={}, &block) at = [:at] || [0, 0] return self.canvas() do |context| self.drawAtPoint(at) block.call(context) if block end end |
#gaussian_blur(*args) ⇒ Object
Apply a gaussian filter
435 436 437 438 |
# File 'lib/sugarcube-image/uiimage.rb', line 435 def gaussian_blur(*args) output = self.apply_filter(CIFilter.gaussian_blur(*args)) return UIImage.imageWithCIImage(output, scale:self.scale, orientation:self.imageOrientation) end |
#in_rect(rect) ⇒ UIImage
This method is used to crop an image. Scale (retina or non-retina) is preserved.
148 149 150 151 152 153 |
# File 'lib/sugarcube-image/uiimage.rb', line 148 def in_rect(rect) imageRef = CGImageCreateWithImageInRect(self.CGImage, rect) sub_image = UIImage.imageWithCGImage(imageRef, scale:self.scale, orientation:self.imageOrientation) return sub_image end |
#masked(mask_image) ⇒ Object
The mask image cannot have ANY transparency. Instead, transparent areas must be white or some value between black and white. The more white a pixel is the more transparent it becomes. black .. white opaque .. transparent
528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 |
# File 'lib/sugarcube-image/uiimage.rb', line 528 def masked(mask_image) mask_image = mask_image.CGImage width = CGImageGetWidth(mask_image) height = CGImageGetHeight(mask_image) component_bits = CGImageGetBitsPerComponent(mask_image) pixel_bits = CGImageGetBitsPerPixel(mask_image) row_bytes = CGImageGetBytesPerRow(mask_image) data_provider = CGImageGetDataProvider(mask_image) mask = CGImageMaskCreate(width, height, component_bits, pixel_bits, row_bytes, data_provider,nil, false) masked = CGImageCreateWithMask(self.CGImage, mask) UIImage.imageWithCGImage(masked, scale:self.scale, orientation:self.imageOrientation) end |
#merge(image, options = {}) ⇒ Object
Draw an image on top of the receiver. The :at option provides either an
absolute location (Array or CGPoint) or relative location (Symbol, one of
:top_left, :top, :top_right, :left, :center (default), :right, :bottom_left,
:bottom, :bottom_right). The :stretch option increases the canvas so
there is room for both images, otherwise the target image's size is used.
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/sugarcube-image/uiimage.rb', line 58 def merge(image, ={}) image_position = .fetch(:at, :center) stretch = .fetch(:stretch, false) size = self.size if stretch if image.size.width > size.width size.width = image.size.width end if image.size.height > size.height size.height = image.size.height end end my_left = image_left = 0 my_top = image_top = 0 my_right = (size.width - self.size.width) my_bottom = (size.height - self.size.height) image_right = (size.width - image.size.width) image_bottom = (size.height - image.size.height) my_cx = my_right / 2.0 my_cy = my_bottom / 2.0 image_cx = image_right / 2.0 image_cy = image_bottom / 2.0 case image_position when :top_left, :topleft, :tl my_position = [my_right, my_bottom] image_position = [image_left, image_top] when :top, :t my_position = [my_cx, my_bottom] image_position = [image_cx, image_top] when :top_right, :topright, :tr my_position = [my_left, my_bottom] image_position = [image_right, image_top] when :left, :l my_position = [my_right, my_cy] image_position = [image_left, image_cy] when :center, :c my_position = [my_cx, my_cy] image_position = [image_cx, image_cy] when :right, :r my_position = [my_left, my_cy] image_position = [image_right, image_cy] when :bottom_left, :bottomleft, :bl my_position = [my_right, my_top] image_position = [image_left, image_bottom] when :bottom, :b my_position = [my_cx, my_top] image_position = [image_cx, image_bottom] when :bottom_right, :bottomright, :br my_position = [my_left, my_top] image_position = [image_right, image_bottom] end return self.draw(size: size, at: my_position) do image.drawAtPoint(image_position) end end |
#nsdata(format = :png, compression = 0.9) ⇒ NSData
Returns an NSData object in PNG or JPG format.
4 5 6 7 8 9 10 11 |
# File 'lib/sugarcube-nsdata/uiimage.rb', line 4 def nsdata(format=:png, compression=0.9) case format when :png, :PNG UIImagePNGRepresentation(self) when :jpg, :JPG UIImageJPEGRepresentation(self, compression) end end |
#overlay(color) ⇒ Object
Apply a color overlay to the image (very practical with PNG button images)
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 |
# File 'lib/sugarcube-image/uiimage.rb', line 444 def (color) image_rect = CGRectMake(0, 0, self.size.width, self.size.height) UIImage.canvas(size: self.size, scale: self.scale) do |ctx| self.drawInRect(image_rect) CGContextSetFillColorWithColor(ctx, color.uicolor.CGColor) CGContextSetAlpha(ctx, 1) CGContextSetBlendMode(ctx, KCGBlendModeSourceAtop) CGContextFillRect(ctx, image_rect) image_ref = CGBitmapContextCreateImage(ctx) new_image = UIImage.imageWithCGImage(image_ref, scale:self.scale, orientation:self.imageOrientation) end return new_image end |
#rotate(angle_or_direction) ⇒ Object
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 |
# File 'lib/sugarcube-image/uiimage.rb', line 465 def rotate(angle_or_direction) case angle_or_direction when :left radian = -90.degrees when :right radian = 90.degrees when :flip radian = 180.degrees when Numeric radian = angle_or_direction else raise "Unknown angle/direction #{angle_or_direction.inspect}" end w = (self.size.width * Math.cos(radian)).abs + (self.size.height * Math.sin(radian)).abs h = (self.size.height * Math.cos(radian)).abs + (self.size.width * Math.sin(radian)).abs new_size = CGSize.new(w, h) new_size = self.size return self.canvas(size: new_size) do |context| # Move the origin to the middle of the image so we will rotate and scale around the center. CGContextTranslateCTM(context, new_size.width / 2, new_size.height / 2) # Rotate the image context CGContextRotateCTM(context, radian) # otherwise it'll be upside down: CGContextScaleCTM(context, 1.0, -1.0) # Now, draw the rotated/scaled image into the context CGContextDrawImage(context, CGRectMake(-new_size.width / 2, -new_size.height / 2, new_size.width, new_size.height), self.CGImage) end end |
#rounded(corner_radius = 5) ⇒ Object
386 387 388 389 390 391 392 |
# File 'lib/sugarcube-image/uiimage.rb', line 386 def rounded(corner_radius=5) return self.canvas do path = UIBezierPath.bezierPathWithRoundedRect([[0, 0], size], cornerRadius:corner_radius) path.addClip self.drawInRect([[0, 0], size]) end end |
#scale_to(new_size, background: background) ⇒ UIImage
Scales an image to fit within the given size. Its current aspect ratio is maintained, but the image is padded so that it fills the entire area. If the image is too small, it will be scaled up to fit. If you specify a background that color will be used, otherwise the background will be transparent.
306 307 308 |
# File 'lib/sugarcube-image/uiimage.rb', line 306 def scale_to(new_size) scale_to(new_size, background:nil) end |
#scale_to_fill(new_size, position: position, scale: scale) ⇒ UIImage
Scales an image to fit within the given size, stretching one or both dimensions so that it completely fills the area. The current aspect ratio is maintained. If you want to place an image inside a container image, this is the method to use.
You can specify a position property, which can be a symbol or a point. It
specifies where you want the image located if it has to be cropped.
Specifying the top-left corner will display the top-left corner of the
image, likewise specifing the bottom-right corner will display that
corner. If you want the image centered, you can use the 'position-less'
version of this method (scale_to_fit()) or specify the point at the center
of the image (scale_to_fit(size, position:[w/2, h/2])), or use a symbol
(scale_to_fit(size, position: :center)).
@param scale [Numeric] image scale
156 157 158 |
# File 'lib/sugarcube-image/uiimage.rb', line 156 def scale_to_fill(new_size) scale_to_fill(new_size, position: :center) end |
#scale_within(new_size) ⇒ Object
This method is similar to scale_to, except it doesn't pad the image, it
just scales the image so that it will fit inside the new bounds.
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 |
# File 'lib/sugarcube-image/uiimage.rb', line 274 def scale_within(new_size) target_size = SugarCube::CoreGraphics::Size(new_size) image_size = self.size if CGSizeEqualToSize(target_size, self.size) return self end width = image_size.width height = image_size.height target_width = target_size.width target_height = target_size.height width_factor = target_width / width height_factor = target_height / height if width_factor < height_factor scale_factor = width_factor else scale_factor = height_factor end if scale_factor == 1 return self end scaled_size = CGSize.new(width * scale_factor, height * scale_factor) return scale_to(scaled_size) end |
#stretchable(insets = UIEdgeInsetsZero) ⇒ Object
507 508 509 510 511 |
# File 'lib/sugarcube-image/uiimage.rb', line 507 def stretchable(insets=UIEdgeInsetsZero) # not necessary, since we don't modify/examine the insets # insets = SugarCube::CoreGraphics::EdgeInsets(insets) resizableImageWithCapInsets(insets, resizingMode:UIImageResizingModeStretch) end |
#tileable(insets = UIEdgeInsetsZero) ⇒ Object
501 502 503 504 505 |
# File 'lib/sugarcube-image/uiimage.rb', line 501 def tileable(insets=UIEdgeInsetsZero) # not necessary, since we don't modify/examine the insets # insets = SugarCube::CoreGraphics::EdgeInsets(insets) resizableImageWithCapInsets(insets, resizingMode:UIImageResizingModeTile) end |
#uicolor(alpha = nil) ⇒ UIColor
4 5 6 7 8 9 10 11 |
# File 'lib/sugarcube-color/uiimage.rb', line 4 def uicolor(alpha=nil) color = UIColor.colorWithPatternImage(self) if not alpha.nil? color = color.colorWithAlphaComponent(alpha.to_f) end color end |
#uiimage ⇒ Object
2 |
# File 'lib/sugarcube-uikit/uiimage.rb', line 2 def uiimage ; self ; end |
#uiimageview ⇒ UIImageView
5 6 7 |
# File 'lib/sugarcube-uikit/uiimage.rb', line 5 def uiimageview UIImageView.alloc.initWithImage(self) end |
#|(filter) ⇒ Object
Operator shorthand for apply_filter, or coerces the image into other
formats.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/sugarcube-pipes/pipes.rb', line 11 def |(filter) if CIFilter === filter apply_filter(filter) elsif filter == UIImage self elsif filter == UIView || filter == UIImageView self.uiimageview elsif filter == CIImage ciimage elsif filter == UIColor uicolor elsif filter == NSData nsdata else raise "The `|` operator is not supported for the #{filter.is_a?(Class) ? filter.name : filter.class.name} class" end end |