حفظ محتويات UIVIEW في iOS 4 مع الحجم الحقيقي للصور داخل (IE SCALE APPONTSES UP for Save)
-
26-09-2019 - |
سؤال
لديّ 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;
}