Jak mogę wziąć UIImage i nadać mu czarną ramkę?

126

Jak mogę ustawić granicę UIImage?

Shay
źródło
Przypadkiem, jeśli ktoś usłyszy w wyszukiwarce Google (tak jak ja) i szuka dodania obramowania do UIImageView, poszukaj odpowiedzi na dole @mclin. Działa świetnie!
Mahendra Liya

Odpowiedzi:

241

Z OS> 3.0 możesz to zrobić:

//you need this import
#import <QuartzCore/QuartzCore.h>

[imageView.layer setBorderColor: [[UIColor blackColor] CGColor]];
[imageView.layer setBorderWidth: 2.0];
mclin
źródło
1
Kiedy dopasowuję się do obrazów w powyższym imageView, obraz jest wyświetlany doskonale, ale boki obrazu pozostają puste, i to samo dzieje się z górną i dolną częścią obrazu, gdy obraz jest poziomy. Puste miejsce wygląda brzydko z ustawioną ramką. Czy napotkałeś ten problem? Jeśli tak, zaproponuj sposób rozwiązania tego problemu
Spotkaj się
@Hamutsi imageView.image = myImage;
Kyle Clegg
6
Tak, możesz. Instancje programu UIImagemożna wciągnąć w kontekst graficzny za pomocą programu CoreGraphics.
Mark Adams
Jak wskazuje @rockstar, może być konieczne dodanie imageView.layer.masksToBounds = YES;
Bjorn Roche
Ten link był rozwiązaniem, którego szukałem.
GrandSteph
67

Możesz to zrobić, tworząc nowy obraz (również w Twoim innym poście na to pytanie):

- (UIImage*)imageWithBorderFromImage:(UIImage*)source;
{
  CGSize size = [source size];
  UIGraphicsBeginImageContext(size);
  CGRect rect = CGRectMake(0, 0, size.width, size.height);
  [source drawInRect:rect blendMode:kCGBlendModeNormal alpha:1.0];

  CGContextRef context = UIGraphicsGetCurrentContext();
  CGContextSetRGBStrokeColor(context, 1.0, 0.5, 1.0, 1.0); 
  CGContextStrokeRect(context, rect);
  UIImage *testImg =  UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();
  return testImg;
}  

Ten kod spowoduje powstanie różowej ramki wokół obrazu. Jeśli jednak zamierzasz po prostu wyświetlić obramowanie, użyj warstwy UIImageViewi ustaw jej obramowanie.

Marcus S. Zarra
źródło
Jak określić szerokość żądanej granicy?
Patrick
16
CGContextSetLineWidth
Marcus S. Zarra
@ MarcusS.Zarra Zdaję sobie sprawę, że nie istniały, kiedy udzielono odpowiedzi na to pytanie, ale to rozwiązanie nie bierze pod uwagę wyświetlacza Retina. Gdybyś mógł to poprawić, byłbym naprawdę wdzięczny :)
Luke
@lukech Próbka nie musi być poprawiana. Po prostu zwiększ szerokość linii, jeśli korzystasz z urządzenia siatkówkowego.
Marcus S. Zarra
2
sizeTo 320x480, niezależnie od tego, czy jesteś na urządzeniu Retina, więc po zapisaniu obrazu, zapisuje w rozdzielczości 320x480px tego, a nie 640x960.
Luke
38
#import <QuartzCore/CALayer.h>


UIImageView *imageView = [UIImageView alloc]init];
imageView.layer.masksToBounds = YES;
imageView.layer.borderColor = [UIColor blackColor].CGColor;
imageView.layer.borderWidth = 1;    

Ten kod może służyć do dodawania UIImageViewobramowania widoku.

Faizan Refai
źródło
idealny! Nie ma potrzeby przechodzenia przez kłopoty z CGImage. (Nie musiałem zapisywać obrazu z ramką). Wielkie dzięki!
Septronic
13
imageView_ProfileImage.layer.cornerRadius =10.0f;
imageView_ProfileImage.layer.borderColor = [[UIColor blackColor] CGColor];
imageView_ProfileImage.layer.borderWidth =.4f;
imageView_ProfileImage.layer.masksToBounds = YES;
Bijendra Singh
źródło
Świetny hack, zwłaszcza jeśli chodzi o zużycie pamięci - inne odpowiedzi zajmą 2x pamięć, aby na chwilę dodać tę granicę. Porada dla profesjonalistów - jeśli chcesz po prostu dodać obramowanie po jednej stronie, możesz też zmienić granice. Świetna odpowiedź!
judepereira
11

