В Symbian OS предпочтительным способом работы с изображением является создание MBM (Multi-Bitmap file) и динамическое получение доступа к необходимому изображению из MBM. MBM позволяет хранить несколько изображений в одном файле. MBM может существовать либо в форме хранилища файлов либо в виде ROM типа изображения. MBM ROM изображение не сжимается, поэтому доступ к нему не требует дополнительных затрат оперативной памяти. В случае файлового хранилища изображение по-умолчанию подвергается компрессии, поэтому при обращении к нему необходима дополнительная оперативная память для проведения декомпрессии. По умолчанию MBM создается в форме файлового хранилища.

MBM файлы создаются из Windows bitmaps с помощью специального конвертераbmconv. Bmconv можно использовать либо напрямую из командной строки либо неявно, поместив описание изображения в проект (файл *.mmp) и выполнив его компиляцию (изображение будет создано в папке, указанной в TARGETPATH).

// MyGame.mmp
START BITMAP MyGame.mbm
HEADER
TARGETPATH..\..\..\..\wins\c\system\apps\MyGame
SOURCEPATH..\MyBitmaps
// тип палитры и файл с изображением
SOURCE c12 image1.bmp
SOURCE c12 image2.bmp
SOURCE c12 image3.bmp
END

Каждому изображению присваивается ID номер на основании файла mmp. ID номера генерируются в файл mbg, который располагается в папке include (epoc32\include). Доступ к изображению из mbm файла можно получить по этому ID номеру. Каждый ID создается автоматически и имеет следующий формат: EMbm<MBM file name><bitmap file name>. Приведем пример: EMbmMygameImage1.

В приведенном ниже примере осуществляется доступ к изображению, расположенному в mbm фале.

#include <mygame.mbg> // генерируется при трансляции
#include <aknutils.h> // для CompleteWithAppPath()
CFbsBitmap* CMyGameView::LoadMyBitmapL()
{
// Задаем имя MBM файла
_LIT(KMBMFileName,"MyGame.mbm");
TFileName mbmFileName(KMBMFileName);
CompleteWithAppPath(mbmFileName);
// Загружаем изображение из mbm
CFbsBitmap* bitmap=new(ELeave) CFbsBitmap();
CleanupStack::PushL(bitmap);
User::LeaveIfError(bitmap->Load(mbmFileName, EMbmMygameImage1));
CleanupStack::Pop();// bitmap
return bitmap;
}</aknutils.h></mygame.mbg>

После того, как изображение загружено, его можно вывести на экран, например, с помощью BitBlt:

void CMyGameView::Draw(const TRect&amp;/*aRect*/)const
{
// Получаем доступ к графическому контексту системы
CWindowGc&amp; gc= SystemGc();
// Выводим изображение на экран
gc.BitBlt( TPoint(10,10), iMyShipBitmap);
}

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

void CMyGameView::Draw(const TRect&amp;/*aRect*/)const
{
// Получаем доступ к графическому контексту
CWindowGc&amp; gc= SystemGc();
// Выводим частично прозрачное изображение
gc.BitBltMasked( TPoint(10,10), iMyShipBitmap, iMyShipRect,
iMyShipMask, EFalse);
}

Частично прозрачные изображения используются, когда изображенный на рисунке объект имеет непрямоугольную форму и на его заднем плане должен быть виден фон.

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

Преобразование можно реализовать с помощью временных файлов:

CFbsBitmap* CMyGameView::LoadAndConvertBitmapL(Const TDesC&amp; aFileName, TInt aBitmapId)
{
// Загружаем оригинальное изображение
CFbsBitmap* originalBitmap=new( ELeave) CFbsBitmap();
CleanupStack::PushL( originalBitmap);
User::LeaveIfError( originalBitmap->Load( aFileName, aBitmapId, EFalse));
// Создаем новое изображение, графическое устройство и контекст
CFbsBitmap* newBitmap=new( ELeave) CFbsBitmap();
CleanupStack::PushL( newBitmap);
newBitmap->Create( originalBitmap->SizeInPixels(),Window()->DisplayMode());
CFbsBitmapDevice* graphicsDevice= CFbsBitmapDevice::NewL(bitmapConverted);
CleanupStack::PushL( graphicsDevice);
CFbsBitGc* graphicsContext;
User::LeaveIfError( graphicsDevice->CreateContext(graphicsContext));
// Копируем исходное изображение во вновь созданное
// (фактически делаем конвертирование)
bitmapContext->BitBlt( TPoint(0,0), originalBitmap);
CleanupStack::Pop(3);
delete bitmapContext;
delete bitmapDevice;
delete originalBitmap;
return newBitmap;
}

