Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > Уменьшение картинки с сохранением пропорций


Автор: mr.Anderson 23.6.2007, 14:20
Ситуация такая. Я пишу фотоальбом. При поиске/импорте фотографий программа должна их отобразить в виде маленьких миниатюр. Для сего нужно, чтобы реальные изображения с компа прорисовались сначала на TBitmap'е, потом в нем же уменьшились, а потом уже отобразились для юзера. Как это сделать? Мне нужно, чтобы изображение было, скажем, не более 180px в высоту и не более 200px в ширину. Плюс должны сохраняться пропорции изображения.

Со всем этим хорошо справляется свойство Stretch у TImage, но в этом случае, если, скажем, предположить, что в программу загружено 1000 фотографий с разрешением 3000х4000 пикселов, то все эти фотки должны будут по сути находиться в памяти (ведь Stretch только визуально уменьшает изображение, а в памяти оно остается в первозданном виде и первозданном весе/размере), а значит, потребуется просто дикое количество памяти. Значит, Stretch не особо подходит. Как быть?

Автор: zkv 23.6.2007, 16:15
В памяти явно надо хранить thumbnail'ы изображений (уменьшенные копии), а сами фотографии открывать по необходимости, при первой же возможности закрывать. Сделать эти копии можно множеством способов, что удобнее использовать для Билдера - не знаю, для МФС куча примеров http://www.codeproject.com/info/search.asp?cats=2&searchkw=thumbnail&Submit1=Search&author=&sd=15+Nov+1999&ed=23+Jun+2007, но можно и самому сочинить что-нить типа: открываем картинку, рисуем на растр в памяти ее уменьшенную копию, закрываем картинку, пошли за следующей. 

Но вот несколько пугают эти цифры 
Цитата(mr.Anderson @  23.6.2007,  14:20 Найти цитируемый пост)
что в программу загружено 1000 фотографий с разрешением 3000х4000 пикселов

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

Автор: mr.Anderson 23.6.2007, 16:27
Цитата
рисуем на растр в памяти ее уменьшенную копию

В этом и состоит вопрос. Как? smile

Автор: jonie 23.6.2007, 17:41
StretchBlt() хотя бы в MSDN посмотри...

Автор: Klin 24.6.2007, 20:35
имхо какие функции не используй, все равно файл открывать придется (и загружать память программы). 

Автор: mr.Anderson 24.6.2007, 21:09
Klin, вопрос не в том, чтобы файл загружать. Просто если во все TImage загрузить такого размера изображения, получится, мягко говоря, накладно для памяти. А если использовать один TImage в качестве буфера, а на реальных имагах отображать только на Canvas, то расход памяти в процессе работы программы будет совсем небольшим.

Порылся с функциями. Я вообще в первом посте не о том речь завел. smile Какой Stretch, о Proportional речь. Если его врубить, изображение подгонится по размеру имага с сохранением пропорций.

Теперь формулировка задачи поточнее: надо загрузить в буферный TImage (невидимый, соответственно) большое изображение, затем сделать его нормальных размеров через Proportional, затем отрисовать на целевом имаге на Canvas. Я сделать этого почему-то не смог, прошу вашей помощи.

Автор: Klin 24.6.2007, 22:23
Ну енто воще элементарно smile

Код

 #include <jpeg.hpp> //  подключаем библиотеку для работы
  . . . . . . . . .
 TJPEGImage * Image = new TJPEGImage; // создаем временный JPEG
 Image->LoadFromFile("I:\\1.jpg"); // загружаем изображения
 Graphics::TBitmap * Bitmap = new Graphics::TBitmap; // временный битмап
 Bitmap->Assign(Image); // загружаем в него наш JPEG
 int myX = 0, myY = 0; // наши новые координаты
 int StepX = Image->Height/100, StepY = Image->Width/100; // рассчитываем шаг
 for (int x = 0; x<=Image->Width; x+=StepX) { // проходим по X
 myY = 0;
  for (int y = 0; y<=Image->Height; y+=StepY) { // проходим по Y
   Canvas->Pixels[myX][myY] = Bitmap->Canvas->Pixels[x][y]; // читаем и записываем пикселы X и Y
   myY++;
  }
  myX++;
 }
 delete Image; // очищаем память


Далее можем изменить место вставки, путь и т.п. Вроде все просто, или я опять че-то не понял   smile

Добавлено через 1 минуту и 27 секунд
да и в строчке номер 8 также определяется размер нового минисайза.

Автор: Lazin 25.6.2007, 08:33
Цитата

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

Зачем использовать TImage в качестве буфера, для этого есть TPicture. Вообще если эскизы изображений создавать каждый раз при запуске программы, то будет страшно тормозить. Обычно их кэшируют, и обновляют только при добавлении файлов. Винда создаёт в каждой папке с изображениями файл Thumbs.db именно для этого. Еще можно не обрабатывать сразу все доступные изображения, а только те которые отображаются на экране, это должно сэкономить часть ресурсов.
Цитата

Ну енто воще элементарно

Только на выходе должно получится что угодно кроме эскиза изображения. Для изображений разного размера получатся эскизы разного размера, совсем непохожие на оригинал.
Код

 #include <jpeg.hpp> //  подключаем библиотеку для работы
  . . . . . . . . .
 TJPEGImage * Image = new TJPEGImage; // создаем временный JPEG
 Image->LoadFromFile("1.jpg"); // загружаем изображения
 Graphics::TBitmap* bmp = new Graphics::TBitmap();
 TRect r(0,0,Image->Width*0.2,Image->Height*0.2);
 bmp->Height = r.Height();
 bmp->Width  = r.Width();
 bmp->Canvas->StretchDraw(r,Image);
 Image1->Picture->Bitmap->Assign(bmp);//показываем результат
 delete bmp;
 delete Image;

Автор: Alexeis 25.6.2007, 09:28
  Есть еще хороший вариант. Если это фотка, то такой жпег обычно содержит в себе еще Thumbnail в формате jpeg. Нужно залезть в EXIF и просто оттуда его извлечь.

Автор: Klin 25.6.2007, 10:53
Alexeis, случайно не знаете как извлечь? Хоть вариант не прет для остальных форматов...

Добавлено через 1 минуту и 7 секунд
воооо еще нарыл smile

Только для JPEG. Есть свойство Scale, оно и изменяет размер JPEG до нужного, сечас реализуем smile

Автор: Klin 25.6.2007, 11:17
ps 
Цитата(mr.Anderson @  24.6.2007,  22:09 Найти цитируемый пост)
нормальных размеров через Proportional, 

имхо тоже только визуалка.

Автор: Alexeis 25.6.2007, 11:24
Цитата(Klin @  25.6.2007,  10:53 Найти цитируемый пост)
Хоть вариант не прет для остальных форматов...

  Это не базовый вариант, а дополнительный, который позволит значительно сохранить время обработки тех картинок где есть Thumbnail ы. К сожалению компоненты встречал только на делфи. На самом деле формат EXIF не так уж сложен, так что если есть желание и время, то можно самому достать.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)