bool CxImageIG::DecodeSelection (const wchar_t *pcwFilePath, int nSelectionIdx, int nLayerPos, bool bUndo) { CxIOFile file; if (!file.Open (pcwFilePath, L"rb")) throw IGEXCEPTION (CxImageIGException, "DecodeSelection", "file.Open failed"); return DecodeSelection (file, nSelectionIdx, nLayerPos, bUndo); }
bool CxImageIG::DecodeLayer (const wchar_t *pcwFilePath, int nLayerIdx, int nLayerPos, RECT *p_rcSubLayer, bool bUndo, int nSubLayerId) { CxIOFile file; if (!file.Open (pcwFilePath, L"rb")) throw IGEXCEPTION (CxImageIGException, "DecodeLayer", "file.Open failed"); return DecodeLayer (file, nLayerIdx, nLayerPos, p_rcSubLayer, bUndo, nSubLayerId); }
int CxImageIG::GetNbSelections (const wchar_t *pcwFilePath) { CxIOFile file; if (!file.Open (pcwFilePath, L"r+b")) return -1; // read current header IGHEADER igHeader; if (!decodeHeader (&file, &igHeader)) return -1; return igHeader.nNbSelections; }
int CxImageIG::GetMaxSelectionId (const wchar_t *pcwFilePath) { CxIOFile file; if (!file.Open (pcwFilePath, L"r+b")) return -1; // read current header IGHEADER igHeader; if (!decodeHeader (&file, &igHeader)) return -1; 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])) return -1; if (igHeader.nNbSelections <= 0) return -1; int nMaxSelectionId = pSelectionSections[0].commonHeader.nId; for (int nSelectionId = 1; nSelectionId < igHeader.nNbSelections; nSelectionId++) { if (nMaxSelectionId < pSelectionSections[nSelectionId].commonHeader.nId) nMaxSelectionId = pSelectionSections[nSelectionId].commonHeader.nId; } return nMaxSelectionId; }
bool CxImageJPG::GetExifThumbnail(const TCHAR *filename, const TCHAR *outname, int32_t type) { CxIOFile file; if (!file.Open(filename, _T("rb"))) return false; CxExifInfo exif(&info.ExifInfo); exif.DecodeExif(&file); if (info.ExifInfo.IsExif && info.ExifInfo.ThumbnailPointer && info.ExifInfo.ThumbnailSize > 0) { // have a thumbnail - check whether it needs rotating or resizing // TODO: Write a fast routine to read the jpeg header to get the width and height CxImage image(info.ExifInfo.ThumbnailPointer, info.ExifInfo.ThumbnailSize, CXIMAGE_FORMAT_JPG); if (image.IsValid()) { if (image.GetWidth() > 256 || image.GetHeight() > 256) { // resize the image // float amount = 256.0f / max(image.GetWidth(), image.GetHeight()); // image.Resample((int32_t)(image.GetWidth() * amount), (int32_t)(image.GetHeight() * amount), 0); } #if CXIMAGE_SUPPORT_TRANSFORMATION if (info.ExifInfo.Orientation != 1) image.RotateExif(info.ExifInfo.Orientation); #endif #if CXIMAGE_SUPPORT_ENCODE return image.Save(outname, CXIMAGE_FORMAT_JPG); #endif } // nice and fast, but we can't resize :( /* FILE *hFileWrite; if ((hFileWrite=fopen(outname, "wb")) != NULL) { fwrite(m_exifinfo.ThumbnailPointer, m_exifinfo.ThumbnailSize, 1, hFileWrite); fclose(hFileWrite); return true; }*/ } return false; }
bool CxImageIG::RemoveSections (const wchar_t *pcwFilePath, int nLayerId, int nSelectionId) { CxIOFile file; if (!file.Open (pcwFilePath, L"r+b")) throw IGEXCEPTION (CxImageIGException, "RemoveSections", "file.Open failed"); // read current header IGHEADER igHeader; if (!decodeHeader (&file, &igHeader)) throw IGEXCEPTION (CxImageIGException, "RemoveSections", "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, pSelectionSections)) throw IGEXCEPTION (CxImageIGException, "RemoveSections", "decodeSections failed"); // remove layers bool bFound = false; int nLayerSectionId = 0; int nSelectionSectionId = 0; if (nLayerId >= 0 && igHeader.nNbLayers > 0) { int nSubLayerId = 0; while (nLayerSectionId < igHeader.nNbLayers) { // update the number of sublayer sections if the removed layer is a sublayer nSubLayerId = 0; bool bSubLayerFound = false; while (nSubLayerId < pLayerSections [nLayerSectionId].nSubLayers) { if (pLayerSections [nLayerSectionId].pnSubLayers [nSubLayerId] == nLayerId) { bSubLayerFound = true; break; } nSubLayerId++; } if (bSubLayerFound) pLayerSections [nLayerSectionId].nSubLayers = nSubLayerId + 1; if (pLayerSections [nLayerSectionId].commonHeader.nId == nLayerId) { bFound = true; break; } nLayerSectionId++; } if (bFound) { igHeader.nNbLayers = nLayerSectionId + 1; // remove selections if necessary int nNbRemovedSelections = 0; nSelectionSectionId = -1; while (++nSelectionSectionId < igHeader.nNbSelections) { if (pSelectionSections [nSelectionSectionId].commonHeader.nSectionId > pLayerSections [nLayerSectionId].commonHeader.nSectionId) { if (pSelectionSections [nSelectionSectionId].commonHeader.nId > nSelectionId && nSelectionId >= 0) { nNbRemovedSelections = igHeader.nNbSelections - nSelectionSectionId; break; } } } igHeader.nNbSelections -= nNbRemovedSelections; } } // remove selections bFound = false; if (igHeader.nNbSelections > 0) { if (nSelectionId >= 0) { nSelectionSectionId = 0; while (nSelectionSectionId < igHeader.nNbSelections) { if (pSelectionSections [nSelectionSectionId].commonHeader.nId == nSelectionId) { bFound = true; break; } nSelectionSectionId++; } if (bFound) { igHeader.nNbSelections = nSelectionSectionId + 1; // remove layers if necessary int nNbRemovedLayers = 0; nLayerSectionId = -1; while (++nLayerSectionId < igHeader.nNbLayers) { if (pLayerSections [nLayerSectionId].commonHeader.nSectionId > pSelectionSections [nSelectionSectionId].commonHeader.nSectionId) { if (pLayerSections [nLayerSectionId].commonHeader.nId > nLayerId) { nNbRemovedLayers = igHeader.nNbLayers - nLayerSectionId; break; } } } igHeader.nNbLayers -= nNbRemovedLayers; } } else igHeader.nNbSelections = 0; } igHeader.nNbSections = igHeader.nNbSelections + igHeader.nNbLayers; // write new headers if (!encodeHeader (&file, &igHeader)) throw IGEXCEPTION (CxImageIGException, "RemoveSections", "encodeHeader failed"); if (!encodeSections (&file, &igHeader, pLayerSections, pSelectionSections)) throw IGEXCEPTION (CxImageIGException, "RemoveSections", "encodeSections failed"); delete [] pLayerSections; delete [] pSelectionSections; return true; }
bool CxImageIG::EncodeSelection (const wchar_t *pcwFilePath, int nSelectionIdx, int nLayerPos, const RECT& rcSelection) { CxIOFile file; if (!file.Open (pcwFilePath, L"r+b")) throw IGEXCEPTION (CxImageIGException, "EncodeSelection", "file.Open failed"); if (((rcSelection.left == -1) && (rcSelection.top != -1)) || ((rcSelection.right != -1) && (rcSelection.bottom == -1))) throw IGEXCEPTION (CxImageIGException, "EncodeSelection", "rcSelection failed"); // read current header IGHEADER igHeader; if (!decodeHeader (&file, &igHeader)) throw IGEXCEPTION (CxImageIGException, "EncodeSelection", "decodeHeader failed"); if ((nLayerPos < 0) || (nLayerPos >= info.nNumLayers)) throw IGEXCEPTION (CxImageIGException, "EncodeSelection", "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, "EncodeSelection", "decodeSections failed"); IGLibrary::IGLayer *pLayer = GetLayer (nLayerPos); if (!pLayer) throw IGEXCEPTION (CxImageIGException, "EncodeSelection", "GetLayer failed"); int nSelectionSectionIndex = findSelectionSectionIndex (&igHeader, pSelectionSections, nSelectionIdx); if (nSelectionSectionIndex < 0) throw IGEXCEPTION (CxImageIGException, "EncodeSelection", "findSelectionSectionIndex failed"); if ((nSelectionSectionIndex > igHeader.nNbSelections) || (nSelectionSectionIndex >= CXIMAGEIG_MAX_NBSELECTIONS) || (pLayer->GetId() < 0)) throw IGEXCEPTION (CxImageIGException, "EncodeSelection", "findSelectionSectionIndex failed"); // check rect bounds if (rcSelection.right != -1) // right = -1 is a special case (full selection) { if ((rcSelection.left < 0) || (rcSelection.top < 0) || (rcSelection.left >= pLayer->GetWidth()) || (rcSelection.top >= pLayer->GetHeight()) || (rcSelection.right >= pLayer->GetWidth()) || (rcSelection.bottom >= pLayer->GetHeight()) || (rcSelection.right <= rcSelection.left) || (rcSelection.bottom <= rcSelection.top)) throw IGEXCEPTION (CxImageIGException, "EncodeSelection", "rcSelection failed"); } // fill layer offset and size pSelectionSections [nSelectionSectionIndex].rcSelection.left = (rcSelection.right == -1) ? 0 : rcSelection.left; pSelectionSections [nSelectionSectionIndex].rcSelection.bottom = (rcSelection.right == -1) ? 0 : pLayer->GetHeight() - 1 - rcSelection.bottom; pSelectionSections [nSelectionSectionIndex].rcSelection.right = (rcSelection.right == -1) ? pLayer->GetWidth() - 1 : rcSelection.right; pSelectionSections [nSelectionSectionIndex].rcSelection.top = (rcSelection.right == -1) ? pLayer->GetHeight() - 1 : pLayer->GetHeight() - 1 - rcSelection.top; if (nSelectionSectionIndex == igHeader.nNbSelections) pSelectionSections [nSelectionSectionIndex].commonHeader.nSectionId = (BYTE)igHeader.nNbSections; pSelectionSections [nSelectionSectionIndex].commonHeader.nId = nSelectionIdx; pSelectionSections [nSelectionSectionIndex].nLayerId = (int)pLayer->GetId(); pSelectionSections [nSelectionSectionIndex].commonHeader.eSectionType = IGSECTION_SELECTION; // no need to set byte offset if it is not the last layer if (igHeader.nNbSections == 0) pSelectionSections [nSelectionSectionIndex].commonHeader.nFirstByteOffset = sizeof (IGHEADER) + sizeof (IGSECTIONHEADER_LAYER) * CXIMAGEIG_MAX_NBLAYERS + sizeof (IGSECTIONHEADER_SELECTION) * CXIMAGEIG_MAX_NBSELECTIONS; else pSelectionSections [nSelectionSectionIndex].commonHeader.nFirstByteOffset = findSectionFirstByteOffset (&igHeader, pLayerSections, pSelectionSections, pSelectionSections [nSelectionSectionIndex].commonHeader.nSectionId); if (nSelectionSectionIndex == igHeader.nNbSelections) igHeader.nNbSections++; else igHeader.nNbSections = pSelectionSections [nSelectionSectionIndex].commonHeader.nSectionId + 1; igHeader.nNbSelections = nSelectionSectionIndex + 1; igHeader.nNbLayers = igHeader.nNbSections - igHeader.nNbSelections; if (!writeSelection (file, pSelectionSections [nSelectionSectionIndex], *pLayer, rcSelection.right == -1)) throw IGEXCEPTION (CxImageIGException, "EncodeSelection", "writeSelection failed"); // write new headers if (!encodeHeader (&file, &igHeader)) throw IGEXCEPTION (CxImageIGException, "EncodeSelection", "encodeHeader failed"); if (!encodeSections (&file, &igHeader, pLayerSections, pSelectionSections)) throw IGEXCEPTION (CxImageIGException, "EncodeSelection", "encodeSections failed"); 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; }