Image::Buffer * WIC::Api::CreateImage(char * data, unsigned dataSize, unsigned w, unsigned h, Image::Format format) { IWICBitmap * bitmap = 0; factory->CreateBitmap(w, h, IMAGE_FORMAT_TO_WIC_GUID[format], WICBitmapCacheOnLoad, &bitmap); if(!bitmap) return 0; WICRect lockRect = { 0, 0, w, h }; IWICBitmapLock * lock = 0; bitmap->Lock(&lockRect, WICBitmapLockWrite, &lock); if(!lock) { bitmap->Release(); return 0; } unsigned bufferSize = 0; WICInProcPointer dataPointer = 0; lock->GetDataPointer(&bufferSize, &dataPointer); memcpy(dataPointer, data, dataSize); lock->Release(); lock = 0; if(format != Image::Format_4x8intRGBA) { IWICBitmapSource * convertedSource = 0; WICConvertBitmapSource(GUID_WICPixelFormat32bppRGBA, bitmap, &convertedSource); bitmap->Release(); bitmap = 0; if(!convertedSource) return 0; // Create the bitmap from the image frame. factory->CreateBitmapFromSource( convertedSource, // Create a bitmap from the image frame WICBitmapCacheOnDemand, // Cache metadata when needed &bitmap); // Pointer to the bitmap convertedSource->Release(); if(!bitmap) return 0; } bitmap->Lock(&lockRect, WICBitmapLockWrite, &lock); if(!lock) { bitmap->Release(); return 0; } return new WIC::Buffer(bitmap, lock, w, h); }
Image::Buffer * WIC::Api::CreateImage(char * buffer, unsigned bufferLength) { if(!factory) return 0; // Create input stream for memory IWICStream * stream = 0; factory->CreateStream(&stream); if(!stream) return 0; stream->InitializeFromMemory((unsigned char*)(buffer), static_cast<DWORD>(bufferLength)); IWICBitmapDecoder * decoder = 0; factory->CreateDecoderFromStream(stream, 0, WICDecodeMetadataCacheOnDemand, &decoder); if(!decoder) return 0; IWICBitmapFrameDecode * bitmapSource = 0; decoder->GetFrame(0, &bitmapSource); if(!bitmapSource) { decoder->Release(); return 0; } IWICBitmapSource * convertedSource = 0; WICConvertBitmapSource(GUID_WICPixelFormat32bppRGBA, bitmapSource, &convertedSource); bitmapSource->Release(); if(!convertedSource) { decoder->Release(); return 0; } // Create the bitmap from the image frame. IWICBitmap * bitmap = 0; factory->CreateBitmapFromSource( convertedSource, // Create a bitmap from the image frame WICBitmapCacheOnDemand, // Cache metadata when needed &bitmap); // Pointer to the bitmap convertedSource->Release(); decoder->Release(); if(!bitmap) return 0; unsigned width = 0, height = 0; bitmap->GetSize(&width, &height); WICRect lockRect = { 0, 0, width, height }; IWICBitmapLock * lock = 0; bitmap->Lock(&lockRect, WICBitmapLockWrite, &lock); if(!lock) { bitmap->Release(); return 0; } return new WIC::Buffer(bitmap, lock, width, height); }
// 解码照片的基础位图文件的. HRESULT VideoEncoder::DecodeFrame(Photo* pPhoto, BYTE** ppOutputBitmap, int* pBitmapSize) { HRESULT hr = S_OK; IWICBitmapDecoder *pDecoder = nullptr; IWICBitmapFrameDecode *pFrame = nullptr; IWICBitmap* pSourceBitmap = nullptr; IWICBitmapLock* pLock = nullptr; BYTE* pSourceBuffer = nullptr; BYTE* pDestinationBuffer = nullptr; UINT pixelWidth; UINT pixelHeight; WICRect lockRect; *ppOutputBitmap = nullptr; hr = m_pIWICFactory->CreateDecoderFromFilename( pPhoto->GetFile().c_str(), nullptr, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &pDecoder ); CheckHR(hr); this->m_logFileStream << "WIC解码器创建成功." << endl; GUID containerFormat; CheckHR(pDecoder->GetContainerFormat(&containerFormat)); // 我们仅支持jpg 文件. if (containerFormat != GUID_ContainerFormatJpeg) { this->m_logFileStream << "仅支持jpeg文件." << endl; return E_NOTSUPPORTEDFORMAT; } // 我们仅支持jpg 文件. 因此只有一桢. CheckHR(pDecoder->GetFrame(0, &pFrame)); // TODO: 目前我们需要所有照片有相同的大小. // 如果需求在将来发生变化,修改代码. pFrame->GetSize(&pixelWidth, &pixelHeight); if (pixelWidth != this->m_frameWidth || pixelHeight != this->m_frameHeight) { this->m_logFileStream << "所有的照片必须使用固定的大小." << endl; return E_IMAGESIZEINCORRECT; } // 创建源位图对象. CheckHR(this->m_pIWICFactory->CreateBitmapFromSource(pFrame, WICBitmapCacheOnLoad, &pSourceBitmap)); this->m_logFileStream << "位图资源创建成功." << endl; lockRect.X = 0; lockRect.Y = 0; lockRect.Width = pixelWidth; lockRect.Height = pixelHeight; CheckHR(pSourceBitmap->Lock(&lockRect, WICBitmapLockWrite, &pLock)); UINT sourceBufferSize; CheckHR(pLock->GetDataPointer(&sourceBufferSize, &pSourceBuffer)); // Jpg BGR 位图转换 RGBA 格式. UINT destinationBufferSize = sourceBufferSize / 3 * 4; pDestinationBuffer = new BYTE[destinationBufferSize]; for (UINT i = 0, j = 0; i < sourceBufferSize; i+=3, j+=4) { pDestinationBuffer[j] = pSourceBuffer[i]; // R pDestinationBuffer[j + 1] = pSourceBuffer[i + 1]; // G pDestinationBuffer[j + 2] = pSourceBuffer[i + 2]; // B pDestinationBuffer[j + 3] = 255; // A } *ppOutputBitmap = pDestinationBuffer; *pBitmapSize = destinationBufferSize; cleanup: if (!SUCCEEDED(hr)) { DWORD error = GetLastError(); this->m_logFileStream << "意外错误: " << error << endl; this->m_logFileStream << "HResult是: " << hr << endl; } if (pSourceBuffer != nullptr) { // 删除pSourceBuffer; } SafeRelease(&pDecoder); SafeRelease(&pFrame); SafeRelease(&pSourceBitmap); SafeRelease(&pLock); return hr; }