Jeśli znasz wymiary swojego obrazu, to dodanie obramowania do warstwy UIImageView jest najlepszym rozwiązaniem AFAIK. Rzeczywiście, możesz po prostu ustawić ramkę dla swojego imageView na x, y, image.size.width, image.size.height

Jeśli masz ImageView o stałym rozmiarze z dynamicznie ładowanymi obrazami, które są zmieniane (lub skalowane do AspectFit), Twoim celem jest zmiana rozmiaru widoku obrazu na nowy obraz o zmienionym rozmiarze.

Najkrótszy sposób, aby to zrobić:

// containerView is my UIImageView
containerView.layer.borderWidth = 7;
containerView.layer.borderColor = [UIColor colorWithRed:0.22 green:0.22 blue:0.22 alpha:1.0].CGColor;

// this is the key command
[containerView setFrame:AVMakeRectWithAspectRatioInsideRect(image.size, containerView.frame)];

Ale aby użyć AVMakeRectWithAspectRatioInsideRect, musisz to dodać

#import <AVFoundation/AVFoundation.h>

import do pliku, a także uwzględnij strukturę AVFoundation w swoim projekcie (dostarczana w pakiecie z SDK).

ScorpionKing2k5
źródło
Dzięki @rafinskipg! Bardzo cenione.
ScorpionKing2k5
8

Nie możesz dodać obramowania, ale działałoby to z tym samym efektem. Możesz również utworzyć UIView o nazwie blackBG w tym przykładzie w UIImageView z obrazem obramowania i pustym środkiem, a wtedy miałbyś niestandardowe obramowanie obrazu zamiast tylko czarnego.

UIView *blackBG = [[UIView alloc] initWithFrame:CGRectMake(0,0,100,100)];

blackBG.backgroundColor = [UIColor blackColor];

UIImageView *myPicture = [[UIImageView alloc] initWithImage:
                          [UIImage imageNamed: @"myPicture.jpg"]];

int borderWidth = 10;

myPicture.frame = CGRectMake(borderWidth,
                             borderWidth,
                             blackBG.frame.size.width-borderWidth*2,
                             blackBG.frame.size.height-borderWidth*2)];

[blackBG addSubview: myPicture];
Andrew Johnson
źródło
Oto, co ostatecznie zrobiłem; zagnieżdżając mój UIImageVieww środku nieco większego UIViewkoloru mojej ramy.
Ben Kreeger
6

wszystkie te odpowiedzi działają dobrze, ALE dodaj prostokąt do obrazu. Załóżmy, że masz kształt (w moim przypadku motyl) i chcesz dodać obramowanie (czerwoną ramkę):

potrzebujemy dwóch kroków: 1) weź obraz, przekonwertuj go na CGImage, przejdź do funkcji rysującej poza ekranem w kontekście za pomocą CoreGraphics i oddaj nowy CGImage

2) przekonwertuj na uiimage z powrotem i narysuj:

// remember to release object!
+ (CGImageRef)createResizedCGImage:(CGImageRef)image toWidth:(int)width
andHeight:(int)height
{
// create context, keeping original image properties
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, width,
                                             height,
                                             8
                                             4 * width,
                                             colorspace,
                                             kCGImageAlphaPremultipliedFirst
                                             );

 CGColorSpaceRelease(colorspace);

if(context == NULL)
    return nil;

// draw image to context (resizing it)
CGContextSetInterpolationQuality(context, kCGInterpolationDefault);

CGSize offset = CGSizeMake(2,2);
CGFloat blur = 4;   
CGColorRef color = [UIColor redColor].CGColor;
CGContextSetShadowWithColor ( context, offset, blur, color);

CGContextDrawImage(context, CGRectMake(0, 0, width, height), image);
// extract resulting image from context
CGImageRef imgRef = CGBitmapContextCreateImage(context);
CGContextRelease(context);
return imgRef;

}

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

