void CBalloonTip::InitIconImage() { HICON hIcon = LoadIcon(CPaintManagerUI::GetResourceDll(),MAKEINTRESOURCE(m_nIcon)); if (hIcon) { ICONINFO icInfo = { 0 }; if (::GetIconInfo(hIcon, &icInfo)) { BITMAP bitmap; GetObject(icInfo.hbmColor, sizeof(BITMAP), &bitmap); Bitmap* pBitmap = NULL; Bitmap* pWrapBitmap = NULL; if (bitmap.bmBitsPixel != 32) { pBitmap = Bitmap::FromHICON(hIcon); } else { pWrapBitmap = Bitmap::FromHBITMAP(icInfo.hbmColor, NULL); BitmapData bitmapData; Rect rcImage(0,0, pWrapBitmap->GetWidth(), pWrapBitmap->GetHeight()); pWrapBitmap->LockBits(&rcImage, ImageLockModeRead, pWrapBitmap->GetPixelFormat(), &bitmapData); pBitmap = new Bitmap(bitmapData.Width, bitmapData.Height, bitmapData.Stride, PixelFormat32bppARGB, (BYTE*)bitmapData.Scan0); pWrapBitmap->UnlockBits(&bitmapData); } //lpIconImage = pBitmap->Clone(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight(), PixelFormat32bppARGB); HBITMAP hBit ; pBitmap->GetHBITMAP(ARGB(0,0,0,0),&hBit); m_pPM->AddImage(_T("BalloonIcon"),hBit,pBitmap->GetWidth(),pBitmap->GetHeight(),TRUE); DeleteObject(icInfo.hbmColor); DeleteObject(icInfo.hbmMask); } DeleteObject(hIcon); } }
static bool ras_decode(Bitmap& target, Stream& stream) { // reset stream stream.Seek(0,Stream::START); // streamsize - headersize int size = stream.GetSize() - 32; if ( size < 1 ) return false; // read header uint32 magic = ReadBigEndian<uint32>(stream); uint32 width = ReadBigEndian<uint32>(stream); uint32 height = ReadBigEndian<uint32>(stream); uint32 bits = ReadBigEndian<uint32>(stream); /* uint32 length = */ ReadBigEndian<uint32>(stream); uint32 type = ReadBigEndian<uint32>(stream); uint32 maptype = ReadBigEndian<uint32>(stream); uint32 maplength = ReadBigEndian<uint32>(stream); // verify header if ( magic != 0x59a66a95 ) return false; if ( bits != 1 && bits != 8 && bits != 24 && bits != 32 ) return false; if ( type != 0 && type != 1 && type != 2 && type != 3 ) return false; // create bitmap switch ( bits ) { case 1: target = Bitmap(width,height,PIXELFORMAT_INTENSITY8); break; case 8: target = Bitmap(width,height,PIXELFORMAT_PALETTE8(NULL)); break; case 24: target = Bitmap(width,height,PIXELFORMAT_RGB888); break; case 32: target = Bitmap(width,height,PIXELFORMAT_ARGB8888); break; default: return false; } // read colormap switch ( maptype ) { // "none" - no palette case 0: { stream.Seek(maplength,Stream::CURRENT); break; } // "equal rgb" -mode palette case 1: { if ( bits != 8 || maplength > 768 ) return false; const PixelFormat& pxf = target.GetPixelFormat(); Color32* palette = pxf.GetPalette(); int count = static_cast<int>(maplength / 3); int i; for ( i=0; i<count; ++i ) palette[i].r = ReadBigEndian<uint8>(stream); for ( i=0; i<count; ++i ) palette[i].g = ReadBigEndian<uint8>(stream); for ( i=0; i<count; ++i ) palette[i].b = ReadBigEndian<uint8>(stream); for ( i=0; i<count; ++i ) palette[i].a = 0xff; break; } // "raw" -mode palette // TODO: this code has not been tested // (couldn't find files to test with or specification) // this is my best guess how the "raw" mode works! case 2: { if ( bits != 8 || maplength > 768 ) return false; const PixelFormat& pxf = target.GetPixelFormat(); Color32* palette = pxf.GetPalette(); int count = static_cast<int>(maplength / 3); for ( int i=0; i<count; ++i ) { palette[i].r = ReadBigEndian<uint8>(stream); palette[i].g = ReadBigEndian<uint8>(stream); palette[i].b = ReadBigEndian<uint8>(stream); palette[i].a = 0xff; } } // unknown fileformat default: return false; } // decode buffer int buffersize = stream.GetSize() - stream.GetOffset(); uint8* buffer = new uint8[buffersize]; stream.Read(buffer,buffersize); // read image uint8* image = target.GetImage(); int numpixel = width * height; if ( numpixel < 1 ) return false; switch ( bits ) { case 1: { switch ( type ) { case 0: case 1: case 3: { int ycount = static_cast<int>(height); while ( ycount-- ) { int bitcount = -1; uint8 v = 0; int xcount = static_cast<int>(width); while ( xcount-- ) { if ( bitcount < 0 ) { bitcount = 7; v = *buffer++; } *image++ = (v >> (bitcount--)) & 1 ? 0 : 255; } } break; } case 2: { // TODO: RLE decoder // TODO: special handling of 1 bit stream break; } } break; } case 8: { switch ( type ) { case 0: case 1: case 3: { memcpy(image,buffer,numpixel); break; } case 2: { // TODO: RLE decoder // TODO: RGB/BGR fix // TODO: test rasrle() rasrle(image,buffer,numpixel); break; } } break; } case 24: { switch ( type ) { case 0: case 1: { memcpy(image,buffer,numpixel*3); break; } case 2: { // TODO: RLE decoder // TODO: RGB/BGR fix // TODO: test rasrle() rasrle(image,buffer,numpixel*3); break; } case 3: { while ( numpixel-- ) { image[0] = buffer[2]; image[1] = buffer[1]; image[2] = buffer[0]; buffer += 3; image += 3; } break; } } break; } case 32: { switch ( type ) { case 0: case 1: { while ( numpixel-- ) { image[0] = buffer[1]; image[1] = buffer[2]; image[2] = buffer[3]; image[3] = buffer[0]; buffer += 4; image += 4; } break; } case 2: { // TODO: RLE decoder // TODO: RGB/BGR fix // TODO: test rasrle() rasrle(image,buffer,numpixel*4); break; } case 3: { while ( numpixel-- ) { image[0] = buffer[3]; image[1] = buffer[2]; image[2] = buffer[1]; image[3] = buffer[0]; buffer += 4; image += 4; } break; } } break; } } // free decode buffer delete[] buffer; return true; }
int loadImage(struct textureTableIndexStruct *tti, char *fname) { /* http://msdn.microsoft.com/en-us/library/ms536298(VS.85).aspx GDI+ Lockbits example - what this function is based on*/ /* http://www.microsoft.com/downloads/details.aspx?FamilyID=6a63ab9c-df12-4d41-933c-be590feaa05a&DisplayLang=en GDI+ redistributable download - gdiplus.dll 2MB */ if(!loaded) { initImageLoader(); loaded = 1; } // convert to wide char http://msdn.microsoft.com/en-us/library/ms235631(VS.80).aspx //fname = "C:/source2/freewrl/freex3d/tests/helpers/brick.png"; //fname = "junk.jpg"; //test failure condition size_t origsize = strlen(fname) + 1; char* fname2 = (char*) malloc(origsize); strcpy(fname2,fname); for(int jj=0;jj<strlen(fname2);jj++) if(fname2[jj] == '/' ) fname2[jj] = '\\'; const size_t newsize = 225; size_t convertedChars = 0; wchar_t wcstring[newsize]; //mbstowcs_s(&convertedChars, wcstring, origsize, fname, _TRUNCATE); #if _MSC_VER >= 1500 mbstowcs_s(&convertedChars, wcstring, origsize, fname2, _TRUNCATE); #else mbstowcs(wcstring, fname2, MB_CUR_MAX); #endif free(fname2); Bitmap *bitmap = NULL; Status stat; bitmap = Bitmap::FromFile(wcstring,false); //new Bitmap(wcstring); //or Bitmap::FromFile(wcstring,false); L"LockBitsTest1.bmp"); // verifying the success of constructors http://msdn.microsoft.com/en-us/library/ms533801(VS.85).aspx stat = bitmap->GetLastStatus(); // http://msdn.microsoft.com/en-us/library/ms535410(VS.85).aspx if(stat != Ok) return 0; //should come here if it can't find the image file BitmapData* bitmapData = new BitmapData; //#define verbose 1 #ifdef verbose printf("bitmap W=%d H=%d\n",bitmap->GetWidth(),bitmap->GetHeight()); /* http://msdn.microsoft.com/en-us/library/ms535387(VS.85).aspx GetPixelFormat http://msdn.microsoft.com/en-us/library/ms534412(v=VS.85).aspx pixelFormat constants http://msdn.microsoft.com/en-us/library/ms534136(v=VS.85).aspx Image::GetFlags ImageFlagsColorSpaceGRAY = 0x0040, */ UINT flags = bitmap->GetFlags(); printf("The value of flags, in hexadecimal form, is %x.\n", flags); // Is the ColorSpaceRGB flag set? if(flags & ImageFlagsColorSpaceRGB) printf("The ColorSpaceRGB flag is set.\n"); else if(flags & ImageFlagsColorSpaceGRAY) printf("The ColorSpaceGRAY flag is set.\n"); printf("bitmap format index =%d %d\n",bitmap->GetPixelFormat()%256,bitmap->GetPixelFormat()); if(Gdiplus::IsAlphaPixelFormat(bitmap->GetPixelFormat()) ) printf("has alpha channel\n"); else printf("no alpha channel\n"); if(Gdiplus::IsCanonicalPixelFormat(bitmap->GetPixelFormat()) ) printf("is canonical\n"); else printf("not canonical\n"); printf("Number of bits per pixel %d\n",Gdiplus::GetPixelFormatSize(bitmap->GetPixelFormat())); #endif #undef verbose bool flipVertically = true; Rect rect(0,0,bitmap->GetWidth(),bitmap->GetHeight()); if(flipVertically) bitmapData->Stride = -bitmap->GetWidth()*4; else bitmapData->Stride = bitmap->GetWidth()*4; bitmapData->Width = bitmap->GetWidth(); bitmapData->Height = bitmap->GetHeight(); bitmapData->PixelFormat = PixelFormat32bppARGB; int totalbytes = bitmap->GetWidth() * bitmap->GetHeight() * 4; //tti->depth; unsigned char * blob = (unsigned char*)malloc(totalbytes); if(flipVertically) bitmapData->Scan0 = &blob[bitmap->GetWidth()*bitmap->GetHeight()*4 + bitmapData->Stride]; else bitmapData->Scan0 = blob; // Lock a rectangular portion of the bitmap for reading. bitmap->LockBits( &rect, ImageLockModeRead|ImageLockModeUserInputBuf, PixelFormat32bppARGB, //PixelFormat24bppRGB, bitmapData); #ifdef verbose printf("The stride is %d.\n\n", bitmapData->Stride); printf("bitmapData W=%d H=%d\n",bitmapData->Width,bitmapData->Height); #endif #ifdef verbose // Display the hexadecimal value of each pixel in the 5x3 rectangle. UINT* pixels = (UINT*)bitmapData->Scan0; for(UINT row = 0; row < 23; ++row) { for(UINT col = 0; col < 5; ++col) { printf("%x\n", pixels[row * bitmapData->Stride / 4 + col]); } printf("- - - - - - - - - - \n"); } #endif //deep copy data so browser owns it (and does its FREE_IF_NZ) and we can delete our copy here and forget about it tti->x = bitmapData->Width; tti->y = bitmapData->Height; tti->frames = 1; tti->texdata = blob; if(!blob) printf("ouch in gdiplus image loader L140 - no image data\n"); //tti->hasAlpha = Gdiplus::IsAlphaPixelFormat(bitmapData->PixelFormat)?1:0; tti->hasAlpha = Gdiplus::IsAlphaPixelFormat(bitmap->GetPixelFormat())?1:0; //printf("fname=%s alpha=%ld\n",fname,tti->hasAlpha); #ifdef verbose for(UINT row = 0; row < 23; ++row) { for(UINT col = 0; col < 5; ++col) { //printf("%x\n", *(UINT*)&(tti->texdata[(row * bitmapData->Stride / 4 + col)*tti->depth])); printf("%x\n", *(UINT*)&(tti->texdata[(row * tti->x + col)*4])); //tti->depth])); } printf("- - - - - - - - - - \n"); } #endif tti->filename = fname; // wrong: tti->status = TEX_NEEDSBINDING; //make this the last thing you set, because another thread is watching ready to bind // wrong - let the calling function set the status otherwise textures disappear sometimes bitmap->UnlockBits(bitmapData); delete bitmapData; delete bitmap; //shutdownImageLoader(); //we'll keep it loaded if(0) { shutdownImageLoader(); loaded = 0; } return 1; }
HBITMAP CDpiHelper::CreateDeviceFromLogicalImage(HBITMAP _In_ hImage, ImageScalingMode scalingMode, Color clrBackground) { IfNullAssertRetNull(hImage, "No image given to convert"); // Instead of doing HBITMAP resizing with StretchBlt from one memory DC into other memory DC and HALFTONE StretchBltMode // which uses nearest neighbor resize algorithm (fast but results in pixelation), we'll use a GdiPlus image to do the resize, // which allows specifying the interpolation mode for the resize resulting in smoother result. VsUI::GdiplusImage gdiplusImage; // Attaching the bitmap uses Bitmap.FromHBITMAP which does not take ownership of the HBITMAP passed as argument. // DeleteObject still needs to be used on the hImage but that should happen after the Bitmap object is deleted or goes out of scope. // The caller will have to DeleteObject both the HBITMAP they passed in this function and the new HBITMAP we'll be returning when we detach the GDI+ Bitmap gdiplusImage.Attach(hImage); #ifdef DEBUG static bool fDebugDPIHelperScaling = false; WCHAR rgTempFolder[MAX_PATH]; static int imgIndex = 1; CStringW strFileName; CPath pathTempFile; if (fDebugDPIHelperScaling) { if (!GetTempPath(_countof(rgTempFolder), rgTempFolder)) *rgTempFolder = '\0'; strFileName.Format(_T("DPIHelper_%05d_Before.png"), imgIndex); pathTempFile.Combine(rgTempFolder, strFileName); gdiplusImage.Save(pathTempFile); } #endif Bitmap* pBitmap = gdiplusImage.GetBitmap(); PixelFormat format = pBitmap->GetPixelFormat(); const Color *pclrActualBackground = &clrBackground; InterpolationMode interpolationMode = GetInterpolationMode(scalingMode); ImageScalingMode actualScalingMode = GetActualScalingMode(scalingMode); if (actualScalingMode != ImageScalingMode::NearestNeighbor) { // Modify the image. If the image is 24bpp or lower, convert to 32bpp so we can use alpha values if (format != PixelFormat32bppARGB) { pBitmap->ConvertFormat(PixelFormat32bppARGB, DitherTypeNone, PaletteTypeCustom, nullptr/*ColorPalette*/, 0 /*alphaThresholdPercent - all opaque*/); } // Now that we have 32bpp image, let's play with the pixels // Detect magenta or near-green in the image and use that as background VsUI::GdiplusImage::ProcessBitmapBits(pBitmap, [&](ARGB * pPixelData) { if (clrBackground.GetValue() != TransparentColor.GetValue()) { if (*pPixelData == clrBackground.GetValue()) { *pPixelData = TransparentHaloColor.GetValue(); pclrActualBackground = &clrBackground; } } else { if (*pPixelData == MagentaColor.GetValue()) { *pPixelData = TransparentHaloColor.GetValue(); pclrActualBackground = &MagentaColor; } else if (*pPixelData == NearGreenColor.GetValue()) { *pPixelData = TransparentHaloColor.GetValue(); pclrActualBackground = &MagentaColor; } } }); } // Convert the GdiPlus image if necessary LogicalToDeviceUnits(&gdiplusImage, scalingMode, TransparentHaloColor); // Get again the bitmap, after the resize pBitmap = gdiplusImage.GetBitmap(); if (actualScalingMode != ImageScalingMode::NearestNeighbor) { // Now that the bitmap is scaled up, convert back the pixels. // Anything that is not fully opaque, make it clrActualBackground VsUI::GdiplusImage::ProcessBitmapBits(pBitmap, [&](ARGB * pPixelData) { if ((*pPixelData & ALPHA_MASK) != 0xFF000000) { *pPixelData = pclrActualBackground->GetValue(); } }); // Convert back to original format if (format != PixelFormat32bppARGB) { pBitmap->ConvertFormat(format, DitherTypeNone, PaletteTypeCustom, nullptr/*ColorPalette*/, 0 /*alphaThresholdPercent - all opaque*/); } } #ifdef DEBUG if (fDebugDPIHelperScaling) { strFileName.Format(_T("DPIHelper_%05d_After.png"), imgIndex++); pathTempFile.Combine(rgTempFolder, strFileName); gdiplusImage.Save(pathTempFile); } #endif // Get the converted image handle - this returns a new HBITMAP that will need to be deleted when no longer needed // Detach using TransparentColor (transparent-black). If the result bitmap is to be used with AlphaBlend, that function // keeps the background if the transparent pixels are black HBITMAP hBmpResult = gdiplusImage.Detach( TransparentColor ); // When the image has 32bpp RGB format, when we call GDI+ to return an HBITMAP for the image, the result is actually // an ARGB bitmap (with alpha bytes==0xFF instead of reserved=0x00). Many GDI functions work with it fine, but // adding it to an imagelist with ImageList_AddMasked will produce the wrong result, because the clrTransparent color // won't match any background pixels due to the alpha byte value. So we need to zero-out out those bytes... // If the bitmap was scaled with a bicubic/bilinear interpolation, the colors are interpolated with the clrBackground // which may be transparent, so the resultant image will have alpha channel of interest, and we'll return the image as is. if (format == PixelFormat32bppRGB) { BITMAP bmp = {0}; if (GetObject(hBmpResult, sizeof(bmp), &bmp) == sizeof(bmp) && bmp.bmBits != nullptr) { RGBQUAD* pPixels = reinterpret_cast<RGBQUAD*>(bmp.bmBits); for (int i=0; i< bmp.bmWidth * bmp.bmHeight; i++) { pPixels[i].rgbReserved = 0; } } } // Return the created image return hBmpResult; }
// Creates new GdiplusImage from logical to device units unique_ptr<VsUI::GdiplusImage> CDpiHelper::CreateDeviceFromLogicalImage(_In_ VsUI::GdiplusImage* pImage, ImageScalingMode scalingMode, Color clrBackground) { IfNullAssertRetNull(pImage, "No image given to convert"); // Get the original/logical bitmap Bitmap* pBitmap = pImage->GetBitmap(); IfNullAssertRetNull(pBitmap, "No image given to convert"); // Create a memory image scaled for size int deviceWidth = LogicalToDeviceUnitsX(pBitmap->GetWidth()); int deviceHeight = LogicalToDeviceUnitsY(pBitmap->GetHeight()); unique_ptr<VsUI::GdiplusImage> pDeviceImage(new VsUI::GdiplusImage()); pDeviceImage->Create( deviceWidth, deviceHeight, pBitmap->GetPixelFormat() ); if (!pDeviceImage->IsLoaded()) { VSFAIL("Failed to create scaled image, out of memory?"); return nullptr; } // Get a Graphics object for the device image on which we can paint unique_ptr<Graphics> pGraphics(pDeviceImage->GetGraphics()); if (pGraphics.get() == nullptr) { VSFAIL("Failed to obtain image Graphics"); return nullptr; } // Set the interpolation mode. InterpolationMode interpolationMode = GetInterpolationMode(scalingMode); pGraphics->SetInterpolationMode(interpolationMode); // Clear the background (used when scaling mode is not nearest neighbor) pGraphics->Clear(clrBackground); // Calculate the destination rectangle: full available space, except when keeping the image unscaled and just adding a border RectF rectD(0, 0, (float)deviceWidth, (float)deviceHeight); if (scalingMode == ImageScalingMode::BorderOnly || (scalingMode == ImageScalingMode::Default && m_PreferredScalingMode == ImageScalingMode::BorderOnly)) { rectD = RectF(0, 0, (float)pBitmap->GetWidth(), (float)pBitmap->GetHeight()); rectD.Offset( (float)((deviceWidth - pBitmap->GetWidth()) / 2), (float)((deviceHeight - pBitmap->GetHeight())/ 2) ); } // Define the source rectangle RectF rectS(0, 0, (float)pBitmap->GetWidth(), (float)pBitmap->GetHeight()); // Specify a source rectangle shifted by half of pixel to account for GDI+ considering the source origin the center of top-left pixel // Failing to do so will result in the right and bottom of the bitmap lines being interpolated with the graphics' background color, // and will appear black even if we cleared the background with transparent color. // The apparition of these artifacts depends on the interpolation mode, on the dpi scaling factor, etc. // E.g. at 150% DPI, Bicubic produces them and NearestNeighbor is fine, but at 200% DPI NearestNeighbor also shows them. // Many articles on the web talk about this problem, e.g. http://www.codeproject.com/Articles/14884/BorderBug rectS.Offset(-0.5f, -0.5f); // Draw the scaled bitmap in the device image pGraphics->DrawImage(pBitmap, rectD, rectS.X, rectS.Y, rectS.Width, rectS.Height, UnitPixel); // Return the new image return pDeviceImage; }
void ToolFilter::activate() { ChildCore *child = this->core->getActiveChild(); if( child != NULL ){ if( this->lastActivate == true && this->isLastActivate == false ){ this->lastActivate = false; return; } ToolFilter::Info fi; Bitmap *source = NULL; if( child->getWorkspace()->getSelection() != NULL ){ source = child->getWorkspace()->getSelectedProjection(NULL,COPCOP); } else { source = child->getWorkspace()->getSelectedLayer()->getRender(); source = source->Clone(Rect(0,0,source->GetWidth(),source->GetHeight()),source->GetPixelFormat()); } fi.bmpSource = source; fi.bmpEffect = NULL; fi.bw = this->lastBw; fi.bwalpha = (this->lastAlpha && this->lastFilterId != ID_FILTER_OLDSTONE && this->lastFilterId != ID_FILTER_EDGETRACE ); fi.smooth = true; fi.edgeTrace = (this->lastFilterId == ID_FILTER_EDGETRACE); fi.filterId = this->lastFilterId; fi.filterValue = this->lastFilterValue; fi.filterByValue = (this->lastFilterId != ID_FILTER_CUSTOM); fi.minVal = 0; switch(fi.filterId){ case ID_FILTER_SHARPEN: fi.maxVal = SHARPENMAX; break; default: fi.maxVal = FILTERMAX; break; } if( fi.filterByValue == true ) fi.matrix = ToolFilter::allocateMatrix(fi.filterId,fi.filterValue); else fi.matrix = this->lastCustomMatrix; int result = NO; if( this->lastActivate == false ){ result = this->core->getDialogs()->showDialog( (LPCTSTR)IDD_FIL, (DLGPROC)Dialogs::processDlg_Fil, (LPARAM)&fi ); } else { this->lastActivate = false; result = YES; } if( result == YES ){ Point shift(0,0); Rect *bounds = NULL; if( child->getWorkspace()->getSelection() != NULL ){ bounds = new Rect(0,0,0,0); child->getWorkspace()->getSelection()->GetBounds(bounds); fi.bmpSource = child->getWorkspace()->getSelectedLayer()->getRender(); } else { int exw = (int)( floor(fi.matrix.mxw / 2.0) + 1 ); int exh = (int)( floor(fi.matrix.mxh / 2.0) + 1 ); shift.X = -exw; shift.Y = -exh; Bitmap *newsource = new Bitmap( source->GetWidth() + 2 * exw, source->GetHeight() + 2 * exh, source->GetPixelFormat()); Graphics *g = Graphics::FromImage(newsource); g->DrawImage(source,exw,exh,source->GetWidth(),source->GetHeight()); delete g; delete source; source = newsource; fi.bmpSource = newsource; } if( fi.filterByValue == true ) this->lastFilterValue = fi.filterValue; else this->lastCustomMatrix = fi.matrix; this->lastBw = fi.bw; this->lastAlpha = fi.bwalpha; Rect newbounds = ToolFilter::applyFilter(&fi,bounds); if( child->getWorkspace()->getSelection() == NULL ){ bounds = &newbounds; bounds->X += shift.X; bounds->Y += shift.Y; } child->getWorkspace()->getSelectedLayer()->applyEffect( fi.bmpEffect, bounds, this, fi.filterId); delete fi.bmpEffect; this->isLastActivate = true; child->getWorkspace()->updateToolws(); child->getWorkspace()->update(); } if( source != NULL ) delete source; } }
Rect ToolFilter::applyFilter(ToolFilter::Info *fi, Rect *clip, bool once) { Core::self->getGui()->setCursor(CURSOR_WAIT); int w = (int)( floor(fi->matrix.mxw / 2.0) ); int h = (int)( floor(fi->matrix.mxh / 2.0) ); int exw = fi->matrix.mxw + 1; int exh = fi->matrix.mxh + 1; UINT *src0, *bmp0; BitmapData srcData, bmpData; Bitmap *src = fi->bmpSource; Rect srcRect(0,0,src->GetWidth(),src->GetHeight()); if( clip == NULL ){ clip = &srcRect; } else { int maxx = max(clip->X - exw,0); int maxy = max(clip->Y - exh,0); int ext = 2; srcRect = Rect( maxx, maxy, min(clip->Width + ext * exw,(int)src->GetWidth() - maxx), min(clip->Height + ext * exh,(int)src->GetHeight() - maxy) ); } int bmpWidth = clip->Width; int bmpHeight = clip->Height; if( fi->smooth == true ){ bmpWidth += 4 * exw; bmpHeight += 4 * exh; } Bitmap *bmp = new Bitmap( bmpWidth, bmpHeight, src->GetPixelFormat() ); Rect bmpRect(0,0,bmp->GetWidth(),bmp->GetHeight()); src->LockBits( &srcRect, ImageLockModeRead, src->GetPixelFormat(), &srcData ); bmp->LockBits( &bmpRect, ImageLockModeWrite, bmp->GetPixelFormat(), &bmpData ); src0 = (UINT *)srcData.Scan0; bmp0 = (UINT *)bmpData.Scan0; int srcWidth = srcData.Width; int srcHeight = srcData.Height; for( int x = 0; x < bmpWidth; x++ ){ for( int y = 0; y < bmpHeight; y++ ){ bmp0[y * bmpData.Stride / 4 + x] = ToolFilter::filterPixel(fi,&srcData,x,y,w,h); } } if( fi->edgeTrace == true && fi->filterValue > 0 ){ ToolFilter::Matrix oldMatrix = fi->matrix; fi->matrix = ToolFilter::allocMatrixEdgetrace(fi->filterValue,1); for( int x = 0; x < bmpWidth; x++ ){ for( int y = 0; y < bmpHeight; y++ ){ bmp0[y * bmpData.Stride / 4 + x] += ToolFilter::filterPixel(fi,&srcData,x,y,w,h); } } fi->matrix = ToolFilter::allocMatrixEdgetrace(fi->filterValue,2); for( int x = 0; x < bmpWidth; x++ ){ for( int y = 0; y < bmpHeight; y++ ){ bmp0[y * bmpData.Stride / 4 + x] += ToolFilter::filterPixel(fi,&srcData,x,y,w,h); } } fi->matrix = oldMatrix; } src->UnlockBits(&srcData); bmp->UnlockBits(&bmpData); fi->bmpEffect = bmp; int refils = 0; switch(fi->filterId){ case ID_FILTER_SHARPEN: if( fi->filterValue > SHARPENMAX/2 ) refils = fi->filterValue - SHARPENMAX/2; break; case ID_FILTER_GAUSSIANBLUR: if( fi->filterValue > GAUSSMAX ) refils = fi->filterValue - GAUSSMAX; break; } Bitmap *source = fi->bmpSource; if( refils > 0 && once == false ){ for(int i = 0; i < refils; i++ ){ fi->bmpSource = fi->bmpEffect; fi->bmpEffect = NULL; ToolFilter::applyFilter(fi,NULL,true); delete fi->bmpSource; } } fi->bmpSource = source; Rect gridClip(clip->X,clip->Y,clip->Width,clip->Height); clip->X -= exw; clip->Y -= exh; Core::self->getGui()->setCursor(); return gridClip; }
BOOL SavePngFile(HICON hIcon, LPCSTR strPngFile,int iOutWith = -1,int iOutHeight = -1) { if (hIcon == NULL) return FALSE; ICONINFO icInfo = { 0 }; if (!::GetIconInfo(hIcon, &icInfo)) return FALSE; BITMAP bitmap; GetObject(icInfo.hbmColor, sizeof(BITMAP), &bitmap); Bitmap* pBitmap = NULL; Bitmap* pWrapBitmap = NULL; if (bitmap.bmBitsPixel != 32) { pBitmap = Bitmap::FromHICON(hIcon); } else { pWrapBitmap = Bitmap::FromHBITMAP(icInfo.hbmColor, NULL); BitmapData bitmapData; Rect rcImage(0,0, pWrapBitmap->GetWidth(), pWrapBitmap->GetHeight()); pWrapBitmap->LockBits(&rcImage, ImageLockModeRead, pWrapBitmap->GetPixelFormat(), &bitmapData); pBitmap = new Bitmap(bitmapData.Width, bitmapData.Height, bitmapData.Stride, PixelFormat32bppARGB, (BYTE*)bitmapData.Scan0); pWrapBitmap->UnlockBits(&bitmapData); Gdiplus::Color Bmpcolor; BOOL BmpcolorTag=TRUE; for (UINT bmpx=0;bmpx<pBitmap->GetWidth();bmpx++) { for (UINT bmpy=0;bmpy<pBitmap->GetHeight();bmpy++) { pBitmap->GetPixel(bmpx,bmpy,&Bmpcolor); if(Bmpcolor.GetA()!=0) { BmpcolorTag=FALSE; break; } } if (BmpcolorTag==FALSE) break; } if (BmpcolorTag==TRUE) { delete pWrapBitmap; pWrapBitmap = NULL; delete pBitmap; pBitmap = NULL; pBitmap = Gdiplus::Bitmap::FromHICON(hIcon); } } DeleteObject(icInfo.hbmColor); DeleteObject(icInfo.hbmMask); static bool GetPngCode = false; static CLSID pngid; if (!GetPngCode) { GetPngCode = true; GetEncoderClsid(L"image/png", &pngid); } if (iOutWith !=-1 && iOutHeight!=-1) { Bitmap *pStretched = StretchBitmap(pBitmap,128,128); if (pStretched) { delete pBitmap; pBitmap = pStretched; } } _bstr_t bstr(strPngFile); wstring wstrPng = (WCHAR*)bstr; Gdiplus::Status s = pBitmap->Save(wstrPng.c_str(),&pngid,NULL); delete pBitmap; if (pWrapBitmap) delete pWrapBitmap; DeleteObject(icInfo.hbmColor); DeleteObject(icInfo.hbmMask); if (s==Gdiplus::Ok) return TRUE; return FALSE; }