bool CxImageIG::decodeSubLayer (CxFile& file, IGLibrary::IGLayer *pSubLayerOwner, IGSECTIONHEADER_LAYER *pLayerSection) { CxImage cxSubLayer; if (!file.Seek (pLayerSection->commonHeader.nFirstByteOffset, SEEK_SET)) throw IGEXCEPTION (CxImageIGException, "decodeSubLayer", "file.Seek failed"); // read sub-layer pixels BYTE *pBufImg = new BYTE [pLayerSection->commonHeader.nSizeBuf]; file.Read (pBufImg, pLayerSection->commonHeader.nSizeBuf, 1); if (!cxSubLayer.Decode (pBufImg, pLayerSection->commonHeader.nSizeBuf, CXIMAGEIG_LAYERFORMAT)) throw IGEXCEPTION (CxImageIGException, "decodeSubLayer", "cxSubLayer.Decode failed"); delete [] pBufImg; // read sub-layer alpha cxSubLayer.AlphaCreate (255); file.Read (cxSubLayer.pAlpha, cxSubLayer.GetWidth() * cxSubLayer.GetHeight(), 1); // decode sub-layer into layer BYTE *pLayerBits = NULL; BYTE *pSubLayerBits = NULL; for (int i = 0; i < pLayerSection->ptSize.y; i++) { pSubLayerBits = cxSubLayer.GetBits (i); pLayerBits = pSubLayerOwner->GetBits (pLayerSection->ptOffset.y + i) + 3 * pLayerSection->ptOffset.x; ::memcpy (pLayerBits, pSubLayerBits, (pLayerSection->ptSize.x) * 3); } BYTE *pLayerAlpha = NULL; BYTE *pSubLayerAlpha = NULL; for (int i = 0; i < (pLayerSection->ptSize.y); i++) { pLayerAlpha = pSubLayerOwner->AlphaGetPointer (pLayerSection->ptOffset.x, pLayerSection->ptOffset.y + i); pSubLayerAlpha = cxSubLayer.AlphaGetPointer (0, i); ::memcpy (pLayerAlpha, pSubLayerAlpha, (pLayerSection->ptSize.x)); } return true; }
void ModelOpened::ExportPNG(wxString val, wxString suffix) { if (val == wxEmptyString) return; wxFileName fn = fixMPQPath(val); if (fn.GetExt().Lower() != wxT("blp")) return; TextureID temptex = texturemanager.add(val); Texture &tex = *((Texture*)texturemanager.items[temptex]); if (tex.w == 0 || tex.h == 0) return; wxString temp; unsigned char *tempbuf = (unsigned char*)malloc(tex.w*tex.h*4); tex.getPixels(tempbuf, GL_BGRA_EXT); CxImage *newImage = new CxImage(0); newImage->AlphaCreate(); // Create the alpha layer newImage->IncreaseBpp(32); // set image to 32bit newImage->CreateFromArray(tempbuf, tex.w, tex.h, 32, (tex.w*4), true); if (bPathPreserved) { wxFileName::Mkdir(wxGetCwd()+SLASH+wxT("Export")+SLASH+fn.GetPath(), 0755, wxPATH_MKDIR_FULL); temp = wxGetCwd()+SLASH+wxT("Export")+SLASH+fn.GetPath()+SLASH+fn.GetName()+wxT(".")+suffix; } else { temp = wxGetCwd()+SLASH+wxT("Export")+SLASH+fn.GetName()+wxT(".")+suffix; } //wxLogMessage(wxT("Info: Exporting texture to %s..."), temp.c_str()); if (suffix == wxT("tga")) #ifndef _MINGW newImage->Save(temp.mb_str(), CXIMAGE_FORMAT_TGA); #else newImage->Save(temp.wc_str(), CXIMAGE_FORMAT_TGA); #endif else
bool IGFrameManager::Cut(LPCWSTR pcwGuid) { IGSmartPtr <IGFrame> spFrame; if (!GetFrame(pcwGuid, spFrame)) return false; CxImage *pCxLayer = spFrame->GetWorkingLayer(); if (!pCxLayer) return false; RECT rcSel; if (pCxLayer->SelectionIsValid()) pCxLayer->SelectionGetBox (rcSel); else{ rcSel.bottom = 0; rcSel.left = 0; rcSel.top = pCxLayer->GetHeight(); rcSel.right = pCxLayer->GetWidth(); } m_spClipboardLayer = new IGLayer(NULL); m_spClipboardLayer->Create (rcSel.right - rcSel.left, rcSel.top - rcSel.bottom, 24); m_spClipboardLayer->AlphaCreate(); pCxLayer->AlphaCreate(); RGBQUAD qGray; qGray.rgbBlue = CXIMAGE_GRAY; qGray.rgbGreen = CXIMAGE_GRAY; qGray.rgbRed = CXIMAGE_GRAY; for(long y=rcSel.bottom; y<rcSel.top; y++){ for(long x=rcSel.left; x<rcSel.right; x++){ if (pCxLayer->BlindSelectionIsInside(x,y)){ m_spClipboardLayer->BlindSetPixelColor(x - rcSel.left, y - rcSel.bottom, pCxLayer->BlindGetPixelColor(x,y)); pCxLayer->BlindSetPixelColor(x, y, qGray); pCxLayer->AlphaSet(x, y, 0); } else m_spClipboardLayer->AlphaSet (x - rcSel.left, y - rcSel.bottom, 0); } } return true; }
bool CxImageIG::DecodeLayer (CxFile &file, int nLayerIdx, int nLayerPos, RECT *p_rcSubLayer, bool bUndo, int nSubLayerId) { // read current header IGHEADER igHeader; if (!decodeHeader (&file, &igHeader)) throw IGEXCEPTION (CxImageIGException, "DecodeLayer", "decodeHeader failed"); if (nLayerIdx < 0) throw IGEXCEPTION (CxImageIGException, "DecodeLayer", "nLayerIdx failed"); if ((nLayerPos < 0) || (nLayerPos >= info.nNumLayers)) throw IGEXCEPTION (CxImageIGException, "DecodeLayer", "nLayerPos failed"); IGSECTIONHEADER_LAYER *pLayerSections = new IGSECTIONHEADER_LAYER [CXIMAGEIG_MAX_NBLAYERS]; IGSECTIONHEADER_SELECTION *pSelectionSections = new IGSECTIONHEADER_SELECTION [CXIMAGEIG_MAX_NBSELECTIONS]; if (!decodeSections (&file, &igHeader, &pLayerSections[0], &pSelectionSections[0])) throw IGEXCEPTION (CxImageIGException, "DecodeLayer", "decodeSections failed"); IGLibrary::IGLayer *pLayer = GetLayer (nLayerPos); if (!pLayer) throw IGEXCEPTION (CxImageIGException, "DecodeLayer", "GetLayer failed"); CxImage cxSubLayer; CxImage *pDecodingLayer = p_rcSubLayer ? &cxSubLayer : pLayer; bool bIsSubLayerOwner = bUndo && p_rcSubLayer; // no need to find sub-layer owner in do mode int nLayerSectionIndex = findLayerSectionIndex (&igHeader, pLayerSections, nLayerIdx, bIsSubLayerOwner); if ((nLayerSectionIndex < 0) || (nLayerSectionIndex >= igHeader.nNbLayers)) throw IGEXCEPTION (CxImageIGException, "DecodeLayer", "findLayerSectionIndex failed"); // in undo mode, if a sub-layer owner is found, decode it if (bUndo){ if (bIsSubLayerOwner) { // decode sub-layer owner if (!DecodeLayer (file, pLayerSections [nLayerSectionIndex].commonHeader.nId, nLayerPos)) throw IGEXCEPTION (CxImageIGException, "DecodeLayer", "DecodeLayer failed"); // decode sub-layers int nSubLayerSectionIndex = findLayerSectionIndex (&igHeader, pLayerSections, nLayerIdx, bIsSubLayerOwner); if ((nSubLayerSectionIndex < 0) || (nSubLayerSectionIndex >= igHeader.nNbLayers)) throw IGEXCEPTION (CxImageIGException, "DecodeLayer", "findLayerSectionIndex failed"); RECT rcSubLayer; rcSubLayer.left = pLayerSections[nSubLayerSectionIndex].ptOffset.x; rcSubLayer.right = pLayerSections[nSubLayerSectionIndex].ptOffset.x + pLayerSections[nSubLayerSectionIndex].ptSize.x - 1; rcSubLayer.top = pLayerSections[nSubLayerSectionIndex].ptOffset.y; rcSubLayer.bottom = pLayerSections[nSubLayerSectionIndex].ptOffset.y + pLayerSections[nSubLayerSectionIndex].ptSize.y - 1; return DecodeLayer (file, pLayerSections [nLayerSectionIndex].commonHeader.nId, nLayerPos, &rcSubLayer, true, nLayerIdx); } } if (!file.Seek (pLayerSections [nLayerSectionIndex].commonHeader.nFirstByteOffset, SEEK_SET)) throw IGEXCEPTION (CxImageIGException, "DecodeLayer", "file.Seek failed"); // read layer pixels BYTE *pBufImg = new BYTE [pLayerSections [nLayerSectionIndex].commonHeader.nSizeBuf]; file.Read (pBufImg, pLayerSections [nLayerSectionIndex].commonHeader.nSizeBuf, 1); if (!pDecodingLayer->Decode (pBufImg, pLayerSections [nLayerSectionIndex].commonHeader.nSizeBuf, CXIMAGEIG_LAYERFORMAT)) throw IGEXCEPTION (CxImageIGException, "DecodeLayer", "pDecodingLayer->Decode failed"); delete [] pBufImg; // read layer alpha pDecodingLayer->AlphaCreate (255); file.Read (pDecodingLayer->pAlpha, pDecodingLayer->GetWidth() * pDecodingLayer->GetHeight(), 1); int nSubLayerWidth = 0; int nSubLayerHeight = 0; if (p_rcSubLayer) { // decode sub-layer nSubLayerWidth = p_rcSubLayer->right - p_rcSubLayer->left + 1; nSubLayerHeight = p_rcSubLayer->bottom - p_rcSubLayer->top + 1; BYTE *pLayerBits = NULL; BYTE *pSubLayerBits = NULL; for (int i = 0; i < nSubLayerHeight; i++) { // if undo, then sub-layer == original layer pSubLayerBits = bUndo ? pDecodingLayer->GetBits (p_rcSubLayer->top + i) + 3 * p_rcSubLayer->left : pDecodingLayer->GetBits (i); pLayerBits = pLayer->GetBits (p_rcSubLayer->top + i) + 3 * p_rcSubLayer->left; ::memcpy (pLayerBits, pSubLayerBits, nSubLayerWidth * 3); } BYTE *pLayerAlpha = NULL; BYTE *pSubLayerAlpha = NULL; for (int i = 0; i < nSubLayerHeight; i++) { pLayerAlpha = pLayer->AlphaGetPointer (p_rcSubLayer->left, p_rcSubLayer->top + i); pSubLayerAlpha = bUndo ? pDecodingLayer->AlphaGetPointer (p_rcSubLayer->left, p_rcSubLayer->top + i) : pDecodingLayer->AlphaGetPointer (0, i); ::memcpy (pLayerAlpha, pSubLayerAlpha, nSubLayerWidth); } if (bUndo) { // original layer is now decoded. decode sub-layers bIsSubLayerOwner = false; int nMaxSubLayerSectionIndex = findLayerSectionIndex (&igHeader, pLayerSections, nSubLayerId, bIsSubLayerOwner); // we always have bIsSubLayerOwner = false, its used for the reference only if (nMaxSubLayerSectionIndex < 0) throw IGEXCEPTION (CxImageIGException, "DecodeLayer", "findLayerSectionIndex failed"); if (nMaxSubLayerSectionIndex <= igHeader.nNbLayers) { for (int i = 0; i < pLayerSections [nLayerSectionIndex].nSubLayers; i++) { if (pLayerSections [nLayerSectionIndex].pnSubLayers [i] <= nMaxSubLayerSectionIndex) { if (!decodeSubLayer (file, pLayer, &pLayerSections [pLayerSections [nLayerSectionIndex].pnSubLayers [i]])) throw IGEXCEPTION (CxImageIGException, "DecodeLayer", "decodeSubLayer failed"); } } } } } else { pLayer->info.xOffset = pLayerSections [nLayerSectionIndex].ptOffset.x; pLayer->info.yOffset = pLayerSections [nLayerSectionIndex].ptOffset.y; } pLayer->SetId (nLayerIdx); pLayer->UpdateImageParameters(); delete [] pLayerSections; delete [] pSelectionSections; return true; }
bool CxImageIG::EncodeLayer (const wchar_t *pcwFilePath, int nLayerIdx, int nLayerPos, RECT *p_rcSubLayer, int nSubLayerOwnerId) { CxIOFile file; if (!file.Open (pcwFilePath, L"r+b")) throw IGEXCEPTION (CxImageIGException, "EncodeLayer", "file.Open failed"); // read current header IGHEADER igHeader; if (!decodeHeader (&file, &igHeader)) throw IGEXCEPTION (CxImageIGException, "EncodeLayer", "decodeHeader failed"); IGSECTIONHEADER_LAYER *pLayerSections = new IGSECTIONHEADER_LAYER[CXIMAGEIG_MAX_NBLAYERS]; IGSECTIONHEADER_SELECTION *pSelectionSections = new IGSECTIONHEADER_SELECTION[CXIMAGEIG_MAX_NBSELECTIONS]; if (!decodeSections (&file, &igHeader, &pLayerSections[0], &pSelectionSections[0])) throw IGEXCEPTION (CxImageIGException, "EncodeLayer", "decodeSections failed"); IGLibrary::IGLayer *pLayer = GetLayer (nLayerPos); if (!pLayer) throw IGEXCEPTION (CxImageIGException, "EncodeLayer", "GetLayer failed"); _ASSERTE ((int)pLayer->GetId() == nLayerIdx && "CxImageIG::EncodeLayer FAILED"); bool bIsSubLayerOwner = false; int nLayerSectionIndex = findLayerSectionIndex (&igHeader, pLayerSections, nLayerIdx, bIsSubLayerOwner); if (nLayerSectionIndex < 0) throw IGEXCEPTION (CxImageIGException, "EncodeLayer", "findLayerSectionIndex failed"); if ((nLayerSectionIndex > igHeader.nNbLayers) || (nLayerSectionIndex >= CXIMAGEIG_MAX_NBLAYERS)) throw IGEXCEPTION (CxImageIGException, "EncodeLayer", "findLayerSectionIndex failed"); CxImage cxSubLayer; CxImage *pEncodingLayer = pLayer; int nSubLayerWidth = 0; int nSubLayerHeight = 0; if (p_rcSubLayer) { // Encode sub-layer nSubLayerWidth = p_rcSubLayer->right - p_rcSubLayer->left + 1; nSubLayerHeight = p_rcSubLayer->bottom - p_rcSubLayer->top + 1; cxSubLayer.Create (nSubLayerWidth, nSubLayerHeight, 24); cxSubLayer.AlphaCreate (255); BYTE *pLayerBits = NULL; BYTE *pSubLayerBits = NULL; for (int i = 0; i < nSubLayerHeight; i++) { pSubLayerBits = cxSubLayer.GetBits (i); pLayerBits = pLayer->GetBits (p_rcSubLayer->top + i) + 3 * p_rcSubLayer->left; ::memcpy (pSubLayerBits, pLayerBits, nSubLayerWidth * 3); } BYTE *pLayerAlpha = NULL; BYTE *pSubLayerAlpha = NULL; for (int i = 0; i < nSubLayerHeight; i++) { pLayerAlpha = pLayer->AlphaGetPointer (p_rcSubLayer->left, p_rcSubLayer->top + i); pSubLayerAlpha = cxSubLayer.AlphaGetPointer (0, i); ::memcpy (pSubLayerAlpha, pLayerAlpha, nSubLayerWidth); } pEncodingLayer = &cxSubLayer; int nSubLayerSectionIndex = findLayerSectionIndex (&igHeader, pLayerSections, nSubLayerOwnerId, bIsSubLayerOwner); if (nSubLayerSectionIndex < 0) throw IGEXCEPTION (CxImageIGException, "EncodeLayer", "findLayerSectionIndex failed"); pLayerSections [nSubLayerSectionIndex].pnSubLayers [pLayerSections [nSubLayerSectionIndex].nSubLayers++] = nLayerSectionIndex; } ProgressSetRange (pLayer->GetHeight(), 0); ProgressSetMessage (L"Encoding layer..."); // fill layer offset and size pLayerSections [nLayerSectionIndex].nSubLayers = 0; pLayerSections [nLayerSectionIndex].ptOffset.x = p_rcSubLayer ? p_rcSubLayer->left : pLayer->info.xOffset; pLayerSections [nLayerSectionIndex].ptOffset.y = p_rcSubLayer ? p_rcSubLayer->top : pLayer->info.yOffset; pLayerSections [nLayerSectionIndex].ptSize.x = p_rcSubLayer ? p_rcSubLayer->right - p_rcSubLayer->left + 1 : pLayer->GetWidth(); pLayerSections [nLayerSectionIndex].ptSize.y = p_rcSubLayer ? p_rcSubLayer->bottom - p_rcSubLayer->top + 1 : pLayer->GetHeight(); if (nLayerSectionIndex == igHeader.nNbLayers) pLayerSections [nLayerSectionIndex].commonHeader.nSectionId = (BYTE)igHeader.nNbSections; pLayerSections [nLayerSectionIndex].commonHeader.nId = nLayerIdx; pLayerSections [nLayerSectionIndex].commonHeader.eSectionType = IGSECTION_LAYER; // set byte offset if (igHeader.nNbSections == 0) pLayerSections [nLayerSectionIndex].commonHeader.nFirstByteOffset = sizeof (IGHEADER) + sizeof (IGSECTIONHEADER_LAYER) * CXIMAGEIG_MAX_NBLAYERS + sizeof (IGSECTIONHEADER_SELECTION) * CXIMAGEIG_MAX_NBSELECTIONS; else pLayerSections [nLayerSectionIndex].commonHeader.nFirstByteOffset = findSectionFirstByteOffset (&igHeader, pLayerSections, pSelectionSections, pLayerSections [nLayerSectionIndex].commonHeader.nSectionId); igHeader.nNbLayers = nLayerSectionIndex + 1; if (igHeader.nNbSelections == 0) { igHeader.nNbSections = pLayerSections [nLayerSectionIndex].commonHeader.nSectionId + 1; igHeader.nNbSelections = igHeader.nNbSections - igHeader.nNbLayers; } else { if (pSelectionSections [igHeader.nNbSelections - 1].commonHeader.nSectionId == pLayerSections [nLayerSectionIndex].commonHeader.nSectionId + 1) igHeader.nNbSections = igHeader.nNbSelections + igHeader.nNbLayers; else { igHeader.nNbSections = pLayerSections [nLayerSectionIndex].commonHeader.nSectionId + 1; igHeader.nNbSelections = igHeader.nNbSections - igHeader.nNbLayers; } } // write layer pixels if (!file.Seek (pLayerSections [nLayerSectionIndex].commonHeader.nFirstByteOffset, SEEK_SET)) throw IGEXCEPTION (CxImageIGException, "EncodeLayer", "file.Seek failed"); // set max JPEG quality float fCurQuality = pEncodingLayer->GetJpegQualityF(); pEncodingLayer->SetJpegQualityF (100.0f); // JPEG encoding BYTE *pBuf = new BYTE [CXIMAGEIG_INIT_LAYERSIZE]; CxMemFile memFile (pBuf, CXIMAGEIG_INIT_LAYERSIZE); if (!pEncodingLayer->Encode (&memFile, CXIMAGEIG_LAYERFORMAT)) throw IGEXCEPTION (CxImageIGException, "EncodeLayer", "pEncodingLayer->Encode failed"); BYTE *pBufImg = memFile.GetBuffer(); long nSizeBufImg = memFile.Tell(); // reset JPEG quality pEncodingLayer->SetJpegQualityF (fCurQuality); file.Write (pBufImg, nSizeBufImg, 1); delete [] pBufImg; pLayerSections [nLayerSectionIndex].commonHeader.nSizeBuf = nSizeBufImg; // write layer alpha if (!pEncodingLayer->pAlpha) pEncodingLayer->AlphaCreate(255); int nNbPixels = pEncodingLayer->GetWidth() * pEncodingLayer->GetHeight(); file.Write (pEncodingLayer->pAlpha, nNbPixels, 1); pLayerSections [nLayerSectionIndex].commonHeader.nEndByteOffset = pLayerSections [nLayerSectionIndex].commonHeader.nFirstByteOffset + nSizeBufImg + nNbPixels; // write new headers if (!encodeHeader (&file, &igHeader)) throw IGEXCEPTION (CxImageIGException, "EncodeLayer", "encodeHeader failed"); if (!encodeSections (&file, &igHeader, pLayerSections, pSelectionSections)) throw IGEXCEPTION (CxImageIGException, "EncodeLayer", "encodeSections failed"); delete [] pLayerSections; delete [] pSelectionSections; return true; }
BOOL CSonicImage::Rotate(int nAngle, POINT * pScout /* = NULL */) { if(m_Dib.IsValid() == FALSE) { return FALSE; } nAngle = abs(nAngle) % 360; int nBitX = nAngle <= 180 ? 1 : 0; int nBitY = nAngle > 90 && nAngle <= 270 ? 1 : 0; int nSrcW = m_nWidth; int nSrcH = m_nHeight; const int nBytePixel = 4; BYTE * pSrc = m_Dib.GetBits(); int nNewX = (nSrcW - nBitX) >> 1; int nNewY = (nSrcH - nBitY) >> 1; double m1 = -nSrcW / 2.0f; double m2 = nSrcW / 2.0f; double n1 = nSrcH / 2.0f; double n2 = -nSrcH / 2.0f; POINT pt1 = {(int)(m1 * COS(nAngle) + n1 * SIN(nAngle)) >> 10, (int)(-m1 * SIN(nAngle) + n1 * COS(nAngle)) >> 10}; POINT pt2 = {(int)(m2 * COS(nAngle) + n1 * SIN(nAngle)) >> 10, (int)(-m2 * SIN(nAngle) + n1 * COS(nAngle)) >> 10}; POINT pt3 = {(int)(m2 * COS(nAngle) + n2 * SIN(nAngle)) >> 10, (int)(-m2 * SIN(nAngle) + n2 * COS(nAngle)) >> 10}; POINT pt4 = {(int)(m1 * COS(nAngle) + n2 * SIN(nAngle)) >> 10, (int)(-m1 * SIN(nAngle) + n2 * COS(nAngle)) >> 10}; int i, j, x1, y1, x11, y11; i = abs(pt3.x - pt1.x); j = abs(pt4.x - pt2.x); int nDestW = max(i, j); i = abs(pt3.y - pt1.y); j = abs(pt4.y - pt2.y); int nDestH = max(i, j); m_nWidth = nDestW; m_nHeight = nDestH; HBITMAP hBmp = NULL; m_Dib.Resize(m_nWidth, m_nHeight, &hBmp); BYTE * pDest = m_Dib.GetBits(); int temp; int nOriginX = nDestW >> 1; int nOriginY = nDestH >> 1; for(i = 0; i < nDestH; i++) { for(j = 0; j < nDestW; j++) { x1 = j - nOriginX; y1 = nOriginY - i; temp = (x1 * COS(nAngle) + y1 * SIN(nAngle)) >> 10; x11 = temp + nNewX; temp = (-x1 * SIN(nAngle) + y1 * COS(nAngle)) >> 10; y11 = nNewY - temp; if(x11 >= 0 && x11 < nSrcW && y11 >= 0 && y11 < nSrcH) { COLORREF color = *(DWORD *)(pSrc + (nSrcW * nBytePixel * y11) + x11 * nBytePixel); *(DWORD *)(pDest + i * nBytePixel * nDestW + j * nBytePixel) = color; } } } if(hBmp) { DeleteObject(hBmp); } if(pScout) { x1 = pScout->x - nNewX; y1 = nNewY - pScout->y; nAngle = 360 - nAngle; x11 = (x1 * COS(nAngle) + y1 * SIN(nAngle)) >> 10; x11 = x11 + nOriginX; y11 = (-x1 * SIN(nAngle) + y1 * COS(nAngle)) >> 10; y11 = nOriginY - y11; pScout->x = x11; pScout->y = y11; } EnableAlphaChannel(FALSE); return TRUE; } BOOL CSonicImage::SaveAsFile(LPCTSTR lpszFileName, enImageType imgType, int nQuality /* = 0 */) { if(m_Dib.IsValid() == FALSE) { return FALSE; } CxImage img; if(img.CreateFromHBITMAP(m_Dib.GetHBitmap()) == FALSE) { return FALSE; } if(IsAlphaChannelValid() && (imgType == IMAGE_TYPE_BMP || imgType == IMAGE_TYPE_PNG || imgType == IMAGE_TYPE_TGA || imgType == IMAGE_TYPE_ICO)) { img.AlphaCreate(); for(int i = 0; i < m_nHeight; i++) { for(int j = 0; j < m_nWidth; j++) { BYTE bAlpha = *(m_Dib.GetBits() + i * m_nWidth * 4 + j * 4 + 3); img.AlphaSet(j, i, bAlpha); } } } DWORD dwType = 0; switch (imgType) { case IMAGE_TYPE_BMP: dwType = CXIMAGE_FORMAT_BMP; break; case IMAGE_TYPE_JPEG: dwType = CXIMAGE_FORMAT_JPG; nQuality = nQuality ? nQuality : DEFAULT_JPEG_QULITY; img.SetJpegQuality(nQuality); break; case IMAGE_TYPE_TGA: dwType = CXIMAGE_FORMAT_TGA; break; case IMAGE_TYPE_PNG: dwType = CXIMAGE_FORMAT_PNG; break; case IMAGE_TYPE_ICO: dwType = CXIMAGE_FORMAT_ICO; break; } CString strPath = lpszFileName; int nFind1 = strPath.ReverseFind(_T('\\')); int nFind2 = strPath.ReverseFind(_T('/')); int nFind = max(nFind1, nFind2); if(nFind != -1) { strPath = strPath.Left(nFind); if(PathFileExists(strPath) == FALSE) { SHCreateDirectoryEx(NULL, strPath, NULL); } } #ifdef _UNICODE USES_CONVERSION; if(img.Save(W2A(lpszFileName), dwType) == FALSE) { return FALSE; } #else if(img.Save(lpszFileName, dwType) == FALSE) { return FALSE; } #endif img.Clear(); return TRUE; } BOOL CSonicImage::Gray() { if(m_Dib.IsValid() == FALSE) { return FALSE; } int nSrcSize = m_nWidth * m_nHeight * 4; CSSE::DoGray(m_Dib.GetBits(), nSrcSize); return TRUE; } HRGN CSonicImage::CreateRgn(DWORD dwColorKey /* = DEFAULT_COLOR_KEY */, int x /* = 0 */, int y /* = 0 */, RECT * pRtSrc /* = NULL */, BOOL bReverse /* = FALSE */) { if(m_Dib.IsValid() == FALSE) { return FALSE; } int nBytePixel = 4; BYTE * pSrc = m_Dib.GetBits(); CRect rtSrc(0, 0, m_nWidth, m_nHeight); if(pRtSrc) { rtSrc = *pRtSrc; } int nLeftx = -1; HRGN hAll = CreateRectRgn(x, y, x + rtSrc.Width(), y + rtSrc.Height()); for(int i = rtSrc.top; i < rtSrc.bottom; i++) { for(int j = rtSrc.left; j < rtSrc.right; j++) { DWORD dwColor = *(DWORD *)(pSrc + (i * m_nWidth * nBytePixel) + j * nBytePixel); if(!bReverse) { if(EQUAL_24COLOR(dwColor, dwColorKey) && nLeftx < 0) { nLeftx = j; } if(nLeftx >= 0 && (!EQUAL_24COLOR(dwColor, dwColorKey) || j + 1 == rtSrc.right)) { if(EQUAL_24COLOR(dwColor, dwColorKey) && j + 1 == rtSrc.right)j++; HRGN hTemp = CreateRectRgn(x + nLeftx - rtSrc.left, y + i - rtSrc.top, x + j - rtSrc.left, y + i + 1 - rtSrc.top); CombineRgn(hAll, hAll, hTemp, RGN_XOR); DeleteObject(hTemp); nLeftx = -1; } } else { if(!EQUAL_24COLOR(dwColor, dwColorKey) && nLeftx < 0) { nLeftx = j; } if(nLeftx >= 0 && (EQUAL_24COLOR(dwColor, dwColorKey) || j + 1 == rtSrc.right)) { if(!EQUAL_24COLOR(dwColor, dwColorKey) && j + 1 == rtSrc.right)j++; HRGN hTemp = CreateRectRgn(x + nLeftx - rtSrc.left, y + i - rtSrc.top, x + j - rtSrc.left, y + i + 1 - rtSrc.top); CombineRgn(hAll, hAll, hTemp, RGN_XOR); DeleteObject(hTemp); nLeftx = -1; } } } } return hAll; } BOOL CSonicImage::IsAlphaChannelValid() { return m_bAlphaChannel; } BOOL CSonicImage::EnableAlphaChannel(BOOL bModifyRgb /* = TRUE */) { if(m_bAlphaChannel) { return FALSE; } if(m_Dib.IsValid() == FALSE) { return FALSE; } m_bAlphaChannel = TRUE; if(bModifyRgb) { int nSrc = m_nWidth * m_nHeight; DWORD * pSrc = (DWORD *)m_Dib.GetBits(); for(int i = 0; i < nSrc; i++) { CSSE::AdjustAlpha(*pSrc); pSrc++; } } return TRUE; } DWORD CSonicImage::GetPixel(int x, int y) { if(m_Dib.IsValid() == FALSE) { return 0; } if(y < 0 || y >= m_nHeight) { return 0; } if(x < 0 || x >= m_nWidth) { return 0; } return *(DWORD *)(m_Dib.GetBits() + (m_nHeight - y - 1) * m_nWidth * 4 + x * 4); } BOOL CSonicImage::SetPixel(int x, int y, DWORD dwColor) { if(m_Dib.IsValid() == FALSE) { return 0; } if(IsAlphaChannelValid()) { CSSE::AdjustAlpha(dwColor); } else { dwColor |= 0xff000000; } if(y < 0 || y >= m_nHeight) { return 0; } if(x < 0 || x >= m_nWidth) { return 0; } *(DWORD *)(m_Dib.GetBits() + (m_nHeight - y - 1) * m_nWidth * 4 + x * 4) = dwColor; return TRUE; } BYTE * CSonicImage::GetBits() { return m_Dib.GetBits(); } BOOL CSonicImage::Init() { double radiant; for(int i = 0; i < 361; i++) { radiant = (i * PAI) / 180; double temp = sin(radiant) * 1024; Trigonometry[i][0] = ROUND(temp); temp = cos(radiant) * 1024; Trigonometry[i][1] = ROUND(temp); } return TRUE; } BOOL CSonicImage::SetBitsToDevice(HDC hdc, int x /* = 0 */, int y /* = 0 */) { return SetDIBitsToDevice(hdc, x, y, m_nWidth, m_nHeight, 0, 0, 0, m_nHeight, m_Dib.GetBits(), m_Dib.GetBitmapInfo(), DIB_RGB_COLORS) != 0; } RECT CSonicImage::CalculateRectByDrawParam(int x, int y, const DRAW_PARAM * pDp, RECT * pSrc /* = NULL */) { CRect rtSrc, rtDest; int cx = m_nWidth; int cy = m_nHeight; if(pDp && (pDp->dwMask & DP_SRC_CLIP)) { rtSrc = pDp->rtSrc; } else { rtSrc.SetRect(0, 0, m_nWidth, m_nHeight); } cx = rtSrc.Width(); cy = rtSrc.Height(); if(pDp) { if(pDp->dwMask & DP_SCALE) { cx = (int)(rtSrc.Width() * pDp->fScaleX); cy = (int)(rtSrc.Height() * pDp->fScaleY); } if(pDp->dwMask & DP_DEST_LIMIT) { cx = pDp->cx; cy = pDp->cy; } if(pDp->dwMask & DP_TILE) { cx = pDp->nTileLength; } if(pDp->dwMask & DP_VER_TILE) { cy = pDp->nTileLength; } } rtDest.SetRect(x, y, x + cx, y + cy); if(pSrc) { *pSrc = rtSrc; } return rtDest; } BOOL CSonicImage::SetColorKey(DWORD dwColor) { if(IsAlphaChannelValid()) { return FALSE; } CSSE::SetColorKey(m_Dib.GetBits(), m_Dib.GetSize(), dwColor); EnableAlphaChannel(FALSE); return TRUE; } BOOL CSonicImage::Load(HDC hdc, int x, int y, int cx, int cy, BOOL bAlphaChannel /* = FALSE */) { Clear(); BITMAP bmp; GetObject((HBITMAP)GetCurrentObject(hdc, OBJ_BITMAP), sizeof(bmp), &bmp); if(bmp.bmType != 0 || bmp.bmPlanes != 1) { return FALSE; } if(bmp.bmBitsPixel != 32) { return FALSE; } if(PrepareMemDC(cx, cy) == FALSE) { return FALSE; } BitBlt(m_Dib.GetSafeHdc(), 0, 0, cx, cy, hdc, x, y, SRCCOPY); if(bAlphaChannel) { EnableAlphaChannel(FALSE); CSSE::DoOr(0xff000000, m_Dib.GetBits(), m_Dib.GetSize()); } return TRUE; } BOOL CSonicImage::Create(int cx, int cy, DWORD dwColor /* = 0 */, BOOL bWithAlpha /* = FALSE */) { if(PrepareMemDC(cx, cy) == FALSE) { return FALSE; } if(bWithAlpha) { CSSE::AdjustAlpha(dwColor); EnableAlphaChannel(FALSE); } if(dwColor) { Flush(dwColor); } return TRUE; } BOOL CSonicImage::Flush(DWORD dwColor) { if(m_Dib.IsValid() == FALSE) { return FALSE; } CSSE::MemSetDWord(m_Dib.GetBits(), dwColor, m_Dib.GetSize()); return TRUE; } BOOL CSonicImage::SetHsl(int h /* = -1 */, int s /* = -1 */, int l /* = -1 */) { if(IsValid() == FALSE) { return FALSE; } CSSE::SetHSL(m_Dib.GetBits(), m_Dib.GetSize(), h, s, l); return TRUE; } BOOL CSonicImage::MirrorX() { if(IsValid() == FALSE) { return FALSE; } CSSE::MirrorX(m_Dib.GetBits(), m_nWidth, m_nHeight); return TRUE; } BOOL CSonicImage::MirrorY() { if(IsValid() == FALSE) { return FALSE; } CSSE::MirrorY(m_Dib.GetBits(), m_nWidth, m_nHeight); return TRUE; } BOOL CSonicImage::Stretch(int cx, int cy) { if(IsValid() == FALSE) { return FALSE; } if(cx == m_nWidth && cy == m_nHeight) { return TRUE; } CSonicImage * pImg = (CSonicImage *)g_UI.CreateImage(); pImg->CloneFrom(this); PrepareMemDC(cx, cy); CSSE::Stretch(pImg->m_Dib.GetBits(), pImg->GetWidth(), pImg->GetHeight(), m_Dib.GetBits(), cx, cy); g_UI.DestroyObject(pImg); return TRUE; } BOOL CSonicImage::Extend(int cx /* = 0 */, int cy /* = 0 */) { if(IsValid() == FALSE) { return FALSE; } cx = (cx == 0 ? m_nWidth : cx); cy = (cy == 0 ? m_nHeight : cy); CSonicImage * pImg = (CSonicImage *)g_UI.CreateImage(); pImg->CloneFrom(this); PrepareMemDC(cx, cy); for(int i = 0; i < cy; i += pImg->GetHeight()) { for(int j = 0; j < cx; j += pImg->GetWidth()) { pImg->SetBitsToDevice(m_Dib.GetSafeHdc(), j, i); } } g_UI.DestroyObject(pImg); return TRUE; } HDC CSonicImage::GetDC() { if(IsValid() == FALSE) { return NULL; } return m_Dib.GetSafeHdc(); } BOOL CSonicImage::DestroyAlphaChannel() { if(IsValid() == FALSE) { return FALSE; } CSSE::DoAnd(0xffffff, (char *)m_Dib.GetBits(), m_Dib.GetSize()); return TRUE; } BOOL CSonicImage::SetAlphaChannel(BYTE bAlpha) { if(IsValid() == FALSE) { return FALSE; } CSSE::DoOr((bAlpha << 24), (char *)m_Dib.GetBits(), m_Dib.GetSize()); EnableAlphaChannel(FALSE); return TRUE; } BOOL CSonicImage::Blur(int nType /* = 0 */) { if(IsValid() == FALSE) { return FALSE; } char * pTemp = new char[m_Dib.GetSize()]; CSSE::MemCopy(pTemp, m_Dib.GetBits(), m_Dib.GetSize()); int i, j; DWORD * pSrc = (DWORD *)m_Dib.GetBits(); DWORD * pDest = (DWORD *)pTemp; for(i = 1; i < m_Dib.GetHeight() - 1; i++) { for(j = 1; j < m_Dib.GetWidth() - 1; j++) { DWORD dw1 = *(pDest + i * m_Dib.GetWidth() + j); DWORD dw2 = *(pDest + i * m_Dib.GetWidth() + j - 1); DWORD dw3 = *(pDest + i * m_Dib.GetWidth() + j + 1); DWORD dw4 = *(pDest + (i - 1) * m_Dib.GetWidth() + j); DWORD dw5 = *(pDest + (i + 1) * m_Dib.GetWidth() + j); DWORD dw6 = *(pDest + (i - 1) * m_Dib.GetWidth() + j - 1); DWORD dw7 = *(pDest + (i - 1) * m_Dib.GetWidth() + j + 1); DWORD dw8 = *(pDest + (i + 1) * m_Dib.GetWidth() + j - 1); DWORD dw9 = *(pDest + (i + 1) * m_Dib.GetWidth() + j + 1); char r, g, b; r = g = b = 0; switch (nType) { case 0: { // gauss blur r = ((GetRValue(dw1) << 2) + ((GetRValue(dw2) + GetRValue(dw3) + GetRValue(dw4) + GetRValue(dw5)) << 1) + GetRValue(dw6) + GetRValue(dw7) + GetRValue(dw8) + GetRValue(dw9)) >> 4; g = ((GetGValue(dw1) << 2) + ((GetGValue(dw2) + GetGValue(dw3) + GetGValue(dw4) + GetGValue(dw5)) << 1) + GetGValue(dw6) + GetGValue(dw7) + GetGValue(dw8) + GetGValue(dw9)) >> 4; b = ((GetBValue(dw1) << 2) + ((GetBValue(dw2) + GetBValue(dw3) + GetBValue(dw4) + GetBValue(dw5)) << 1) + GetBValue(dw6) + GetBValue(dw7) + GetBValue(dw8) + GetBValue(dw9)) >> 4; } break; case 1: { // even blur r = (GetRValue(dw1) + GetRValue(dw2) + GetRValue(dw3) + GetRValue(dw4) + GetRValue(dw5) + GetRValue(dw6) + GetRValue(dw7) + GetRValue(dw8) + GetRValue(dw9)) / 9; g = (GetGValue(dw1) + GetGValue(dw2) + GetGValue(dw3) + GetGValue(dw4) + GetGValue(dw5) + GetGValue(dw6) + GetGValue(dw7) + GetGValue(dw8) + GetGValue(dw9)) / 9; b = (GetBValue(dw1) + GetBValue(dw2) + GetBValue(dw3) + GetBValue(dw4) + GetBValue(dw5) + GetBValue(dw6) + GetBValue(dw7) + GetBValue(dw8) + GetBValue(dw9)) / 9; } break; } *(pSrc + i * m_Dib.GetWidth() + j) = (0xff000000 | RGB(r, g, b)); } } delete []pTemp; return TRUE; }