CGRect frame = CGRectMake(0,0,160, 122);
UIImage * img = [UIImage imageNamed:@"butterfly"]; // take low res OR high res, but frame should be the low-res one.
imgV = [[UIImageView alloc]initWithFrame:frame];
[imgV setImage: img];
imgV.center = self.view.center;
[self.view addSubview: imgV];

frame.size.width = frame.size.width * 1.3;
frame.size.height = frame.size.height* 1.3;
CGImageRef cgImage =[ViewController createResizedCGImage:[img CGImage] toWidth:frame.size.width andHeight: frame.size.height ];

imgV2 = [[UIImageView alloc]initWithFrame:frame];
[imgV2 setImage: [UIImage imageWithCGImage:cgImage] ];

// release:
if (cgImage) CGImageRelease(cgImage);

[self.view addSubview: imgV2];

}

Dodałem zwykłego motyla i większego motyla z czerwoną obwódką.

ingconti
źródło
czy istnieje sposób, aby ustawić tutaj szerokość czerwonej ramki.
coder1010
5

Możesz dodać obramowanie do UIImageView, a następnie zmienić rozmiar UIimageView zgodnie z rozmiarem obrazu:

#import <QuartzCore/QuartzCore.h>


// adding border to the imageView
[imageView.layer setBorderColor: [[UIColor whiteColor] CGColor]];
[imageView.layer setBorderWidth: 2.0];

// resize the imageView to fit the image size
CGSize size = [image size];
float factor = size.width / self.frame.size.width;
if (factor < size.height / self.frame.size.height) {
    factor = size.height / self.frame.size.height;
}

CGRect rect = CGRectMake(0, 0, size.width/factor, size.height/factor);
imageView.frame = rect;

Upewnij się, że ustawiłeś początek imageView na środek

biegunB
źródło
2

Możesz manipulować samym obrazem, ale znacznie lepszym sposobem jest po prostu dodanie UIView, który zawiera UIImageView, i zmiana tła na czarne. Następnie ustaw rozmiar tego widoku kontenera na nieco większy niż UIImageView.

Kendall Helmstetter Gelner
źródło
Czy będzie działać z różnymi rozmiarami obrazów, które zmieniają się w locie? UIImageView będzie się zmieniać przez cały czas, a UIView? ps Manipulowanie samym obrazem będzie świetne.
Shay
Będziesz musiał dostosować ramkę widoku zawierającego wraz z obrazem - możesz zapisać środkowe właściwości dla obu widoków, dostosować rozmiar obrazu, dostosować rozmiar kontenera, a następnie ponownie ustawić właściwości środkowe dla obu.
Kendall Helmstetter Gelner
Dokładnie tak to zrobiłem, w przeciwieństwie do wytyczania ścieżki za pomocą CG. po prostu wydawało się łatwiejsze.
Corey Floyd
2

Innym sposobem jest zrobienie tego bezpośrednio od projektanta.

Wybierz swój obraz i przejdź do „Pokaż inspektora tożsamości”.

Tutaj możesz ręcznie dodać „ Atrybuty środowiska wykonawczego zdefiniowane przez użytkownika” :

layer.borderColor
layer.borderWidth


wprowadź opis obrazu tutaj

Luca Davanzo
źródło
1
To nie zadziała, ponieważ potrzebujesz CGColor, a dzięki XIB zapewnia tylko UIColor
Codesnooker
Kolor nie zadziała, ale jeśli potrzebujesz tylko czarnego - to jest najbardziej „wierszy kodu” wydajna odpowiedź = D
soprof.
1

// musisz zaimportować

QuartzCore/QuartzCore.h

a następnie dla ImageView w obramowaniu

[imageView.layer setBorderColor: [[UIColor blackColor] CGColor]];

[imageView.layer setBorderWidth: 2.0];

[imageView.layer setCornerRadius: 5.0];
Panky
źródło
1

Ta funkcja zwróci obraz z czarną ramką. Spróbuj tego ... mam nadzieję, że to ci pomoże

- (UIImage *)addBorderToImage:(UIImage *)image frameImage:(UIImage *)blackBorderImage
{
    CGSize size = CGSizeMake(image.size.width,image.size.height);
    UIGraphicsBeginImageContext(size);

    CGPoint thumbPoint = CGPointMake(0,0);

    [image drawAtPoint:thumbPoint];


    UIGraphicsBeginImageContext(size);
    CGImageRef imgRef = blackBorderImage.CGImage;
    CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, size.width,size.height), imgRef);
    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    CGPoint starredPoint = CGPointMake(0, 0);
    [imageCopy drawAtPoint:starredPoint];
    UIImage *imageC = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return imageC;
}
SachinVsSachin
źródło
Jeśli znalazłeś jakieś glicery, daj mi znać ...
poprawię
1

