จับภาพหน้าจอของพื้นที่เฉพาะโดยทางโปรแกรม

เช่นเดียวกับที่คุณเห็นในโค้ดของฉัน ฉันจะจับภาพหน้าจอและบันทึกลงในอัลบั้มรูป

//for retina displays
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
    UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, [UIScreen mainScreen].scale);
} else {
    UIGraphicsBeginImageContext(self.view.bounds.size);
}
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);

ในตอนแรกฉันใช้ webview.size แทน self.view.bounds.size และมันทำงานได้อย่างถูกต้องเนื่องจากมุมมองอยู่ที่ 0/0 แต่ตอนนี้ฉันจัด WebView ไว้ตรงกลาง แต่รูปภาพเริ่มต้นที่ 0/0 สำหรับขนาดที่กำหนด

ฉันจะกำหนดค่าให้ภาพหน้าจอเริ่มต้นที่ location อื่น (เช่น 300/150) สำหรับขนาดที่กำหนดได้อย่างไร

หรือมีวิธีอื่นในการถ่ายภาพ UIWebView?


person Sharky    schedule 02.01.2012    source แหล่งที่มา
comment
สิ่งนี้ใช้ได้กับเดสก์ท็อป OSX หรือแค่ iphone?   -  person Noitidart    schedule 07.05.2015


คำตอบ (4)


คุณต้องทำการเปลี่ยนแปลงสองครั้งเพื่อดึงเฉพาะบางส่วนของหน้าจอ:

  1. สร้างภาพให้เล็กลง - ใช้ขนาดของสี่เหลี่ยมที่คุณต้องการถ่าย
  2. ย้ายจุดกำเนิดของบริบทที่คุณแสดงผลเป็นค่าลบ x/y ของสี่เหลี่ยมที่คุณต้องการจับ

หลังจากนั้น คุณเพียงแค่แสดงเลเยอร์ให้เข้ากับบริบทในขณะที่คุณทำอยู่ และคุณควรจะได้สิ่งที่คุณกำลังมองหา สิ่งนี้ควรจะทำ:

CGRect grabRect = CGRectMake(40,40,300,200);

//for retina displays
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
    UIGraphicsBeginImageContextWithOptions(grabRect.size, NO, [UIScreen mainScreen].scale);
} else {
    UIGraphicsBeginImageContext(grabRect.size);
}
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(ctx, -grabRect.origin.x, -grabRect.origin.y);
[self.view.layer renderInContext:ctx];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);
person escrafford    schedule 08.03.2013
comment
สิ่งนี้ทำให้แอปของฉันขัดข้อง มีความคิดอะไรบ้างว่าทำไม? ฉันได้เพิ่มเฟรมเวิร์ก QuartzCore และใส่โค้ดนี้ในฟังก์ชัน แต่ก็ยังไม่สามารถทำได้ - person rebellion; 05.06.2013
comment
@rebellion - ฉันได้สิ่งนี้ไปแล้ว แม้จะไม่ได้อยู่ในอัลบั้มรูปก็ตาม ดูการปรับตัวของฉันด้านล่างเป็นวิธีการหมวดหมู่ UIView - person idStar; 21.06.2013
comment
ขอบคุณ มันใช้งานได้ดีสำหรับฉัน ปัญหาเล็กน้อยคือสีพื้นหลังของภาพเป็นสีขาว ฉันอยากให้มันโปร่งใส ฉันจะทำเช่นนั้นได้อย่างไร. กรุณาช่วย - person iMemon; 06.11.2013
comment
สีพื้นหลังของภาพเป็นสีขาวเนื่องจากฉันอัปโหลดภาพ jpeg แทนที่จะเป็นภาพ PNG รหัสด้านบนสมบูรณ์แบบ :) - person iMemon; 06.11.2013

ฉันได้ทดสอบและทดสอบคำตอบของ @ escrafford ข้างต้นแล้วและทำให้มันใช้งานได้ดี ฉันได้ทดสอบในบริบทของการทำให้มันเป็นวิธีการจัดหมวดหมู่บน UIView เพื่อให้สามารถกำหนดพารามิเตอร์ 'grabRect' ได้ นี่คือรหัสนั้นในฐานะหมวดหมู่ UIView ที่ส่งคืน UIImageView ให้คุณ:

/**
 Takes a screenshot of a UIView at a specific point and size, as denoted by
 the provided croppingRect parameter. Returns a UIImageView of this cropped
 region.

 CREDIT: This is based on @escrafford's answer at http://stackoverflow.com/a/15304222/535054
*/
- (UIImageView *)rp_screenshotImageViewWithCroppingRect:(CGRect)croppingRect {
    // For dealing with Retina displays as well as non-Retina, we need to check
    // the scale factor, if it is available. Note that we use the size of teh cropping Rect
    // passed in, and not the size of the view we are taking a screenshot of.
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
        UIGraphicsBeginImageContextWithOptions(croppingRect.size, YES, [UIScreen mainScreen].scale);
    } else {
        UIGraphicsBeginImageContext(croppingRect.size);
    }

    // Create a graphics context and translate it the view we want to crop so
    // that even in grabbing (0,0), that origin point now represents the actual
    // cropping origin desired:
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(ctx, -croppingRect.origin.x, -croppingRect.origin.y);
    [self.layer renderInContext:ctx];

    // Retrieve a UIImage from the current image context:
    UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    // Return the image in a UIImageView:
    return [[UIImageView alloc] initWithImage:snapshotImage];
}
person idStar    schedule 20.06.2013
comment
แน่นอนว่ารหัสนี้สมมติว่า ARC และเป็นปัจจุบัน (โซลูชันที่ใช้งานได้) เช่นเดียวกับที่ iOS6.1 - person idStar; 21.06.2013

ฉันแก้ไขปัญหาแล้ว แต่ไม่ได้ตอบคำถาม:

ฉันสร้างคลาสย่อยของ UIView และย้าย UIWebView ของฉันไปที่นั่น เพื่อให้มันอยู่ที่ 0/0 สัมพันธ์กับคลาสย่อย จากนั้นใช้ขนาดของ WebView:

UIGraphicsBeginImageContext(webview.frame.size);

และโค้ดอื่นจากด้านบน

ตอนนี้คุณสามารถย้ายคลาสย่อยไปยังทุกที่ที่คุณต้องการ

หมายเหตุ: หากคุณมีป้ายกำกับ เช่น ป้ายกำกับวันที่/เวลา คุณต้องย้ายป้ายกำกับเหล่านั้นด้วย ไม่เช่นนั้นคุณจะไม่เห็นป้ายกำกับเหล่านั้นบนรูปภาพ

ดังนั้นสร้างคลาสย่อยเป็น UIView และย้ายทุกๆ IBOutlet ที่คุณต้องการให้ปรากฏบนรูปภาพในนั้น

คำถามยังคงเปิดอยู่: เป็นไปได้ไหมที่จะถ่ายภาพเฉพาะบริเวณของหน้าจอ?

ขอแสดงความนับถือ. $h@rky

person Sharky    schedule 09.01.2012

- (void)drawRect:(CGRect)rect {
  UIGraphicsBeginImageContext(self.bounds.size);    
  [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
  UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();
  UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);  
}

คุณสามารถเรียกสิ่งนี้ตามมุมมองของคุณ :]

person Nils Munch    schedule 02.01.2012
comment
เมธอด DrawRect จะถูกเรียกเมื่อมีการสร้างมุมมองเว็บ ดังนั้นฉันจึงมีรูปสีเทาที่จุดเริ่มต้น แนวคิดที่ฉันได้รับจากสิ่งนี้คือการลากโค้ดและวางลงในคลาส UIView ที่กำหนดเองของฉันโดยที่มุมมองเว็บของฉันอยู่ที่ 0/0 ใช้งานได้ แต่ฉันไม่เห็นป้ายกำกับอีกต่อไปเพราะมันเป็นส่วนหนึ่งของมุมมองรูต - person Sharky; 03.01.2012