আইওএসের সাহায্যে কীভাবে সহজেই আকারের আকার / অপ্টিমাইজ করা যায়?


114

আমার অ্যাপ্লিকেশনটি নেটওয়ার্ক থেকে ইমেজ ফাইলগুলির একটি সেট ডাউনলোড করছে এবং সেগুলি স্থানীয় আইফোন ডিস্কে সেভ করছে। এর মধ্যে কয়েকটি চিত্র আকারে বেশ বড় (উদাহরণস্বরূপ, 500 পিক্সেলের চেয়ে প্রস্থের বড়)। যেহেতু আইফোনটির মূল আকারে চিত্রটি দেখাতে যথেষ্ট বড় ডিসপ্লেও নেই, তাই আমি স্থান / কর্মক্ষমতা বাঁচাতে চিত্রটিকে কিছুটা ছোট আকারে পুনরায় আকার দেওয়ার পরিকল্পনা করছি।

এছাড়াও, এই চিত্রগুলির মধ্যে কিছু জেপিইজি এবং সেগুলি 60% মানের সেটিং হিসাবে সংরক্ষণ করা হয় না।

আমি কীভাবে আইফোন এসডিকে দিয়ে একটি চিত্রের আকার পরিবর্তন করতে পারি এবং কীভাবে আমি একটি জেপিইজি চিত্রের মান সেটিংস পরিবর্তন করতে পারি?

উত্তর:


246

এই প্রশ্নের উত্তর হিসাবে বেশ কয়েকটি পরামর্শ দেওয়া হয়েছে । আমি প্রাসঙ্গিক কোড সহ এই পোস্টে বর্ণিত কৌশলটি পরামর্শ দিয়েছিলাম :

