/** * exports the image into a RGBA buffer, Useful for OpenGL applications. * \param buffer: output memory buffer pointer. Must be NULL, * the function allocates and fill the memory, * the application must free the buffer, see also FreeMemory(). * \param size: output memory buffer size. * \param bFlipY: direction of Y axis. default = false. * \return true if everything is ok */ bool CxImage::Encode2RGBA(uint8_t * &buffer, int32_t &size, bool bFlipY) { if (buffer!=NULL){ strcpy(info.szLastError,"the buffer must be empty"); return false; } CxMemFile file; file.Open(); if(Encode2RGBA(&file,bFlipY)){ buffer=file.GetBuffer(); size=file.Size(); return true; } return false; }
/** * Saves to memory buffer the image in a specific format. * \param buffer: output memory buffer pointer. Must be NULL, * the function allocates and fill the memory, * the application must free the buffer, see also FreeMemory(). * \param size: output memory buffer size. * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS * \return true if everything is ok */ bool CxImage::Encode(BYTE * &buffer, long &size, DWORD imagetype) { if (buffer!=NULL){ strcpy(info.szLastError,"the buffer must be empty"); return false; } CxMemFile file; file.Open(); if(Encode(&file,imagetype)){ buffer=file.GetBuffer(); size=file.Size(); return true; } return false; }
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 CxImageIG::Encode(CxFile *hFile) { if (!hFile) throw IGEXCEPTION (CxImageIGException, "Encode", "hFile failed"); // create ig format header IGHEADER igHeader; igHeader.Manufacturer = IGHEADER_MAGICKEY; igHeader.Version = 0x01; igHeader.Encoding = 0x01; igHeader.nWidth = head.biWidth; igHeader.nHeight = head.biHeight; igHeader.nNbLayers = info.nNumLayers; igHeader.nNbSelections = 0; igHeader.nNbSections = info.nNumLayers; igHeader.nPosWorkingLayer = (BYTE)GetLayerPos(dynamic_cast<IGLibrary::IGLayer*> (GetSelectionLayer())); // write layer headers int nLayerSumHeight = 0; IGSECTIONHEADER_LAYER *pLayerHeader = new IGSECTIONHEADER_LAYER[CXIMAGEIG_MAX_NBLAYERS]; for (int i = 0; i < info.nNumLayers; i++) { if (i < info.nNumLayers) { IGLibrary::IGLayer *pLayer = GetLayer (i); pLayerHeader[i].commonHeader.eSectionType = IGSECTION_LAYER; pLayerHeader[i].commonHeader.nId = (int)pLayer->GetId(); pLayerHeader[i].commonHeader.nSectionId = i; pLayerHeader[i].commonHeader.nFirstByteOffset = 0; pLayerHeader[i].ptOffset.x = pLayer->info.xOffset; pLayerHeader[i].ptOffset.y = pLayer->info.yOffset; pLayerHeader[i].ptSize.x = pLayer->GetWidth(); pLayerHeader[i].ptSize.y = pLayer->GetHeight(); pLayerHeader[i].nSubLayers = 0; nLayerSumHeight += pLayer->GetHeight(); } } if (info.nNumLayers < CXIMAGEIG_MAX_NBLAYERS) ZeroMemory (&pLayerHeader [info.nNumLayers], sizeof(IGSECTIONHEADER_LAYER) * (CXIMAGEIG_MAX_NBLAYERS - info.nNumLayers)); ProgressSetRange (nLayerSumHeight, 0); ProgressSetMessage (L"Encoding picture..."); // write layer data if (!hFile->Seek (sizeof(IGHEADER) + sizeof (IGSECTIONHEADER_LAYER) * CXIMAGEIG_MAX_NBLAYERS + sizeof (IGSECTIONHEADER_SELECTION) * CXIMAGEIG_MAX_NBSELECTIONS, SEEK_SET)) throw IGEXCEPTION (CxImageIGException, "Encode", "hFile->Seek failed"); // write layers IGLibrary::IGLayer *pLayer; for (int i = 0; i < info.nNumLayers; i++) { // write layer pixels pLayer = GetLayer (i); if (i == 0) pLayerHeader [i].commonHeader.nFirstByteOffset = sizeof(IGHEADER) + sizeof (IGSECTIONHEADER_LAYER) * CXIMAGEIG_MAX_NBLAYERS + sizeof (IGSECTIONHEADER_SELECTION) * CXIMAGEIG_MAX_NBSELECTIONS; else pLayerHeader [i].commonHeader.nFirstByteOffset = pLayerHeader [i - 1].commonHeader.nEndByteOffset; float fCurQuality = pLayer->GetJpegQualityF(); pLayer->SetJpegQualityF (100.0f); BYTE *pBuf = new BYTE [CXIMAGEIG_INIT_LAYERSIZE]; CxMemFile memFile (pBuf, CXIMAGEIG_INIT_LAYERSIZE); if (!pLayer->Encode (&memFile, CXIMAGEIG_LAYERFORMAT)) throw IGEXCEPTION (CxImageIGException, "Encode", "pLayer->Encode failed"); BYTE *pBufImg = memFile.GetBuffer(); long nSizeBufImg = memFile.Tell(); pLayer->SetJpegQualityF (fCurQuality); hFile->Write (pBufImg, nSizeBufImg, 1); delete [] pBufImg; pLayerHeader [i].commonHeader.nSizeBuf = nSizeBufImg; // write layer alpha if (!pLayer->pAlpha) pLayer->AlphaCreate(255); int nNbPixels = pLayer->GetWidth() * pLayer->GetHeight(); hFile->Write (pLayer->pAlpha, nNbPixels, 1); pLayerHeader [i].commonHeader.nEndByteOffset = pLayerHeader [i].commonHeader.nFirstByteOffset + nSizeBufImg + nNbPixels; } // write section layer headers if (!hFile->Seek (sizeof(IGHEADER), SEEK_SET)) throw IGEXCEPTION (CxImageIGException, "Encode", "hFile->Seek failed"); hFile->Write (pLayerHeader, sizeof (IGSECTIONHEADER_LAYER) * info.nNumLayers, 1); // write section selection headers if (IsSelection()) { // the selection is saved as well igHeader.nNbSelections = 1; igHeader.nNbSections++; RECT rcSel; CxImage *pSelectionLayer = GetSelectionLayer(); pSelectionLayer->SelectionGetBox(rcSel); IGSECTIONHEADER_SELECTION *pSelectionHeader = new IGSECTIONHEADER_SELECTION; pSelectionHeader->commonHeader.eSectionType = IGSECTION_SELECTION; pSelectionHeader->commonHeader.nFirstByteOffset = pLayerHeader [info.nNumLayers - 1].commonHeader.nEndByteOffset; pSelectionHeader->commonHeader.nSizeBuf = (rcSel.right - rcSel.left + 1) * (rcSel.top - rcSel.bottom + 1); pSelectionHeader->commonHeader.nEndByteOffset = pSelectionHeader->commonHeader.nFirstByteOffset + pSelectionHeader->commonHeader.nSizeBuf; pSelectionHeader->commonHeader.nId = IGFrameHistory::GetMaxSelectionId() + 1; pSelectionHeader->commonHeader.nSectionId = (BYTE)info.nNumLayers; pSelectionHeader->nLayerId = (int)(dynamic_cast<IGLibrary::IGLayer&> (*pSelectionLayer)).GetId(); pSelectionHeader->rcSelection = rcSel; if (!hFile->Seek (sizeof(IGHEADER) + sizeof (IGSECTIONHEADER_LAYER) * info.nNumLayers, SEEK_SET)) throw IGEXCEPTION (CxImageIGException, "Encode", "hFile->Seek failed"); hFile->Write (pSelectionHeader, sizeof (IGSECTIONHEADER_SELECTION), 1); if (!writeSelection (*hFile, *pSelectionHeader, *pSelectionLayer)) throw IGEXCEPTION (CxImageIGException, "Encode", "writeSelection failed"); delete pSelectionHeader; } delete [] pLayerHeader; // write ig format header if (!hFile->Seek (0, SEEK_SET)) throw IGEXCEPTION (CxImageIGException, "Encode", "hFile->Seek failed"); hFile->Write (&igHeader, sizeof(IGHEADER), 1); if (!hFile->Seek (0, SEEK_END)) throw IGEXCEPTION (CxImageIGException, "Encode", "hFile->Seek failed"); return TRUE; }
bool CxImagePCX::Encode(CxFile * hFile) { if (EncodeSafeCheck(hFile)) return false; try { PCXHEADER pcxHeader; memset(&pcxHeader,0,sizeof(pcxHeader)); pcxHeader.Manufacturer = PCX_MAGIC; pcxHeader.Version = 5; pcxHeader.Encoding = 1; pcxHeader.Xmin = 0; pcxHeader.Ymin = 0; pcxHeader.Xmax = (WORD)head.biWidth-1; pcxHeader.Ymax = (WORD)head.biHeight-1; pcxHeader.Hres = (WORD)info.xDPI; pcxHeader.Vres = (WORD)info.yDPI; pcxHeader.Reserved = 0; pcxHeader.PaletteType = head.biClrUsed==0; switch(head.biBitCount){ case 24: case 8: { pcxHeader.BitsPerPixel = 8; pcxHeader.ColorPlanes = head.biClrUsed==0 ? 3 : 1; #if CXIMAGE_SUPPORT_ALPHA if (AlphaIsValid() && head.biClrUsed==0) pcxHeader.ColorPlanes =4; #endif //CXIMAGE_SUPPORT_ALPHA pcxHeader.BytesPerLine = (WORD)head.biWidth; break; } default: //(4 1) pcxHeader.BitsPerPixel = 1; pcxHeader.ColorPlanes = head.biClrUsed==16 ? 4 : 1; pcxHeader.BytesPerLine = (WORD)((head.biWidth * pcxHeader.BitsPerPixel + 7)>>3); } if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 1){ pcxHeader.ColorMap[0][0] = pcxHeader.ColorMap[0][1] = pcxHeader.ColorMap[0][2] = 0; pcxHeader.ColorMap[1][0] = pcxHeader.ColorMap[1][1] = pcxHeader.ColorMap[1][2] = 255; } if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 4){ RGBQUAD c; for (int i = 0; i < 16; i++){ c=GetPaletteColor(i); pcxHeader.ColorMap[i][0] = c.rgbRed; pcxHeader.ColorMap[i][1] = c.rgbGreen; pcxHeader.ColorMap[i][2] = c.rgbBlue; } } pcxHeader.BytesPerLine = (pcxHeader.BytesPerLine + 1)&(~1); if (hFile->Write(&pcxHeader, sizeof(pcxHeader), 1) == 0 ) throw "cannot write PCX header"; CxMemFile buffer; buffer.Open(); BYTE c,n; long x,y; if (head.biClrUsed==0){ for (y = head.biHeight-1; y >=0 ; y--){ for (int p=0; p<pcxHeader.ColorPlanes; p++){ c=n=0; for (x = 0; x<head.biWidth; x++){ if (p==0) PCX_PackPixels(GetPixelColor(x,y).rgbRed,c,n,buffer); else if (p==1) PCX_PackPixels(GetPixelColor(x,y).rgbGreen,c,n,buffer); else if (p==2) PCX_PackPixels(GetPixelColor(x,y).rgbBlue,c,n,buffer); #if CXIMAGE_SUPPORT_ALPHA else if (p==3) PCX_PackPixels(AlphaGet(x,y),c,n,buffer); #endif //CXIMAGE_SUPPORT_ALPHA } PCX_PackPixels(-1-(head.biWidth&0x1),c,n,buffer); } } hFile->Write(buffer.GetBuffer(false),buffer.Size(),1); } else if (head.biBitCount==8) { for (y = head.biHeight-1; y >=0 ; y--){ c=n=0; for (x = 0; x<head.biWidth; x++){ PCX_PackPixels(GetPixelIndex(x,y),c,n,buffer); } PCX_PackPixels(-1-(head.biWidth&0x1),c,n,buffer); } hFile->Write(buffer.GetBuffer(false),buffer.Size(),1); if (head.biBitCount == 8){ hFile->PutC(0x0C); BYTE* pal = (BYTE*)malloc(768); RGBQUAD c; for (int i=0;i<256;i++){ c=GetPaletteColor(i); pal[3*i+0] = c.rgbRed; pal[3*i+1] = c.rgbGreen; pal[3*i+2] = c.rgbBlue; } hFile->Write(pal,768,1); free(pal); } } else { //(head.biBitCount==4) || (head.biBitCount==1) RGBQUAD *rgb = GetPalette(); bool binvert = false; if (CompareColors(&rgb[0],&rgb[1])>0) binvert=(head.biBitCount==1); BYTE* plane = (BYTE*)malloc(pcxHeader.BytesPerLine); BYTE* raw = (BYTE*)malloc(head.biWidth); for(y = head.biHeight-1; y >=0 ; y--) { for( x = 0; x < head.biWidth; x++) raw[x] = (BYTE)GetPixelIndex(x,y); if (binvert) for( x = 0; x < head.biWidth; x++) raw[x] = 1-raw[x]; for( x = 0; x < pcxHeader.ColorPlanes; x++ ) { PCX_PixelsToPlanes(raw, head.biWidth, plane, x); PCX_PackPlanes(plane, pcxHeader.BytesPerLine, buffer); } } free(plane); free(raw); hFile->Write(buffer.GetBuffer(false),buffer.Size(),1); } } catch (char *message) { strncpy(info.szLastError,message,255); return false; } return true; }