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; }
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; }