+ (UIImage*)imageWithImage:(UIImage*)image 
               scaledToSize:(CGSize)newSize;
{
   UIGraphicsBeginImageContext( newSize );
   [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
   UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
   UIGraphicsEndImageContext();

   return newImage;
}

যতক্ষণ না চিত্রের সঞ্চয়স্থান রয়েছে, আইফোনের সাথে ব্যবহার করার জন্য দ্রুততম চিত্রের ফর্ম্যাটটি পিএনজি, কারণ এটির ফর্ম্যাটটির জন্য এটি অপ্টিমাইজেশন রয়েছে। তবে, আপনি যদি এই চিত্রগুলি জেপিইজি হিসাবে সংরক্ষণ করতে চান তবে আপনি নিজের ইউআইআইমেজ নিতে পারেন এবং নিম্নলিখিতগুলি করতে পারেন:

NSData *dataForJPEGFile = UIImageJPEGRepresentation(theImage, 0.6);

এটি একটি এনএসডিটা ইভেন্ট তৈরি করে যা একটি 60 শতাংশ মানের সেটিং-এ JPEG চিত্রের কাঁচা বাইট রয়েছে। সেই এনএসডাটা উদাহরণের বিষয়বস্তুগুলি তখন ডিস্কে লেখা বা মেমরিতে ক্যাশে করা যায়।


1
স্যার ... আমি একই যুক্তিটি লিখেছি তবে ডান পাশের একটি সাদা স্ট্রেট লাইন উপস্থিত হবে (প্রতিকৃতি) আমাকে সমাধান দিন
নাগ_আইফোন

1
হাই, পুনরায় আকার দেওয়ার সময় আমরা কীভাবে দিক অনুপাত এবং ক্লিপগুলিকে আবদ্ধ করতে পারি? আমার ক্ষেত্রে, যখন আমি কোনও চিত্রের আকার পরিবর্তন করি যখন আলাদা রেশন থাকে তখন "নিউজাইজ" হয়, তখন আমি একটি বিকৃত আকারযুক্ত আকারের চিত্র পাই। ধন্যবাদ!
ভান ডু ট্রান

1
এটি অতীতে কাজ করেছে, তবে আইওএস 5.0.1 এবং তার পরে, এর ফলে মেমরি ফাঁস হয়। এটি সম্পাদন করার অন্য কোনও উপায়?
উসমান নিসার

উন্নত পারফরম্যান্সের জন্য [চিত্র অঙ্কনইনরেট: রেক্ট ব্লেন্ডমোড: কেসিবিগ্লেন্ডমোডকপি আলফা: 1.0] ব্যবহারের প্রস্তাব দিন (সুতরাং ড্রয়ের সময় ব্লেন্ডিং গণনা করতে হবে না
cdemiris99

আপনার ইউআইজিগ্রাফিক্সবিগিন আইজেমকন্টেক্সট উইথঅ্যাপশনগুলি (আকার, NO, 0.0) ব্যবহার করা উচিত; যেখানে ০.০ রেটিনা এবং তদূর্ধ্বকে সমর্থন করতে মূল স্ক্রিন স্কেল ব্যবহার করবে। অ্যাপল জানিয়েছে "আপনার সাধারণত অনুরূপ নামযুক্ত ইউআইজিগ্রাফিকসবেগিনআইমেজকন্টেক্সট ফাংশন (পিছনের সামঞ্জস্যের জন্য একটি ফ্যালব্যাক হিসাবে বাদে) এড়ানো উচিত" "
ব্র্যাড গস

65

আপনার চিত্রগুলি পুনরায় আকার দেওয়ার সবচেয়ে সহজ এবং সহজ উপায় হ'ল এটি

float actualHeight = image.size.height;
float actualWidth = image.size.width;
float imgRatio = actualWidth/actualHeight;
float maxRatio = 320.0/480.0;

if(imgRatio!=maxRatio){
    if(imgRatio < maxRatio){
        imgRatio = 480.0 / actualHeight;
        actualWidth = imgRatio * actualWidth;
        actualHeight = 480.0;
    }
    else{
        imgRatio = 320.0 / actualWidth;
        actualHeight = imgRatio * actualHeight;
        actualWidth = 320.0;
    }
}
CGRect rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight);
UIGraphicsBeginImageContext(rect.size);
[image drawInRect:rect];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

এটা সুন্দর. আমি রেটিনা-ডিসপ্লে রেজোলিউশন বজায় রেখে প্রায় 1 এমবি থেকে 100 কে সার্ভারে প্রেরিত চিত্রগুলি ছাঁটাতে সক্ষম হয়েছি (যদিও আমি 320.0 এবং 480.0 মানগুলি 640.0 এবং 1136.0 তে পরিবর্তন করেছি) এবং স্কেলিংয়ের পরে কিছু জেপিইজি সংক্ষেপণও করেছি: ইউআইআইএমজেজেপিজেগ্রিপ্রেসেশন (ইমগ, 0.7f);
কেলার

2
যদি চিত্র অনুপাত এবং সর্বোচ্চ অনুপাত সমান হয়? উদাহরণস্বরূপ, যদি আইমজের আকার 3200x4800 হয়?
akshay1188

এটি অতীতে কাজ করেছে, তবে আইওএস 5.0.1 এবং তার পরে, এর ফলে মেমরি ফাঁস হয়। এটি সম্পাদন করার অন্য কোনও উপায়?
উসমান নিসার

25

উপরের পদ্ধতিগুলি ছোট চিত্রগুলির জন্য ভাল কাজ করে তবে আপনি যখন খুব বড় চিত্রটির আকার পরিবর্তন করার চেষ্টা করবেন তখন আপনি মেমরিটি খুব দ্রুতই শেষ হয়ে যাবে এবং অ্যাপটি ক্রাশ করবে। আরও ভাল উপায় হ'ল CGImageSourceCreateThumbnailAtIndexপ্রথমে ডিকোডিংটি ছাড়াই চিত্রটিকে পুনরায় আকার দিন।

আপনি যদি আকার পরিবর্তন করতে চান সেই চিত্রটির পথ যদি থাকে তবে আপনি এটি ব্যবহার করতে পারেন:

- (void)resizeImageAtPath:(NSString *)imagePath {
    // Create the image source (from path)
    CGImageSourceRef src = CGImageSourceCreateWithURL((__bridge CFURLRef) [NSURL fileURLWithPath:imagePath], NULL);

    // To create image source from UIImage, use this
    // NSData* pngData =  UIImagePNGRepresentation(image);
    // CGImageSourceRef src = CGImageSourceCreateWithData((CFDataRef)pngData, NULL);

    // Create thumbnail options
    CFDictionaryRef options = (__bridge CFDictionaryRef) @{
            (id) kCGImageSourceCreateThumbnailWithTransform : @YES,
            (id) kCGImageSourceCreateThumbnailFromImageAlways : @YES,
            (id) kCGImageSourceThumbnailMaxPixelSize : @(640)
    };
    // Generate the thumbnail
    CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(src, 0, options); 
    CFRelease(src);
    // Write the thumbnail at path
    CGImageWriteToFile(thumbnail, imagePath);
}

আরও বিশদ এখানে


ধন্যবাদ, এই সমাধানটি কবজির মতো কাজ করে), আপনি কি অন্যান্য ফাইল ফর্ম্যাটগুলি জানেন যা CGImageSourceইমেজ এবং পিডিএফ ছাড়াও সমর্থন করে ?
সেজে 444

