Как работать с изображениями (png) размером 2-4Mb - PullRequest
1 голос
/ 29 марта 2010

Я работаю с изображениями размером от 2 до 4 МБ. Я работаю с изображениями с разрешением 1200x1600, выполняя операции масштабирования, перемещения и поворота. Я хочу добавить еще одно изображение и сохранить его в фотоальбоме. Мое приложение падает после того, как я успешно отредактировал одно изображение и сохранил фотографии. Это происходит из-за размера изображений, я думаю. Я хочу сохранить 90% разрешения изображений.

Я выпускаю несколько изображений, когда получаю предупреждение о памяти. Но все равно происходит сбой, так как я работаю с двумя изображениями размером 3 МБ каждое и контекстом размера 1200x1600 и одновременно получаю изображение из контекста.

Есть ли способ сжимать изображения и работать с ним?

Ответы [ 2 ]

3 голосов
/ 29 марта 2010

Я сомневаюсь в этом. Даже сжатие и распаковка изображения, ничего не делая с ним, теряет информацию. Я подозреваю, что любые алгоритмы для манипулирования сжатыми изображениями будут безнадежно убыточными.

Сказав это, это может быть технически возможно. Например, вращение преобразования Фурье также поворачивает исходное изображение. Но практическое сжатие изображений обычно не так просто, как вычисление преобразования Фурье.

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

1 голос
/ 29 марта 2010

Ключ никогда не будет полностью декодировать все изображение в память в полном размере.

  1. Если вам нужно отобразить изображение, нет причин делать это в полном размере - дисплей на iPhone слишком мал, чтобы воспользоваться этим. Для объектов изображения, предназначенных для отображения, декодируйте изображение в уменьшенном виде.

  2. Для обработки вам потребуется написать собственный код, который работает с потоком пикселей, а не с массивом в памяти. Я не знаю, доступно ли это уже на iPhone, но вы можете написать это самостоятельно, написав напрямую в API библиотеки libpng.

Например, ваш код сейчас, вероятно, выглядит примерно так (псевдокод)

img = ReadImageFromFile("image.png")
img2 = RotateImage(img, 90)
SaveImage(img2, "image2.png")

Главное, что нужно понять, это то, что в данном случае img - это не данные в файле PNG (2 МБ), а полностью несжатое изображение (~ 6 МБ). RotateImage (или как он там называется) возвращает другое изображение примерно такого же размера. Если вы увеличиваете масштаб, это еще хуже.

Вы хотите, чтобы код выглядел более похожим на это (но, возможно, для этого не было бы никаких API-интерфейсов - вам, возможно, придется написать его самостоятельно)

imgPixelGetter = PixelDecoderFromFile("image.png")
imgPixelSaver = OpenImageForAppending("image2.png") 
w = imgPixelGetter.Width
h = imgPixelGetter.Height

// set up a 90 degree rotate
imgPixelSaver.Width = h
imgPixelSaver.Height = w

// read each vertical scanline of pixels
for (x = 0; x < w; ++x) {
    pixelRect = imgPixelGetter.ReadRect(x, 0, 1, h) // x, y, w, h
    pixelRect.Rotate(90); // it's now got a width of h and a height of 1
    imgPixelSaver.AppendScanLine(pixelRect)
}

В этом алгоритме у вас никогда не было всего изображения в памяти сразу - вы читали его по частям и сохраняли его. Вы можете написать аналогичные алгоритмы для масштабирования и обрезки.

Компромисс в том, что он будет медленнее, чем просто декодирование его в память - это зависит от формата изображения и кода, который выполняет ReadRect (). К сожалению, PNG не предназначен для такого вида доступа к пикселям.

...