В примере имя файла и ID передаются как параметры, затем осуществляется загрузка из MBM. Для преобразования изображения к палитре экрана создается новое изображение с требуемой палитрой и в него копируется исходное.

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

  • Метод CMdaBitmapRotator используется для поворота изображения на заданный угол.
  • Метод CMdaBitmapScaler используется для масштабирования изображения.

Начиная с Series 60 Developer Platform 2.0 вышеупомянутые методы считаются устаревшими, и разработчики должны использовать следующие:

  • CbitmapRotator.
  • CbitmapScaler.

По своей природе эти методы являются асинхронными, то есть для их использования необходим класс-потомок MMdaImageUtilObserver, который будет сообщать, когда преобразование завершено.

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

Для прямого доступа к рисунку используйте метод CFbsBitmap::DataAddress, который возвращает указатель на начало его данных (верхний левый угол). Нужно быть осторожным при прямой работе с изображением, поскольку его расположение в памяти может измениться в результате ее дефрагментации. Это значит, что динамическая память должна быть заблокирована перед доступом к ней. Это можно сделать с помощью метода TBitmapUtil, или в Series 60 Developer Platform 2.0 методами LockHeap и UnlockHeap класса CFbsBitmap.

При работе с изображением напрямую Вы должны иметь информацию о его формате. Например, в 16-битном изображении каждый пиксель имеет формат 5-6-5 (биты красного - биты зеленого - биты синего), а в 12-битном - формат 4-4-4.

В следующем примере показана реализация простого эффекта - красная составляющего каждого пикселя увеличивается.

void CMyGameView::DoMyBitmapEffect(CFbsBitmap* aBitmap)
{
// Блокируем динамическую память
// для series 60 2.0 нужно использовать:
// aBitmap->LockHeap();
// а для series 60 1.0:
TBitmapUtil bitmapUtil(aBitmap);
bitmapUtil.Begin( TPoint(0,0));
 
// Изменяем рисунок
TSize bitmapSize= aBitmap->SizeInPixels();
// ЗАМЕЧАНИЕ: TUint16* применим лишь для 16bit изображений;
TUint16* bitmapData=(TUint16*)aBitmap->DataAddress();
for( TInt y=0; y< bitmapSize.iHeight; y++);
{
for( TInt x=0; x< bitmapSize.iWidth; x++)
{
// Увеличиваем красную составляющую рисунка
*bitmapData=(*bitmapData&amp;31)|// blue
((*bitmapData>>5)&amp;63)|// green
((*bitmapData>>11)&amp;31+1);// red
bitmapData++;
}
}
// Разблокируем динамическую память
// для series 60 1.0:
bitmapUtil.End();
// для 60 2.0 нужно использовать:
// aBitmap->UnlockHeap();
}

Для Series 60 Developer Platform 2.0 доступны более продвинутые методы 2D Акселерации. Например, прозрачность можно реализовать без использования маски. Об 2D акселерации будет рассказано позже.


Перевод:aRix




Наши соцсети

Подписаться Facebook Подписаться Вконтакте Подписаться Twitter Подписаться Google Подписаться Telegram

Популярное

Ссылки

Новости [1] [2] [3]... Android/ iOS/ J2ME[1] [2] [3]) Android / Архив

Рейтинг@Mail.ru Яндекс.Метрика
MobiLab.ru © 2005-2018
При использовании материалов сайта ссылка на www.mobilab.ru обязательна