ধন্যবাদ। আমি এর একটি অ্যানালগ খুঁজছিলাম inSampleSizeযা অ্যান্ড্রয়েডের ডিকোডার দ্বারা ব্যবহৃত হয়। এবং এটিই একমাত্র উত্তর যা মেমরির দক্ষ পদ্ধতিতে কোনও চিত্রকে স্কেল করার একটি উপায় সরবরাহ করে।
স্টান মটস

স্টোরেজে ফাইলগুলির সাথে সরাসরি এটির কাজ করার আমার দুর্দান্ত ফলাফল ছিল, মেমরির চিত্রগুলি নিয়েও কাজ করে তবে তাড়াতাড়ি নয় (বড় ছবিতে কোনও ইউআইআইমেজ তারপর স্কেলে লোড করতে)।
কেন্ডল হেলস্টেটার জেলনার

শেয়ার এক্সটেনশনে কাজ করে না। অ্যাপ্লিকেশনটি এখনও খুব বড় চিত্রের সাথে ক্র্যাশ হচ্ছে।
জর্জ

18

আকৃতি অনুপাতটি হারানো ছাড়াই চিত্রগুলি স্কেল করার সর্বোত্তম উপায় (অর্থাত্ প্যাকেজটি প্রসারিত না করে) এই পদ্ধতিটি ব্যবহার করা:

//to scale images without changing aspect ratio
+ (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)newSize {

    float width = newSize.width;
    float height = newSize.height;

    UIGraphicsBeginImageContext(newSize);
    CGRect rect = CGRectMake(0, 0, width, height);

    float widthRatio = image.size.width / width;
    float heightRatio = image.size.height / height;
    float divisor = widthRatio > heightRatio ? widthRatio : heightRatio;

    width = image.size.width / divisor;
    height = image.size.height / divisor;

    rect.size.width  = width;
    rect.size.height = height;

    //indent in case of width or height difference
    float offset = (width - height) / 2;
    if (offset > 0) {
        rect.origin.y = offset;
    }
    else {
        rect.origin.x = -offset;
    }

    [image drawInRect: rect];

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

    return smallImage;

}

আপনার ইউটিলিটি ক্লাসে এই পদ্ধতিটি যুক্ত করুন যাতে আপনি এটি আপনার প্রকল্পের সর্বত্র ব্যবহার করতে পারেন এবং এটির মতো অ্যাক্সেস করতে পারেন:

xyzImageView.image = [Utility scaleImage:yourUIImage toSize:xyzImageView.frame.size];

এই অনুপাতটি অনুপাত বজায় রেখে স্কেলিংয়ের যত্ন নেয়। স্কেলড ডাউন ইমেজের উচ্চতা (বা বিপরীতে) এর চেয়ে প্রস্থ বেশি হলে চিত্রে এটি সূচকগুলি যুক্ত করে।


8

আপনার যদি সার্ভারের উপর নিয়ন্ত্রণ থাকে তবে আমি দৃ strongly ়ভাবে ইমেজম্যাগিকের সাথে চিত্রগুলি সার্ভারের দিকটি পুনরায় আকার দেওয়ার প্রস্তাব দিচ্ছি । বড় আকারের চিত্র ডাউনলোড করা এবং ফোনে তাদের আকার পরিবর্তন করা অনেক মূল্যবান সংস্থান - ব্যান্ডউইথ, ব্যাটারি এবং মেমরির অপচয়। যার সবকটিই ফোনে দুষ্প্রাপ্য।


