Class: UIImage

Inherits:
Object show all
Defined in:
lib/sugarcube/uiimage.rb,
lib/sugarcube-568/uiimage.rb

Constant Summary collapse

SugarCube568_TallSuffix =
'-568h@2x'

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.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_oldObject



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.



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/sugarcube/uiimage.rb', line 34

def <<(image)
  size = self.size
  if image.size.width > size.width
    size.width = image.size.width
  end
  if image.size.height > size.height
    size.height = image.size.height
  end

  UIGraphicsBeginImageContextWithOptions(size, false, self.scale)

  self_position = CGPoint.new((size.width - self.size.width) / 2, (size.width - self.size.width) / 2)
  self.drawAtPoint(self_position)

  image_position = CGPoint.new((size.width - image.size.width) / 2, (size.width - image.size.width) / 2)
  image.drawAtPoint(image_position)

  new_image = UIGraphicsGetImageFromCurrentImageContext()
  UIGraphicsEndImageContext()
  return new_image
end

#alignment_rect(insets = UIEdgeInsetsZero) ⇒ Object



406
407
408
# File 'lib/sugarcube/uiimage.rb', line 406

def alignment_rect(insets=UIEdgeInsetsZero)
  imageWithAlignmentRectInsets(insets)
end

#at_scale(scale) ⇒ Object



467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
# File 'lib/sugarcube/uiimage.rb', line 467

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

  UIGraphicsBeginImageContextWithOptions(new_size, false, scale)
  thumbnail_rect = CGRect.new([0, 0], new_size)

  self.drawInRect(thumbnail_rect)

  new_image = UIGraphicsGetImageFromCurrentImageContext()
  UIGraphicsEndImageContext()
  return new_image
end

#color_at(point) ⇒ Object

Oddly enough, this method doesn't seem to have retina support



436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
# File 'lib/sugarcube/uiimage.rb', line 436

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

#darken(options = {}) ⇒ Object

Accepts two options: brightness (default: -0.5) and saturation (default: -0.2) Returns a darkened version of the image.

Raises:

  • (Exception)


321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
# File 'lib/sugarcube/uiimage.rb', line 321

def darken(options={})
  filter_name = 'CIColorControls'
  filter_options = {
    inputBrightness: options[:brightness] || -0.5,
    inputSaturation: options[:saturation] || -0.2,
  }

  cg_input_image = CIImage.alloc.initWithImage(self)
  darken_filter = CIFilter.filterWithName(filter_name)
  raise Exception.new("Filter not found: #{filter_name}") unless darken_filter

  darken_filter.setDefaults
  darken_filter.setValue(cg_input_image, forKey:'inputImage')
  filter_options.each_pair do |key, value|
    darken_filter.setValue(value, forKey:key)
  end
  output = darken_filter.valueForKey('outputImage')

  context = CIContext.contextWithOptions(nil)
  cg_output_image = context.createCGImage(output, fromRect:output.extent)
  output_image = UIImage.imageWithCGImage(cg_output_image, scale:self.scale, orientation:self.imageOrientation)

  return output_image
end

#in_rect(rect) ⇒ UIImage

This method is used to crop an image. Scale (retina or non-retina) is preserved.

Parameters:

  • rect (CGRect)

    the portion of the image to return

Returns:



64
65
66
67
68
69
# File 'lib/sugarcube/uiimage.rb', line 64

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



418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
# File 'lib/sugarcube/uiimage.rb', line 418

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

#nsdataNSData

Returns an NSData object in PNG format.

Returns:

  • (NSData)

    an NSData object in PNG format



20
21
22
# File 'lib/sugarcube/uiimage.rb', line 20

def nsdata
  UIImagePNGRepresentation(self)
end

#rotate(angle_or_direction) ⇒ Object



349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
# File 'lib/sugarcube/uiimage.rb', line 349

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

  # Create the bitmap context
  UIGraphicsBeginImageContextWithOptions(new_size, false, self.scale)
  bitmap = UIGraphicsGetCurrentContext()

  # Move the origin to the middle of the image so we will rotate and scale around the center.
  CGContextTranslateCTM(bitmap, new_size.width / 2, new_size.height / 2)

  # Rotate the image context
  CGContextRotateCTM(bitmap, radian)

  # otherwise it'll be upside down:
  CGContextScaleCTM(bitmap, 1.0, -1.0)
  # Now, draw the rotated/scaled image into the context
  CGContextDrawImage(bitmap, CGRectMake(-new_size.width / 2, -new_size.height / 2, new_size.width, new_size.height), self.CGImage)

  new_image = UIGraphicsGetImageFromCurrentImageContext()
  UIGraphicsEndImageContext()
  return new_image
end

#rounded(corner_radius = 5) ⇒ Object



309
310
311
312
313
314
315
316
317
# File 'lib/sugarcube/uiimage.rb', line 309

def rounded(corner_radius=5)
  UIGraphicsBeginImageContextWithOptions(size, false, self.scale)
  path = UIBezierPath.bezierPathWithRoundedRect([[0, 0], size], cornerRadius:corner_radius)
  path.addClip
  self.drawInRect([[0, 0], size])
  new_image = UIGraphicsGetImageFromCurrentImageContext()
  UIGraphicsEndImageContext()
  return new_image
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.

Parameters:

  • new_size (CGSize)

    Maximum dimensions of desired image. The returned image is guaranteed to fit within these dimensions.

  • background (UIColor) (defaults to: background)

    Color to fill padded areas. Default is transparent.

Returns:



224
225
226
# File 'lib/sugarcube/uiimage.rb', line 224

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

Parameters:

  • new_size (CGSize)

    Minimum dimensions of desired image. The returned image is guaranteed to fit within these dimensions.

  • position (Symbol, CGPoint) (defaults to: position)

    Where to position the resized image. Valid symbols are: [:topleft, :top, :topright, :left, :center, :right, :bottomleft, :bottom, :bottomright] (if you forget and use an underscore, like top_left, that'll work, too)

Returns:



72
73
74
# File 'lib/sugarcube/uiimage.rb', line 72

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.



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/sugarcube/uiimage.rb', line 192

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



397
398
399
400
401
# File 'lib/sugarcube/uiimage.rb', line 397

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



391
392
393
394
395
# File 'lib/sugarcube/uiimage.rb', line 391

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

Returns:



5
6
7
8
9
10
11
12
# File 'lib/sugarcube/uiimage.rb', line 5

def uicolor(alpha=nil)
  color = UIColor.colorWithPatternImage(self)
  if not alpha.nil?
    color = color.colorWithAlphaComponent(alpha.to_f)
  end

  color
end

#uiimageObject



2
# File 'lib/sugarcube/uiimage.rb', line 2

def uiimage ; self ; end

#uiimageviewUIImageView

Returns:

  • (UIImageView)


15
16
17
# File 'lib/sugarcube/uiimage.rb', line 15

def uiimageview
  UIImageView.alloc.initWithImage(self)
end