Подтвердить что ты не робот

Как быстро оценить размеры файлов с измененными размерами на iOS?

В Mail, когда я добавляю изображение и пытаюсь его отправить, он быстро спрашивает, какой размер я хочу отправить изображениям. Смотрите скриншот:

enter image description here

Я хочу сделать что-то подобное в приложении, где я буду загружать изображение и хочу, чтобы пользователь мог изменить размер изображения до его загрузки. Каков наилучший способ оценить размер файла, как это делает Apple?

Похоже, что для создания каждого из изображений с измененным размером потребовалось бы слишком много времени, чтобы проверить их размеры. Есть ли лучший способ?

Я нашел этот образец кода Apple, который немного помогает, но, честно говоря, немного подавляющим.:)

4b9b3361

Ответ 1

Самый большой фактор при определении окончательного размера сжатого изображения - это не размер изображения или качество сжатия JPEG, а сложность изображения (освещенная энтропия). Если вы знаете, что всегда будете иметь дело с очень подробными фотографиями (в отличие от сплошных цветовых полей или градиентов), это несколько уменьшает дисперсию вдоль этого измерения, но...

Я потратил немало времени на численный анализ этой проблемы. Я пробовал размер сжатого изображения подробного изображения с высоким разрешением, которое было уменьшено с шагом в 10 процентных пунктов, на 9 различных уровнях качества JPEG. Это создало трехмерный набор данных, описывающий неявную функцию z = (x, y), где x - размер масштабированного изображения в пикселях (w * h), y - качество сжатия JPEG, а z - размер полученного изображения в байтах.

Полученная поверхность трудно оценить. Противоинтуитивно он имеет колебания и множественные точки перегиба, что означает, что функция степени 2 как в х, так и у недостаточна для ее соответствия, а увеличение степеней полиномов и создание пользовательских функций фитинга не давали значительно лучших результатов. Мало того, что это не линейное соотношение, это даже не монотонное отношение. Это просто сложно.

Давайте получим практичность. Обратите внимание, когда Apple предложит вам размер изображения: когда вы нажмете "Отправить", а не когда изображение сначала появится в представлении композиции почты. Это дает им столько времени, сколько потребуется, чтобы составить свое сообщение, прежде чем они должны будут иметь приблизительные размеры изображений. Поэтому мое подозрение таково: они делают это нелегко. Масштабирование изображения на разные размеры можно распараллелить и выполнить в фоновом режиме, и хотя на iPhone 4-calibur требуется несколько секунд, вся эта работа может быть скрыта от пользователя. Если вы беспокоитесь об использовании памяти, вы можете записать изображения во временные файлы и последовательно их отображать, а не параллельно, которые будут использовать не более ~ 2x память несжатого файла в памяти.

Вкратце: если вы не знаете много о ожидаемой энтропии изображений, которые вы сжимаете, любая функция оценки будет крайне неточной для некоторого класса изображений. Если вы можете справиться с этим, то довольно легко сделать линейную или квадратичную подгонку по некоторым выборочным данным и произвести функцию для целей оценки. Однако, если вы хотите сделать так близко, как это делает Apple, вам, вероятно, придется выполнять фактическую работу по изменению размера в фоновом режиме, так как просто слишком много факторов для создания эвристики, которая все время делает все правильно.

Ответ 2

Я создал метод, который изменил бы размер изображения, например:

-(UIImage *)resizeImage:(UIImage *)image width:(CGFloat)resizedWidth height:(CGFloat)resizedHeight
{
CGImageRef imageRef = [image CGImage];

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef bitmap = CGBitmapContextCreate(NULL, resizedWidth, resizedHeight, 8, 4 * resizedWidth, colorSpace, kCGImageAlphaPremultipliedFirst);
CGContextDrawImage(bitmap, CGRectMake(0, 0, resizedWidth, resizedHeight), imageRef);
CGImageRef ref = CGBitmapContextCreateImage(bitmap);
UIImage *result = [UIImage imageWithCGImage:ref];

CGContextRelease(bitmap);
CGImageRelease(ref);

return result;
}

И чтобы получить размер изображения, вам нужно преобразовать его в NSData и задать длину:

 UIImage* actualImage = [UIImage imageNamed:@"image"];

NSData* actualImageData = UIImagePNGRepresentation(actualImage);

NSLog(@"Actual %f KB", (CGFloat)actualImageData.length / (CGFloat)1024);


UIImage* largeImage = [self resizeImage:actualImage width:actualImage.size.width * 0.8 height:actualImage.size.height * 0.8];

NSData* largeImageData = UIImagePNGRepresentation(largeImage);

NSLog(@"Large %f KB", (CGFloat)largeImageData.length / (CGFloat)1024);


UIImage* mediumImage = [self resizeImage:actualImage width:actualImage.size.width * 0.5 height:actualImage.size.height * 0.5];

NSData* mediumImageData = UIImagePNGRepresentation(mediumImage);

NSLog(@"Medium %f KB", (CGFloat)mediumImageData.length / (CGFloat)1024);


UIImage* smallImage = [self resizeImage:actualImage width:actualImage.size.width * 0.3 height:actualImage.size.height * 0.3];

NSData* smallImageData = UIImagePNGRepresentation(smallImage);

NSLog(@"Small %f KB", (CGFloat)smallImageData.length / (CGFloat)1024);

Ответ 3

Если вы сохраните его до NSData, вы можете вызвать [NSData length], чтобы получить количество содержащихся в нем байтов, а затем разделить его, чтобы получить правильные размеры в kB или MB

Ответ 4

Размеры изображения, представленные в приложении Mail, являются только оценками - фактический размер файла отправленного изображения отличается. Было бы слишком медленно преобразовать полноразмерный образ (3264 x 2448 в iPhone 4S) в различные размеры, чтобы получить размер файла.

[править]

Файлы сжатия не являются линейными, поэтому вы не можете просто получить numPixels/filesize, чтобы точно оценить размер файла для меньших изображений.

Таким образом, этот ответ не является абсолютно бесполезным, вот размеры изображений, которые экспортирует Mail.app:

Маленький: 320x240 Средний: 640x480 Large: 1224x1632

Ответ 5

Вы всегда можете использовать UIImageJPEGRepresentation для сжатия изображения. Этими четырьмя параметрами могут быть значения в диапазоне 0,25, 0,5, 0,75 и 1,0, размер которых может быть легко обнаружен вычислениями на изображении после применения того же метода.