2
এফটিএফকিউ: "আমার অ্যাপ্লিকেশনটি নেটওয়ার্ক থেকে চিত্র ফাইলের একটি সেট ডাউনলোড করছে,"
রোগ

এটি একটি প্রাসঙ্গিক উত্তর হতে পারে। প্রশ্নটি থেকে বলা হয় যে ছবিগুলি নেটওয়ার্ক থেকে ডাউনলোড করা হচ্ছে। ওপি যদি ইমেজগুলির সার্ভারের সাথে কাজ করতে পারে তবে তার উচিত। যদি সে না পারে, উত্তর আরও সাহায্য করবে।
জোশুয়া ডান্স

6

আমি সুইফটে চিত্র স্কেলিংয়ের একটি চূড়ান্ত সমাধান বিকাশ করেছি।

আপনি চিত্রটি পূরণ করতে, দিক পূরণ করতে বা দিকের ফিট নির্দিষ্ট আকারের আকার পরিবর্তন করতে এটি ব্যবহার করতে পারেন।

আপনি চিত্রটি কেন্দ্র বা চারটি কিনার এবং চার কোণার যেকোন একটিতে সারিবদ্ধ করতে পারেন।

এবং আপনি অতিরিক্ত স্থানটি ছাঁটাই করতে পারেন যা যুক্ত হয় যদি মূল চিত্র এবং লক্ষ্য আকারের অনুপাতটি সমান না হয়।

enum UIImageAlignment {
    case Center, Left, Top, Right, Bottom, TopLeft, BottomRight, BottomLeft, TopRight
}

enum UIImageScaleMode {
    case Fill,
    AspectFill,
    AspectFit(UIImageAlignment)
}

extension UIImage {
    func scaleImage(width width: CGFloat? = nil, height: CGFloat? = nil, scaleMode: UIImageScaleMode = .AspectFit(.Center), trim: Bool = false) -> UIImage {
        let preWidthScale = width.map { $0 / size.width }
        let preHeightScale = height.map { $0 / size.height }
        var widthScale = preWidthScale ?? preHeightScale ?? 1
        var heightScale = preHeightScale ?? widthScale
        switch scaleMode {
        case .AspectFit(_):
            let scale = min(widthScale, heightScale)
            widthScale = scale
            heightScale = scale
        case .AspectFill:
            let scale = max(widthScale, heightScale)
            widthScale = scale
            heightScale = scale
        default:
            break
        }
        let newWidth = size.width * widthScale
        let newHeight = size.height * heightScale
        let canvasWidth = trim ? newWidth : (width ?? newWidth)
        let canvasHeight = trim ? newHeight : (height ?? newHeight)
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(canvasWidth, canvasHeight), false, 0)

        var originX: CGFloat = 0
        var originY: CGFloat = 0
        switch scaleMode {
        case .AspectFit(let alignment):
            switch alignment {
            case .Center:
                originX = (canvasWidth - newWidth) / 2
                originY = (canvasHeight - newHeight) / 2
            case .Top:
                originX = (canvasWidth - newWidth) / 2
            case .Left:
                originY = (canvasHeight - newHeight) / 2
            case .Bottom:
                originX = (canvasWidth - newWidth) / 2
                originY = canvasHeight - newHeight
            case .Right:
                originX = canvasWidth - newWidth
                originY = (canvasHeight - newHeight) / 2
            case .TopLeft:
                break
            case .TopRight:
                originX = canvasWidth - newWidth
            case .BottomLeft:
                originY = canvasHeight - newHeight
            case .BottomRight:
                originX = canvasWidth - newWidth
                originY = canvasHeight - newHeight
            }
        default:
            break
        }
        self.drawInRect(CGRectMake(originX, originY, newWidth, newHeight))
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}

নীচে এই সমাধানটি প্রয়োগ করার উদাহরণ রয়েছে।

ধূসর আয়তক্ষেত্রটি টার্গেট সাইটের চিত্রটিকে আবার আকার দেওয়া হবে। হালকা নীল আয়তক্ষেত্রের নীল চেনাশোনাগুলি হ'ল চিত্র (আমি চেনাশোনাগুলি ব্যবহার করেছি কারণ দিকটি সংরক্ষণ না করে কখন এটি ছোট করে দেওয়া হয় তা দেখতে সহজ)। হালকা কমলা রঙের এমন অঞ্চল চিহ্নিত করে যা আপনি পাস করলে ছাঁটা হবে trim: true