W Swift 3 oto jak to zrobić z samym UIImage:

let size = CGSize(width: image.size.width, height: image.size.height)
UIGraphicsBeginImageContext(size)
let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
image?.draw(in: rect, blendMode: .normal, alpha: 1.0)
let context = UIGraphicsGetCurrentContext()
context?.setStrokeColor(red: 0, green: 0, blue: 0, alpha: 1)
context?.stroke(rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

self.imageView.image = newImage
CodyMace
źródło
1

Dla tych, którzy szukają rozwiązania typu plug-and-play na UIImage, napisałem odpowiedź CodyMace jako rozszerzenie.

Stosowanie: let outlined = UIImage(named: "something")?.outline()

extension UIImage {

    func outline() -> UIImage? {

        let size = CGSize(width: self.size.width, height: self.size.height)
        UIGraphicsBeginImageContext(size)
        let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        self.draw(in: rect, blendMode: .normal, alpha: 1.0)
        let context = UIGraphicsGetCurrentContext()
        context?.setStrokeColor(red: 0, green: 0, blue: 0, alpha: 1)
        context?.stroke(rect)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage

    }

}
Mavrick Laakso
źródło
0

Stworzyłem klasę, która dodaje obramowanie do imageView h. Użyj tej klasy zamiast UIImageView. Podałem dopełnienie 4. Możesz podać według własnego uznania.

class UIBorderImageView: UIView {

private lazy var imageView: UIImageView = {
    let imageView = UIImageView()
    imageView.contentMode = .scaleAspectFit
    imageView.translatesAutoresizingMaskIntoConstraints = false
    return imageView
}()

override init(frame: CGRect) {
    super.init(frame: frame)
    self.backgroundColor = UIColor.White()
    self.layer.borderColor = UIColor.GreyMedium().cgColor
    self.layer.borderWidth = 1.0
    self.layer.cornerRadius = 4.0
    self.layer.masksToBounds = true
    self.setUpViews()
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

private func setUpViews(){
    self.addSubview(imageView)
    self.addConstraintsWithFormat(format: "H:|-4-[v0]-4-|", views: imageView)
    self.addConstraintsWithFormat(format: "V:|-4-[v0]-4-|", views: imageView)
}

func configureImageViewWith(image:UIImage){
    self.imageview.image = image 
}}
Pranav Gupta
źródło
-1

Używam tej metody, aby dodać obramowanie poza obrazem . Możesz dostosować boderWidthstałą szerokość obramowania .

Szybki 3

func addBorderToImage(image : UIImage) -> UIImage {
    let bgImage = image.cgImage
    let initialWidth = (bgImage?.width)!
    let initialHeight = (bgImage?.height)!
    let borderWidth = Int(Double(initialWidth) * 0.10);
    let width = initialWidth + borderWidth * 2
    let height = initialHeight + borderWidth * 2
    let data = malloc(width * height * 4)

    let context = CGContext(data: data,
                        width: width,
                        height: height,
                        bitsPerComponent: 8,
                        bytesPerRow: width * 4,
                        space: (bgImage?.colorSpace)!,
                        bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue);

    context?.draw(bgImage!, in: CGRect(x: CGFloat(borderWidth), y: CGFloat(borderWidth), width: CGFloat(initialWidth), height: CGFloat(initialHeight)))
    context?.setStrokeColor(UIColor.white.cgColor)
    context?.setLineWidth(CGFloat(borderWidth))
    context?.move(to: CGPoint(x: 0, y: 0))
    context?.addLine(to: CGPoint(x: 0, y: height))
    context?.addLine(to: CGPoint(x: width, y: height))
    context?.addLine(to: CGPoint(x: width, y: 0))
    context?.addLine(to: CGPoint(x: 0, y: 0))
    context?.strokePath()

    let cgImage = context?.makeImage()
    let uiImage = UIImage(cgImage: cgImage!)

    free(data)

    return uiImage;
}
Miguel Isla
źródło