static Image *ReadEMFImage(const ImageInfo *image_info, ExceptionInfo *exception) { Gdiplus::Bitmap *bitmap; Gdiplus::BitmapData bitmap_data; Gdiplus::GdiplusStartupInput startup_input; Gdiplus::Graphics *graphics; Gdiplus::Image *source; Gdiplus::Rect rect; GeometryInfo geometry_info; Image *image; MagickStatusType flags; register Quantum *q; register ssize_t x; ssize_t y; ULONG_PTR token; unsigned char *p; wchar_t fileName[MagickPathExtent]; assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); image=AcquireImage(image_info,exception); if (Gdiplus::GdiplusStartup(&token,&startup_input,NULL) != Gdiplus::Status::Ok) ThrowReaderException(CoderError, "GdiplusStartupFailed"); MultiByteToWideChar(CP_UTF8,0,image->filename,-1,fileName,MagickPathExtent); source=Gdiplus::Image::FromFile(fileName); if (source == (Gdiplus::Image *) NULL) { Gdiplus::GdiplusShutdown(token); ThrowReaderException(FileOpenError,"UnableToOpenFile"); } image->resolution.x=source->GetHorizontalResolution(); image->resolution.y=source->GetVerticalResolution(); image->columns=(size_t) source->GetWidth(); image->rows=(size_t) source->GetHeight(); if (image_info->density != (char *) NULL) { flags=ParseGeometry(image_info->density,&geometry_info); image->resolution.x=geometry_info.rho; image->resolution.y=geometry_info.sigma; if ((flags & SigmaValue) == 0) image->resolution.y=image->resolution.x; if ((image->resolution.x > 0.0) && (image->resolution.y > 0.0)) { image->columns=(size_t) floor((Gdiplus::REAL) source->GetWidth() / source->GetHorizontalResolution() * image->resolution.x + 0.5); image->rows=(size_t)floor((Gdiplus::REAL) source->GetHeight() / source->GetVerticalResolution() * image->resolution.y + 0.5); } } bitmap=new Gdiplus::Bitmap((INT) image->columns,(INT) image->rows, PixelFormat32bppARGB); graphics=Gdiplus::Graphics::FromImage(bitmap); graphics->SetInterpolationMode(Gdiplus::InterpolationModeHighQualityBicubic); graphics->SetSmoothingMode(Gdiplus::SmoothingModeHighQuality); graphics->SetTextRenderingHint(Gdiplus::TextRenderingHintClearTypeGridFit); graphics->Clear(Gdiplus::Color((BYTE) ScaleQuantumToChar( image->background_color.alpha),(BYTE) ScaleQuantumToChar( image->background_color.red),(BYTE) ScaleQuantumToChar( image->background_color.green),(BYTE) ScaleQuantumToChar( image->background_color.blue))); graphics->DrawImage(source,0,0,(INT) image->columns,(INT) image->rows); delete graphics; delete source; rect=Gdiplus::Rect(0,0,(INT) image->columns,(INT) image->rows); if (bitmap->LockBits(&rect,Gdiplus::ImageLockModeRead,PixelFormat32bppARGB, &bitmap_data) != Gdiplus::Ok) { delete bitmap; Gdiplus::GdiplusShutdown(token); ThrowReaderException(FileOpenError,"UnableToReadImageData"); } image->alpha_trait=BlendPixelTrait; for (y=0; y < (ssize_t) image->rows; y++) { p=(unsigned char *) bitmap_data.Scan0+(y*abs(bitmap_data.Stride)); if (bitmap_data.Stride < 0) q=GetAuthenticPixels(image,0,image->rows-y-1,image->columns,1,exception); else q=GetAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (Quantum *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { SetPixelBlue(image,ScaleCharToQuantum(*p++),q); SetPixelGreen(image,ScaleCharToQuantum(*p++),q); SetPixelRed(image,ScaleCharToQuantum(*p++),q); SetPixelAlpha(image,ScaleCharToQuantum(*p++),q); q+=GetPixelChannels(image); } if (SyncAuthenticPixels(image,exception) == MagickFalse) break; } bitmap->UnlockBits(&bitmap_data); delete bitmap; Gdiplus::GdiplusShutdown(token); return(image); }
int DrawSdk::Image::WriteScaledImageFile(WCHAR* scaledImageName, float scaleX, float scaleY, const WCHAR* format) { int hr = S_OK; // // Starting the Gdiplus machine should be executed outside of this method // Gdiplus::GdiplusStartupInput gdiplusStartupInput; // ULONG_PTR gdiplusToken; // Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); Gdiplus::ImageCodecInfo *pImageCodecInfo = NULL; CLSID *pClsid = NULL; HDC hdc = CreateCompatibleDC(NULL); // Get the encoder CLSID depending on the image format (image/jpeg, image/gif, image/png) UINT num = 0; UINT size = 0; Gdiplus::GetImageEncodersSize(&num, &size); if (size == 0) hr = -1; // Failure if (SUCCEEDED(hr)) { pImageCodecInfo = (Gdiplus::ImageCodecInfo*)(malloc(size)); if (pImageCodecInfo == NULL) hr = -1; // Failure } if (SUCCEEDED(hr)) { Gdiplus::GetImageEncoders(num, size, pImageCodecInfo); for(int j = 0; j < num; ++j) { if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 ) { pClsid = &pImageCodecInfo[j].Clsid; break; // Success } } if (pClsid == NULL) hr = -1; // Failure } // Bugfix 5301: // If 'gdipImage_' is NULL then it was not kept in memory and therefore // a temporary Gdiplus::Image object is created for the rescaling. // This avoids having too much image data in the memory. Gdiplus::Image *tmpImage = NULL; if (SUCCEEDED(hr) && gdipImage_ == NULL) { // convert char-String in WCHAR-String int iStringLength = _tcslen(imageName_) + 1; WCHAR *wcFilename = (WCHAR *)malloc(iStringLength*sizeof(WCHAR)); #ifdef _UNICODE wcscpy(wcFilename, imageName_); #else MultiByteToWideChar( CP_ACP, 0, imageName, iStringLength, wcFilename, iStringLength); #endif tmpImage = new Gdiplus::Image(wcFilename, FALSE); if (wcFilename) free(wcFilename); } else { tmpImage = gdipImage_; } if (SUCCEEDED(hr) && tmpImage != NULL) { // Resize the image by scaling factors Gdiplus::REAL destWidth = scaleX * this->GetWidth(); Gdiplus::REAL destHeight = scaleY * this->GetHeight(); // If no correct size is defined in the object queue, use the real image size instead if ( (this->GetWidth() <= 0.0f) && (this->GetHeight() <= 0.0f) ) { destWidth = scaleX * tmpImage->GetWidth(); destHeight = scaleY * tmpImage->GetHeight(); } // At least we have to write one pixel if (destWidth < 1.0f) destWidth = 1.0f; if (destHeight < 1.0f) destHeight = 1.0f; Gdiplus::Bitmap scaledImage((int)(destWidth + 0.5f), (int)(destHeight + 0.5f)); scaledImage.SetResolution(tmpImage->GetHorizontalResolution(), tmpImage->GetVerticalResolution()); Gdiplus::Graphics grPhoto(&scaledImage); grPhoto.SetCompositingQuality(Gdiplus::CompositingQualityHighSpeed); grPhoto.SetCompositingMode(Gdiplus::CompositingModeSourceOver); grPhoto.SetInterpolationMode(Gdiplus::InterpolationModeHighQualityBicubic); Gdiplus::Rect destRect(0, 0, (int)(destWidth + 0.5f), (int)(destHeight + 0.5f)); hr = grPhoto.DrawImage(tmpImage, destRect, 0, 0, tmpImage->GetWidth(),tmpImage->GetHeight(), Gdiplus::UnitPixel); // Write the scaled image to a file if (SUCCEEDED(hr)) hr = scaledImage.Save(scaledImageName, pClsid, NULL); } // Cleanup if (hdc) { ::DeleteDC(hdc); hdc = NULL; } if (pImageCodecInfo) { free(pImageCodecInfo); pImageCodecInfo = NULL; } if (tmpImage != NULL && tmpImage != gdipImage_) delete tmpImage; // // Stop the Gdiplus machine --> this should be executed outside of this method (see above) // Gdiplus::GdiplusShutdown(gdiplusToken); return hr; }