স্কেলিংয়ের আগে এবং পরে দিকটি ফিট করে :

দিক 1 ফিট (আগে) দিক 1 ফিট (পরে)

দিক ফিট করার আরও একটি উদাহরণ :

দিক 2 ফিট (আগে) দিক 2 ফিট (পরে)

শীর্ষ প্রান্তিককরণের সাথে দিকটি ফিট :

দিক 3 ফিট (আগে) দিক 3 ফিট (পরে)

দিকটি পূরণ করুন :

দিক পূর্বে (পূর্বে) দিকটি পূরণ (পরে)

পূরণ করুন :

পূরণ করুন (আগে) পূরণ করুন (পরে)

আমি আমার উদাহরণগুলিতে আপসেলিং ব্যবহার করেছি কারণ এটি প্রদর্শন করা সহজ তবে সমাধানটি প্রশ্নে যেমন ডাউনস্কেলিংয়ের জন্যও কাজ করে।

জেপিজি সংক্ষেপণের জন্য আপনার এটি ব্যবহার করা উচিত:

let compressionQuality: CGFloat = 0.75 // adjust to change JPEG quality
if let data = UIImageJPEGRepresentation(image, compressionQuality) {
  // ...
}

আপনি আমার কোডটি এক্সকোড খেলার মাঠের সাথে দেখতে পারেন ।


3

সুইফ্ট 3-এর জন্য নীচের কোডটি অনুপাতের অনুপাত রেখে চিত্রকে স্কেল করে। আপনি অ্যাপলের ডকুমেন্টেশনে ইমেজ কনটেক্সট সম্পর্কে আরও পড়তে পারেন :

extension UIImage {
    class func resizeImage(image: UIImage, newHeight: CGFloat) -> UIImage {
        let scale = newHeight / image.size.height
        let newWidth = image.size.width * scale
        UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
        image.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage!
    }
}

এটি ব্যবহার করতে, কল resizeImage()পদ্ধতি:

UIImage.resizeImage(image: yourImageName, newHeight: yourImageNewHeight)

2

আপনি প্রয়োজনীয় আকারে চিত্র স্কেল করতে এই কোডটি ব্যবহার করতে পারেন।

+ (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)newSize
{
    CGSize actSize = image.size;
    float scale = actSize.width/actSize.height;

    if (scale < 1) {
        newSize.height = newSize.width/scale;
    } 
    else {
        newSize.width = newSize.height*scale;
    }

    UIGraphicsBeginImageContext(newSize);
    [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
}

2

আইওএস মেমরি ডিপ ডাইভ এই সেশন অনুসারে, ImageIOচিত্রগুলি ডাউনস্কেল করার জন্য আমাদের আরও ভাল ব্যবহার হয়েছিল।

UIImageডাউনস্কেল চিত্র ব্যবহার করার খারাপ ।

  • আসল চিত্রটিকে মেমোরিতে ছড়িয়ে দেবে
  • অভ্যন্তরীণ স্থানাঙ্ক স্থান স্থানান্তর ব্যয়বহুল

ব্যবহার ImageIO

  • ইমেজআইও মেমরি নষ্ট না করে চিত্রের আকার এবং মেটাডেটা তথ্য পড়তে পারে।

  • ইমেজআইও কেবল পুনরায় আকারিত চিত্রের ব্যয়ে চিত্রগুলিকে আকার দিতে পারে।

স্মৃতিতে চিত্র সম্পর্কে

  • মেমরির ব্যবহার চিত্রের আকারের সাথে সম্পর্কিত, ফাইলের আকারের সাথে নয়।
  • UIGraphicsBeginImageContextWithOptionsসর্বদা SRGBরেন্ডারিং-ফর্ম্যাট ব্যবহার করে যা প্রতি পিক্সেলটিতে 4 বাইট ব্যবহার করে।
  • একটি চিত্রের load -> decode -> render3 টি পর্যায় রয়েছে।
  • UIImage মাপ দেওয়ার এবং পুনরায় আকার দেওয়ার জন্য ব্যয়বহুল

নিম্নলিখিত চিত্রের জন্য, আপনি যদি ব্যবহার করেন তবে UIGraphicsBeginImageContextWithOptions কেবল একটি চিত্র লোড করতে আমাদের 590KB দরকার হয়, 2048 pixels x 1536 pixels x 4 bytes per pixelযখন ডিকোডিংয়ের সময় আমাদের = 10MB প্রয়োজন এখানে চিত্র বর্ণনা লিখুন

UIGraphicsImageRendererআইওএস 10-এ প্রবর্তিত হওয়ার পরে , iOS 12 এ স্বয়ংক্রিয়ভাবে সেরা গ্রাফিক ফর্ম্যাটটি চয়ন করবে। এর অর্থ, আপনার যদি এসআরজিবি প্রয়োজন না UIGraphicsBeginImageContextWithOptionsহয় UIGraphicsImageRendererতবে প্রতিস্থাপন করে আপনি 75% মেমরি সঞ্চয় করতে পারেন ।

এটি মেমোরিতে আইওএস চিত্র সম্পর্কে আমার নিবন্ধ

func resize(url: NSURL, maxPixelSize: Int) -> CGImage? {
    let imgSource = CGImageSourceCreateWithURL(url, nil)
    guard let imageSource = imgSource else {
        return nil
    }

    var scaledImage: CGImage?
    let options: [NSString: Any] = [
            // The maximum width and height in pixels of a thumbnail.
            kCGImageSourceThumbnailMaxPixelSize: maxPixelSize,
            kCGImageSourceCreateThumbnailFromImageAlways: true,
            // Should include kCGImageSourceCreateThumbnailWithTransform: true in the options dictionary. Otherwise, the image result will appear rotated when an image is taken from camera in the portrait orientation.
            kCGImageSourceCreateThumbnailWithTransform: true
    ]
    scaledImage = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options as CFDictionary)

    return scaledImage
}


