حفظ محتويات UIVIEW في iOS 4 مع الحجم الحقيقي للصور داخل (IE SCALE APPONTSES UP for Save)

StackOverflow https://stackoverflow.com/questions/4213529

سؤال

لديّ Uiview مع العديد من LiimageViews كآراء فرعية. يعمل التطبيق على iOS4 وأستخدم الصور بدقة عرض شبكية العين (أي تحميل الصور مع المقياس = 2)

أرغب في حفظ محتويات Uiview ... ولكن ... الحصول على الحجم الحقيقي للصور في الداخل. أي أن العرض يحتوي على حجم 200x200 والصور ذات المقياس = 2 من الداخل ، أود حفظ صورة ناتجة عن 400 × 400 وجميع الصور بحجمها الحقيقي.

الآن ما يتبادر إلى الذهن أولاً هو إنشاء سياق صورة جديد وتحميله مرة أخرى جميع الصور في الداخل مع Scale = 1 وينبغي أن تفعل ، لكنني كنت أتساءل عما إذا كانت هناك طريقة أكثر أناقة للقيام بذلك؟ يبدو وكأنه خصر من الذاكرة ووقت المعالج لإعادة تحميل كل شيء مرة أخرى لأنه تم بالفعل ...

ملاحظة: إذا كان لدى أي شخص إجابة - بما في ذلك الكود سيكون لطيفًا

هل كانت مفيدة؟

المحلول

تنفيذ التقديم أي uiview إلى الصورة (العمل أيضًا لعرض شبكية العين).

ملف Helper.H:

@interface UIView (Ext) 
- (UIImage*) renderToImage;
@end

والتنفيذ الانتماء في ملف helper.m:

#import <QuartzCore/QuartzCore.h>

@implementation UIView (Ext)
- (UIImage*) renderToImage
{
  // IMPORTANT: using weak link on UIKit
  if(UIGraphicsBeginImageContextWithOptions != NULL)
  {
    UIGraphicsBeginImageContextWithOptions(self.frame.size, NO, 0.0);
  } else {
    UIGraphicsBeginImageContext(self.frame.size);
  }

  [self.layer renderInContext:UIGraphicsGetCurrentContext()];
  UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();  
  return image;
}

0.0 هو عامل المقياس. عامل المقياس للتطبيق على صورة نقطية. إذا حددت قيمة 0.0 ، يتم تعيين عامل المقياس على عامل مقياس الشاشة الرئيسية للجهاز.

Quartzcore.framework يجب أيضًا وضعها في المشروع لأننا ندعو وظيفة على كائن الطبقة.

لتمكين الرابط الضعيف على إطار UIKIT ، انقر فوق عنصر المشروع في Nevigator الأيسر ، انقر فوق هدف المشروع -> إنشاء مراحل -> ربط ثنائي واختر "اختياري" (ضعيف) على إطار UIKIT.

هنا مكتبة مع امتدادات مماثلة ل uicolor ، uiimage ، nsarray ، nsdictionary ، ...

نصائح أخرى

لقد قمت بأداء مثل هذا الشيء لحفظ المسامير من MkMapview كملف PNG (في شاشة Retina): MkpinannotationView: هل هناك أكثر من ثلاثة ألوان متاحة؟

إليك مستخلص من الجزء الحاسم الذي يؤدي توفير أ UIView (theView) باستخدام تعريف شبكية العين:


-(void) saveMyView:(UIView*)theView {
    //The image where the view content is going to be saved.
    UIImage* image = nil;
    UIGraphicsBeginImageContextWithOptions(theView.frame.size, NO, 2.0);
    [theView.layer renderInContext: UIGraphicsGetCurrentContext()];
    image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    NSData* imgData = UIImagePNGRepresentation(image);
    NSString* targetPath = [NSString stringWithFormat:@"%@/%@", [self writablePath], @"thisismyview.png" ];
    [imgData writeToFile:targetPath atomically:YES]; 
}

-(NSString*) writablePath { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; return documentsDirectory; }

المفتاح هو أن المعلمة الثالثة لـ uigraphicsbeginimageContextWithOptions هي مقياس, ، والذي يحدد كيفية كتابة الصورة في النهاية.

إذا كنت تريد دائمًا أبعاد البيكسل الحقيقية ، فاستخدم [[UISCREEN MAINSCREEN]] للحصول على المقياس الحالي للشاشة:

UIGraphicsBeginImageContextWithOptions(viewSizeInPoints, YES, [[UIScreen mainScreen] scale]);

إذا كنت تستخدم المقياس = 1.0 على iPhone4 ، فستحصل على صورة مع البعد في نقاط ويتم خفض النتيجة من عدد البكسل الحقيقي. إذا قمت بكتابة الصورة يدويًا إلى بُعد 640 × 960 (على سبيل المثال: تمرير وحدات البكسل كمعلمة الأولى) ، فستكون في الواقع الصورة التي يتم تحجيمها مرة أخرى والتي تبدو فظيعة كما تتخيل أنها ستبدو.

ألا يمكنك فقط إنشاء سياق رسومات جديد في الحجم المطلوب ، واستخدام cgaffinetransform لتوسيع نطاقه ، وجعل طبقة الجذر الجذرية لجذر Uiview ، واستعادة السياق إلى الحجم الأصلي وتقديم الصورة؟ لم تجرب هذا لمحتوى Retina ، ولكن يبدو أن هذا يعمل بشكل جيد مع الصور الكبيرة التي تم تقليصها في LiimageViews ...

شيء مثل:

CGSize originalSize = myOriginalImage.size; //or whatever

//create context
UIGraphicsBeginImageContext(originalSize);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context); //1 original context

// translate/flip the graphics context (for transforming from CG* coords to UI* coords
CGContextTranslateCTM(context, 0, originalSize.height);
CGContextScaleCTM(context, 1.0, -1.0);

//original image
CGContextDrawImage(context, CGRectMake(0,0,originalSize.width,originalSize.height), myOriginalImage.CGImage);

CGContextRestoreGState(context);//1 restore to original for UIView render;

//scaling
CGFloat wratio = originalSize.width/self.view.frame.size.width;
CGFloat hratio = originalSize.height/self.view.frame.size.height;

//scale context to match view size
CGContextSaveGState(context); //1 pre-scaled size
CGContextScaleCTM(context, wratio, hratio);

//render 
[self.view.layer renderInContext:context];

CGContextRestoreGState(context);//1  restore to pre-scaled size;

UIImage *exportImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

استيراد Quartzcore (انقر فوق المشروع الرئيسي ، مراحل البناء ، الاستيراد) وحيث تحتاج إلى إضافة:

#import <QuartzCore/QuartzCore.h>

ImageViews الخاصة بي هي خصائص ، إذا لم تكن كذلك ، فتجاهل .self وقم بتمرير ImageViews إلى الوظيفة كمعلمات ، ثم اتصل renderInContext على الصورتين في جديد UIGraphicsCurrentContext

- (UIImage *)saveImage
{
    UIGraphicsBeginImageContextWithOptions(self.mainImage.bounds.size, NO, 0.0);

    [self.backgroundImage.layer renderInContext:UIGraphicsGetCurrentContext()];
    [self.mainImage.layer renderInContext:UIGraphicsGetCurrentContext()];

    UIImage *savedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return savedImage;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top