обойти некоторые (многие) проблемы с API-интерфейсом Camera Actions в системах Windows 8,
Я решил создать собственное расширение для работы с камерой.
Прямо сейчас часть камеры и весь клей для связи с AIR Runtime фактически работают, поэтому нажатие на кнопку в AIR откроет новое окно Windows, которое вернет System :: Drawing :: Bitmap.
Моя задача была бы сейчас
а) создать объект FREBitmapData и
б) Заполнить BitmapData из Windows Bitmap.
Должно быть, это было легко, подумал я много дней назад … Поскольку я не очень хорошо знаком с C ++, у меня это вообще не получалось.
Вот что я попробовал до сих пор:
bmp = form1->bitmap; // bmp is a handle to the System::Drawing::Bitmap returned from the external window
// Lock the bitmap's bits.
Rectangle rect = Rectangle(0, 0, bmp->Width, bmp->Height);
System::Drawing::Imaging::BitmapData^ bmpData = bmp->LockBits(rect, System::Drawing::Imaging::ImageLockMode::ReadWrite, bmp->PixelFormat);
// Get the address of the first line.
IntPtr ptr = bmpData->Scan0;
// Declare an array to hold the bytes of the bitmap.
// This code is specific to a bitmap with 24 bits per pixels.
int inputLength = Math::Abs(bmpData->Stride) * bmp->Height;
array<Byte>^ input = gcnew array<Byte>(inputLength);
// Copy the RGB values into the array.
System::Runtime::InteropServices::Marshal::Copy(ptr, input, 0, inputLength);
// Unlock the bits.
bmp->UnlockBits(bmpData);
// Create a FREByteArray to hold the data.
// Don't know, if this is necessary
FREObject* outputObject;
FREByteArray* outputBytes = new FREByteArray;
outputBytes->length = inputLength;
outputBytes->bytes = (uint8_t *) &input;
FREAcquireByteArray(outputObject, outputBytes);
// now copy it over
memcpy(outputBytes->bytes, &input, inputLength);
FREReleaseByteArray(outputObject);
// we create a new instance of BitmapData here,
// as we cannot simply pass it over in the args,
// because we don't know it's correct size at extension creation
FREObject* width;
FRENewObjectFromUint32(bmp->Width, width);
FREObject* height;
FRENewObjectFromUint32(bmp->Height, height);
FREObject* transparent;
FRENewObjectFromBool(uint32_t(0), transparent);
FREObject* fillColor;
FRENewObjectFromUint32(uint32_t(0xFFFFFF), fillColor);
FREObject obs[4] = { width, height, transparent, fillColor };
// we create some Actionscript Intsances here, we want to send back
FREObject* asBmpObj;
FRENewObject("BitmapData", 4, obs, asBmpObj, NULL);
// Now we have our AS bitmap data, copy bytes over
FREBitmapData* asData;
FREAcquireBitmapData(asBmpObj, asData);
// Now what? asData->bits32 won't accept array<Bytes> or any other value I've tried.
return asBmpObj;
Основная идея была:
а) выяснить размер и битовую глубину оригинального Win Bitmap (размер определяется разрешением камеры, выбранным в окне камеры)
б) записать его байты в массив. Преобразовать в 32 бит при необходимости. (Все еще отсутствует какая-либо идея.)
в) создать AS Bitmap того же размера. Битовая глубина всегда должна быть 32.
d) скопировать массив в AS Bitmap.
Но я просто не могу этого достичь.
Любой совет? Спасибо!
Я не думаю, что следующая прямая копия будет работать.
// Copy the RGB values into the array.
System::Runtime::InteropServices::Marshal::Copy(ptr, input, 0, inputLength);
Вы должны конвертировать пиксель за пикселем. Я не знаю, как преобразовать его в FREBitmapData. Вот примеры, вы можете следовать на MSDN
Я наконец-то понял:
приведенный ниже код не имеет отношения к преобразованию 24to32 бит, но на самом деле он хорошо работает в моем приложении, поэтому я подумал, что могу поделиться им:
FREObject launch(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])
{
System::Drawing::Bitmap^ windowsBitmap;
SKILLCamControl::CamControlForm^ form1;
form1 = gcnew SKILLCamControl::CamControlForm();
DialogResult dr;
// Show testDialog as a modal dialog and determine if DialogResult = OK.
dr = form1->ShowDialog();
if (dr == DialogResult::OK) {
windowsBitmap = form1->bitmap;
int bmpW = windowsBitmap->Width;
int bmpH = windowsBitmap->Height;
// we create a new instance of BitmapData here,
// as we cannot simply pass it over in the args,
// because we don't know it's correct size at extension creation
FREObject width;
FRENewObjectFromUint32( uint32_t(bmpW), &width);
FREObject height;
FRENewObjectFromUint32( uint32_t(bmpH), &height);
FREObject transparent;
FRENewObjectFromBool( uint32_t(0), &transparent);
FREObject fillColor;
FRENewObjectFromUint32( uint32_t(0xFF0000), &fillColor);
FREObject obs[4] = { width, height, transparent, fillColor };
FREObject freBitmap;
FRENewObject((uint8_t *)"flash.display.BitmapData", 4, obs, &freBitmap , NULL);
FREBitmapData2 freBitmapData;
FREAcquireBitmapData2(freBitmap, &freBitmapData);
// is inverted?
if (&freBitmapData.isInvertedY != (uint32_t*)(0) ) windowsBitmap->RotateFlip(RotateFlipType::RotateNoneFlipY);
int pixelSize = 4;
//Rect rect( 0, 0, freBitmap.width, freBitmap.height );
System::Drawing::Rectangle rect(0, 0, bmpW, bmpH);
BitmapData^ windowsBitmapData = windowsBitmap->LockBits(rect, ImageLockMode::ReadOnly, PixelFormat::Format32bppArgb);
for (int y = 0; y < bmpH ; y++)
{
//get pixels from each bitmap
byte* oRow = (byte*)windowsBitmapData->Scan0.ToInt32() + (y * windowsBitmapData->Stride);
byte* nRow = (byte*)freBitmapData.bits32 + (y * freBitmapData.lineStride32 * 4);
for (int x = 0; x < bmpW ; x++)
{
// set pixels
nRow[x * pixelSize] = oRow[x * pixelSize]; //B
nRow[x * pixelSize + 1] = oRow[x * pixelSize + 1]; //G
nRow[x * pixelSize + 2] = oRow[x * pixelSize + 2]; //R
}
}
// Free resources
FREReleaseBitmapData(freBitmap);
FREInvalidateBitmapDataRect(freBitmap, 0, 0, bmpW, bmpH);
windowsBitmap->UnlockBits(windowsBitmapData);
delete windowsBitmapData;
delete windowsBitmap;
return freBitmap;
}
else if (dr == DialogResult::Cancel)
{
return NULL;
}
return NULL;
}
Я сам не пользуюсь C ++, так что это не полный ответ, а просто кое-что для рассмотрения …
Растровые данные — это универсальные необработанные данные пикселей. Это должно быть проходимо в разных программах. Если вы на самом деле не создаете .BMP
файлы с заголовком и т.д ??
...that will return a System::Drawing::Bitmap
Означает ли это, что у вас есть растровые данные, хранящиеся в C ++ (как необработанные несжатые пиксели RGBA)? Если это так, то просто поместите это в byteArray и отправьте в AS3 или, если вы можете скопировать это растровое изображение в буфер обмена Windows, затем используйте AS3 для чтения из буфера обмена в новое растровое изображение AS3.
это может помочь вам:
AS3: Сериализация растровых изображений : Прокрутите вниз до раздела ByteArray to BitmapData (чтобы это работало, вы должны сначала сохранить байты растрового изображения C ++ в виде файла, называйте его как хотите, например, tempIMG.dat или myPIc.bin, или как угодно, поскольку расширение файла не имеет большого значения, если вам нужен загружаемый URL).