let filePath = Bundle.main.path(forResource:"large_leaves_70mp", ofType: "jpg")

let url = NSURL(fileURLWithPath: filePath ?? "")

let image = resize(url: url, maxPixelSize: 600)

অথবা

// Downsampling large images for display at smaller size
func downsample(imageAt imageURL: URL, to pointSize: CGSize, scale: CGFloat) -> UIImage {
    let imageSourceOptions = [kCGImageSourceShouldCache: false] as CFDictionary
    let imageSource = CGImageSourceCreateWithURL(imageURL as CFURL, imageSourceOptions)!
    let maxDimensionInPixels = max(pointSize.width, pointSize.height) * scale
    let downsampleOptions =
        [kCGImageSourceCreateThumbnailFromImageAlways: true,
        kCGImageSourceShouldCacheImmediately: true,
        // Should include kCGImageSourceCreateThumbnailWithTransform: true in the options dictionary. Otherwise, the image result will appear rotated when an image is taken from camera in the portrait orientation.
        kCGImageSourceCreateThumbnailWithTransform: true,
        kCGImageSourceThumbnailMaxPixelSize: maxDimensionInPixels] as CFDictionary
    let downsampledImage =
        CGImageSourceCreateThumbnailAtIndex(imageSource, 0, downsampleOptions)!
    return UIImage(cgImage: downsampledImage)
}

1

রেটিনা ডিসপ্লেতে যে সমস্যা দেখা দিতে পারে তা হ'ল চিত্রের স্কেল ইমেজক্যাপচার বা তাই দ্বারা সেট করা হয়েছে। উপরের পুনরায় আকার ফাংশনগুলি এটি পরিবর্তন করবে না। এই ক্ষেত্রে আকারগুলি সঠিকভাবে কাজ করবে না।

নীচের কোডে, স্কেলটি 1 তে সেট করা হয়েছে (মাপসই নয়) এবং প্রত্যাবর্তিত চিত্রটির এমন আকার রয়েছে যা আপনি আশা করতে পারেন। এটি UIGraphicsBeginImageContextWithOptionsকল করা হয়।

-(UIImage *)resizeImage :(UIImage *)theImage :(CGSize)theNewSize {
    UIGraphicsBeginImageContextWithOptions(theNewSize, NO, 1.0);
    [theImage drawInRect:CGRectMake(0, 0, theNewSize.width, theNewSize.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

1

এখানে বেশ কয়েকটি উত্তরের সাথে যুক্ত করা হচ্ছে, তবে আমি একটি সমাধানের জন্য গিয়েছি যা মাত্রার পরিবর্তে ফাইল আকার দ্বারা আকার পরিবর্তন করে।

এটি আপনার প্রদত্ত আকারে না পৌঁছানো পর্যন্ত চিত্রের মাত্রা এবং গুণমান উভয়ই হ্রাস করবে।

func compressTo(toSizeInMB size: Double) -> UIImage? {
    let bytes = size * 1024 * 1024
    let sizeInBytes = Int(bytes)
    var needCompress:Bool = true
    var imgData:Data?
    var compressingValue:CGFloat = 1.0

    while (needCompress) {

        if let resizedImage = scaleImage(byMultiplicationFactorOf: compressingValue), let data: Data = UIImageJPEGRepresentation(resizedImage, compressingValue) {

            if data.count < sizeInBytes || compressingValue < 0.1 {
                needCompress = false
                imgData = data
            } else {
                compressingValue -= 0.1
            }
        }
    }

    if let data = imgData {
        print("Finished with compression value of: \(compressingValue)")
        return UIImage(data: data)
    }
    return nil
}

private func scaleImage(byMultiplicationFactorOf factor: CGFloat) -> UIImage? {
    let size = CGSize(width: self.size.width*factor, height: self.size.height*factor)
    UIGraphicsBeginImageContext(size)
    draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
    if let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext() {
        UIGraphicsEndImageContext()
        return newImage;
    }
    return nil
}

আকারের উত্তর দ্বারা স্কেলিংয়ের ক্রেডিট


1

সুইফট সংস্করণ

func resizeImage(image: UIImage, newWidth: CGFloat) -> UIImage? {

    let scale = newWidth / image.size.width
    let newHeight = CGFloat(200.0)
    UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
    image.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))

    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage
}

0

আমি ব্র্যাডস কৌশলটি ব্যবহার করে একটি scaleToFitWidthপদ্ধতি তৈরি করতে শেষ করেছিলাম UIImage+Extensionsযদি তা কারওর জন্য উপকারী হয় ...

-(UIImage *)scaleToFitWidth:(CGFloat)width
{
    CGFloat ratio = width / self.size.width;
    CGFloat height = self.size.height * ratio;

    NSLog(@"W:%f H:%f",width,height);

    UIGraphicsBeginImageContext(CGSizeMake(width, height));
    [self drawInRect:CGRectMake(0.0f,0.0f,width,height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
}

তারপরে আপনি যেখানে পছন্দ করেন

#import "UIImage+Extensions.h"

UIImage *newImage = [image scaleToFitWidth:100.0f];

আপনি UIView+Extensionsযদি কোনও ইউআইভিউ থেকে চিত্রগুলি রেন্ডার করতে চান তবে আপনি এটি আরও নিচে একটি শ্রেণিতে স্থানান্তর করতে পারেন তা লক্ষণীয়


0

আমি কেবল কোকো সুইফ্ট প্রোগ্রামারদের জন্য এই প্রশ্নের উত্তর দিতে চেয়েছিলাম। এই ফাংশনটি নতুন আকারের সাথে এনএসআইমেজকে ফেরত দেয়। আপনি এই ফাংশনটি এভাবে ব্যবহার করতে পারেন।

        let sizeChangedImage = changeImageSize(image, ratio: 2)






 // changes image size

    func changeImageSize (image: NSImage, ratio: CGFloat) -> NSImage   {

    // getting the current image size
    let w = image.size.width
    let h = image.size.height

    // calculating new size
    let w_new = w / ratio 
    let h_new = h / ratio 

    // creating size constant
    let newSize = CGSizeMake(w_new ,h_new)

    //creating rect
    let rect  = NSMakeRect(0, 0, w_new, h_new)

    // creating a image context with new size
    let newImage = NSImage.init(size:newSize)



    newImage.lockFocus()

        // drawing image with new size in context
        image.drawInRect(rect)

    newImage.unlockFocus()


    return newImage

}

0

যদি আপনার চিত্রটি নথি ডিরেক্টরিতে থাকে তবে এই URL টি এক্সটেনশান যুক্ত করুন:

extension URL {
    func compressedImageURL(quality: CGFloat = 0.3) throws -> URL? {
        let imageData = try Data(contentsOf: self)
        debugPrint("Image file size before compression: \(imageData.count) bytes")

        let compressedURL = NSURL.fileURL(withPath: NSTemporaryDirectory() + NSUUID().uuidString + ".jpg")

        guard let actualImage = UIImage(data: imageData) else { return nil }
        guard let compressedImageData = UIImageJPEGRepresentation(actualImage, quality) else {
            return nil
        }
        debugPrint("Image file size after compression: \(compressedImageData.count) bytes")

        do {
            try compressedImageData.write(to: compressedURL)
            return compressedURL
        } catch {
            return nil
        }
    }
}

ব্যবহার:

guard let localImageURL = URL(string: "< LocalImagePath.jpg >") else {
    return
}

//Here you will get URL of compressed image
guard let compressedImageURL = try localImageURL.compressedImageURL() else {
    return
}

debugPrint("compressedImageURL: \(compressedImageURL.absoluteString)")

দ্রষ্টব্য: - আপনার স্থানীয় জেপিজি চিত্রের পথের সাথে <লোকাল আইমেজপ্যাথ.জপিজি> পরিবর্তন করুন।


-1

যদি এখনও কেউ আরও ভাল বিকল্পের সন্ধান করে

-(UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)targetSize {


    UIImage *sourceImage = image;
    UIImage *newImage = nil;

    CGSize imageSize = sourceImage.size;
    CGFloat width = imageSize.width;
    CGFloat height = imageSize.height;

    CGFloat targetWidth = targetSize.width;
    CGFloat targetHeight = targetSize.height;

    CGFloat scaleFactor = 0.0;
    CGFloat scaledWidth = targetWidth;
    CGFloat scaledHeight = targetHeight;

    CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

    if (CGSizeEqualToSize(imageSize, targetSize) == NO) {

        CGFloat widthFactor = targetWidth / width;
        CGFloat heightFactor = targetHeight / height;

        if (widthFactor < heightFactor)
            scaleFactor = widthFactor;
        else
            scaleFactor = heightFactor;

        scaledWidth  = width * scaleFactor;
        scaledHeight = height * scaleFactor;

        // center the image


        if (widthFactor < heightFactor) {
            thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
        } else if (widthFactor > heightFactor) {
            thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
        }
    }


    // this is actually the interesting part:

    UIGraphicsBeginImageContext(targetSize);

    CGRect thumbnailRect = CGRectZero;
    thumbnailRect.origin = thumbnailPoint;
    thumbnailRect.size.width  = scaledWidth;
    thumbnailRect.size.height = scaledHeight;

    [sourceImage drawInRect:thumbnailRect];

    newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    if(newImage == nil) NSLog(@"could not scale image");


    return newImage ;

}

-1
- (UIImage *)resizeImage:(UIImage*)image newSize:(CGSize)newSize {
    CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));
    CGImageRef imageRef = image.CGImage;

    UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
    CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, newSize.height);

    CGContextConcatCTM(context, flipVertical);
    CGContextDrawImage(context, newRect, imageRef);

    CGImageRef newImageRef = CGBitmapContextCreateImage(context);
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];

    CGImageRelease(newImageRef);
    UIGraphicsEndImageContext();

    return newImage;
}

দয়া করে আপনার উত্তরে কোডটির কমপক্ষে কিছু ব্যাখ্যা সরবরাহ করুন। এবং উত্তর পাঠককে পাঠ্যযোগ্য করে তুলতে কোডটি ফর্ম্যাট করুন।
xpereta

-2

কোনও চিত্রকে পুনরায় আকার দেওয়ার জন্য ড্রইএনআরেক্টের স্থলে এই ফাংশনটি ব্যবহার করে আমার আরও ভাল (গ্রাফিকাল) ফলাফল রয়েছে:

- (UIImage*) reduceImageSize:(UIImage*) pImage newwidth:(float) pWidth
{
    float lScale = pWidth / pImage.size.width;
    CGImageRef cgImage = pImage.CGImage;
    UIImage   *lResult = [UIImage imageWithCGImage:cgImage scale:lScale
                            orientation:UIImageOrientationRight];
    return lResult;
}

দিকের অনুপাত স্বয়ংক্রিয়ভাবে যত্ন নেওয়া হয়

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.