bool CxImage::SelectionFlip() { if (!pSelection) return false; BYTE *buff = (BYTE*)cxalloc(head.biWidth);//malloc(head.biWidth); if (!buff) return false; BYTE *iSrc,*iDst; iSrc = pSelection + (head.biHeight-1)*head.biWidth; iDst = pSelection; for (long i=0; i<(head.biHeight/2); ++i) { memcpy(buff, iSrc, head.biWidth); memcpy(iSrc, iDst, head.biWidth); memcpy(iDst, buff, head.biWidth); iSrc-=head.biWidth; iDst+=head.biWidth; } cxfree(buff);//free(buff); long top = info.rSelectionBox.top; info.rSelectionBox.top = head.biHeight - info.rSelectionBox.bottom; info.rSelectionBox.bottom = head.biHeight - top; return true; }
void CxImageJPG::CxExifInfo::DiscardAllButExif() { Section_t ExifKeeper; Section_t CommentKeeper; int a; memset(&ExifKeeper, 0, sizeof(ExifKeeper)); memset(&CommentKeeper, 0, sizeof(ExifKeeper)); for (a=0;a<SectionsRead;a++){ if (Sections[a].Type == M_EXIF && ExifKeeper.Type == 0){ ExifKeeper = Sections[a]; }else if (Sections[a].Type == M_COM && CommentKeeper.Type == 0){ CommentKeeper = Sections[a]; }else{ cxfree(Sections[a].Data);//free(Sections[a].Data); Sections[a].Data = 0; } } SectionsRead = 0; if (ExifKeeper.Type){ Sections[SectionsRead++] = ExifKeeper; } if (CommentKeeper.Type){ Sections[SectionsRead++] = CommentKeeper; } }
/** * Deallocates the selction. */ bool CxImage::SelectionDelete() { if (pSelection){ cxfree(pSelection);//free(pSelection); pSelection=NULL; } info.rSelectionBox.left = head.biWidth; info.rSelectionBox.bottom = head.biHeight; info.rSelectionBox.right = info.rSelectionBox.top = 0; return true; }
bool CxImage::SelectionMirror() { if (!pSelection) return false; BYTE* pSelection2 = (BYTE*)cxalloc(head.biWidth * head.biHeight);//malloc(head.biWidth * head.biHeight); if (!pSelection2) return false; BYTE *iSrc,*iDst; long wdt=head.biWidth-1; iSrc=pSelection + wdt; iDst=pSelection2; for(long y=0; y < head.biHeight; y++){ for(long x=0; x <= wdt; x++) *(iDst+x)=*(iSrc-x); iSrc+=head.biWidth; iDst+=head.biWidth; } cxfree(pSelection);//free(pSelection); pSelection=pSelection2; long left = info.rSelectionBox.left; info.rSelectionBox.left = head.biWidth - info.rSelectionBox.right; info.rSelectionBox.right = head.biWidth - left; return true; }
/** * Match a window against a single leaf window condition. * * For internal use. */ static inline void c2_match_once_leaf(session_t *ps, win *w, const c2_l_t *pleaf, bool *pres, bool *perr) { assert(pleaf); const Window wid = (pleaf->tgt_onframe ? w->client_win: w->id); // Return if wid is missing if (!pleaf->predef && !wid) return; const int idx = (pleaf->index < 0 ? 0: pleaf->index); switch (pleaf->ptntype) { // Deal with integer patterns case C2_L_PTINT: { long tgt = 0; // Get the value // A predefined target if (pleaf->predef) { *perr = false; switch (pleaf->predef) { case C2_L_PID: tgt = wid; break; case C2_L_PX: tgt = w->a.x; break; case C2_L_PY: tgt = w->a.y; break; case C2_L_PX2: tgt = w->a.x + w->widthb; break; case C2_L_PY2: tgt = w->a.y + w->heightb; break; case C2_L_PWIDTH: tgt = w->a.width; break; case C2_L_PHEIGHT: tgt = w->a.height; break; case C2_L_PWIDTHB: tgt = w->widthb; break; case C2_L_PHEIGHTB: tgt = w->heightb; break; case C2_L_PBDW: tgt = w->a.border_width; break; case C2_L_PFULLSCREEN: tgt = win_is_fullscreen(ps, w); break; case C2_L_POVREDIR: tgt = w->a.override_redirect; break; case C2_L_PARGB: tgt = (WMODE_ARGB == w->mode); break; case C2_L_PFOCUSED: tgt = w->focused_real; break; case C2_L_PWMWIN: tgt = w->wmwin; break; case C2_L_PCLIENT: tgt = w->client_win; break; case C2_L_PLEADER: tgt = w->leader; break; default: *perr = true; assert(0); break; } } // A raw window property else { winprop_t prop = wid_get_prop_adv(ps, wid, pleaf->tgtatom, idx, 1L, c2_get_atom_type(pleaf), pleaf->format); if (prop.nitems) { *perr = false; tgt = winprop_get_int(prop); } free_winprop(&prop); } if (*perr) return; // Do comparison switch (pleaf->op) { case C2_L_OEXISTS: *pres = (pleaf->predef ? tgt: true); break; case C2_L_OEQ: *pres = (tgt == pleaf->ptnint); break; case C2_L_OGT: *pres = (tgt > pleaf->ptnint); break; case C2_L_OGTEQ: *pres = (tgt >= pleaf->ptnint); break; case C2_L_OLT: *pres = (tgt < pleaf->ptnint); break; case C2_L_OLTEQ: *pres = (tgt <= pleaf->ptnint); break; default: *perr = true; assert(0); break; } } break; // String patterns case C2_L_PTSTRING: { const char *tgt = NULL; char *tgt_free = NULL; // A predefined target if (pleaf->predef) { switch (pleaf->predef) { case C2_L_PWINDOWTYPE: tgt = WINTYPES[w->window_type]; break; case C2_L_PNAME: tgt = w->name; break; case C2_L_PCLASSG: tgt = w->class_general; break; case C2_L_PCLASSI: tgt = w->class_instance; break; case C2_L_PROLE: tgt = w->role; break; default: assert(0); break; } } // If it's an atom type property, convert atom to string else if (C2_L_TATOM == pleaf->type) { winprop_t prop = wid_get_prop_adv(ps, wid, pleaf->tgtatom, idx, 1L, c2_get_atom_type(pleaf), pleaf->format); Atom atom = winprop_get_int(prop); if (atom) { tgt_free = XGetAtomName(ps->dpy, atom); } if (tgt_free) { tgt = tgt_free; } free_winprop(&prop); } // Otherwise, just fetch the string list else { char **strlst = NULL; int nstr; if (wid_get_text_prop(ps, wid, pleaf->tgtatom, &strlst, &nstr) && nstr > idx) { tgt_free = mstrcpy(strlst[idx]); tgt = tgt_free; } if (strlst) XFreeStringList(strlst); } if (tgt) { *perr = false; } else { return; } // Actual matching switch (pleaf->op) { case C2_L_OEXISTS: *pres = true; break; case C2_L_OEQ: switch (pleaf->match) { case C2_L_MEXACT: if (pleaf->match_ignorecase) *pres = !strcasecmp(tgt, pleaf->ptnstr); else *pres = !strcmp(tgt, pleaf->ptnstr); break; case C2_L_MCONTAINS: if (pleaf->match_ignorecase) *pres = strcasestr(tgt, pleaf->ptnstr); else *pres = strstr(tgt, pleaf->ptnstr); break; case C2_L_MSTART: if (pleaf->match_ignorecase) *pres = !strncasecmp(tgt, pleaf->ptnstr, strlen(pleaf->ptnstr)); else *pres = !strncmp(tgt, pleaf->ptnstr, strlen(pleaf->ptnstr)); break; case C2_L_MWILDCARD: { int flags = 0; if (pleaf->match_ignorecase) flags |= FNM_CASEFOLD; *pres = !fnmatch(pleaf->ptnstr, tgt, flags); } break; case C2_L_MPCRE: #ifdef CONFIG_REGEX_PCRE *pres = (pcre_exec(pleaf->regex_pcre, pleaf->regex_pcre_extra, tgt, strlen(tgt), 0, 0, NULL, 0) >= 0); #else assert(0); #endif break; } break; default: *perr = true; assert(0); } // Free the string after usage, if necessary if (tgt_free) { if (C2_L_TATOM == pleaf->type) cxfree(tgt_free); else free(tgt_free); } } break; default: assert(0); break; } }
void CxImage::AlphaDelete() { if (pAlpha) { cxfree(pAlpha);/*free(pAlpha);*/ pAlpha=0; } }
bool CxImageJPG::CxExifInfo::DecodeExif(CxFile * hFile, int nReadMode) { int a; int HaveCom = FALSE; a = hFile->GetC(); if (a != 0xff || hFile->GetC() != M_SOI){ return FALSE; } for(;;){ int itemlen; int marker = 0; int ll,lh, got; BYTE * Data; if (SectionsRead >= MAX_SECTIONS){ strcpy(m_szLastError,"Too many sections in jpg file"); return false; } for (a=0;a<7;a++){ marker = hFile->GetC(); if (marker != 0xff) break; if (a >= 6){ printf("too many padding bytes\n"); return false; } } if (marker == 0xff){ // 0xff is legal padding, but if we get that many, something's wrong. strcpy(m_szLastError,"too many padding bytes!"); return false; } Sections[SectionsRead].Type = marker; // Read the length of the section. lh = hFile->GetC(); ll = hFile->GetC(); itemlen = (lh << 8) | ll; if (itemlen < 2){ strcpy(m_szLastError,"invalid marker"); return false; } Sections[SectionsRead].Size = itemlen; Data = (BYTE *)cxalloc(itemlen);//malloc(itemlen); if (Data == NULL){ strcpy(m_szLastError,"Could not allocate memory"); return false; } Sections[SectionsRead].Data = Data; // Store first two pre-read bytes. Data[0] = (BYTE)lh; Data[1] = (BYTE)ll; got = hFile->Read(Data+2, 1, itemlen-2); // Read the whole section. if (got != itemlen-2){ strcpy(m_szLastError,"Premature end of file?"); return false; } SectionsRead += 1; switch(marker){ case M_SOS: // stop before hitting compressed data // If reading entire image is requested, read the rest of the data. if (nReadMode & EXIF_READ_IMAGE){ int cp, ep, size; // Determine how much file is left. cp = hFile->Tell(); hFile->Seek(0, SEEK_END); ep = hFile->Tell(); hFile->Seek(cp, SEEK_SET); size = ep-cp; Data = (BYTE *)cxalloc(size);//malloc(size); if (Data == NULL){ strcpy(m_szLastError,"could not allocate data for entire image"); return false; } got = hFile->Read(Data, 1, size); if (got != size){ strcpy(m_szLastError,"could not read the rest of the image"); return false; } Sections[SectionsRead].Data = Data; Sections[SectionsRead].Size = size; Sections[SectionsRead].Type = PSEUDO_IMAGE_MARKER; SectionsRead ++; } return true; case M_EOI: // in case it's a tables-only JPEG stream printf("No image in jpeg!\n"); return FALSE; case M_COM: // Comment section if (HaveCom || ((nReadMode & EXIF_READ_EXIF) == 0)){ // Discard this section. cxfree(Sections[--SectionsRead].Data);//free(Sections[--SectionsRead].Data); Sections[SectionsRead].Data=0; }else{ process_COM(Data, itemlen); HaveCom = TRUE; } break; case M_JFIF: // Regular jpegs always have this tag, exif images have the exif // marker instead, althogh ACDsee will write images with both markers. // this program will re-create this marker on absence of exif marker. // hence no need to keep the copy from the file. cxfree(Sections[--SectionsRead].Data);//free(Sections[--SectionsRead].Data); Sections[SectionsRead].Data=0; break; case M_EXIF: // Seen files from some 'U-lead' software with Vivitar scanner // that uses marker 31 for non exif stuff. Thus make sure // it says 'Exif' in the section before treating it as exif. if ((nReadMode & EXIF_READ_EXIF) && memcmp(Data+2, "Exif", 4) == 0){ m_exifinfo->IsExif = process_EXIF((BYTE *)Data+2, itemlen); }else{ // Discard this section. cxfree(Sections[--SectionsRead].Data);//free(Sections[--SectionsRead].Data); Sections[SectionsRead].Data=0; } break; case M_SOF0: case M_SOF1: case M_SOF2: case M_SOF3: case M_SOF5: case M_SOF6: case M_SOF7: case M_SOF9: case M_SOF10: case M_SOF11: case M_SOF13: case M_SOF14: case M_SOF15: process_SOFn(Data, marker); break; default: // Skip any other sections. //if (ShowTags) printf("Jpeg section marker 0x%02x size %d\n",marker, itemlen); break; } } return true; }
CxImageJPG::CxExifInfo::~CxExifInfo() { for(int i=0;i<MAX_SECTIONS;i++) if(Sections[i].Data) cxfree(Sections[i].Data);//free(Sections[i].Data); if (freeinfo) delete m_exifinfo; }
jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) { cxfree(object);//free(object); }
jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) { cxfree(object);//free(object); }
/** * Adds a polygonal region to the existing selection. points points to an array of POINT structures. * Each structure specifies the x-coordinate and y-coordinate of one vertex of the polygon. * npoints specifies the number of POINT structures in the array pointed to by points. */ bool CxImage::SelectionAddPolygon(POINT *points, long npoints, BYTE level) { if (points==NULL || npoints<3) return false; if (pSelection==NULL) SelectionCreate(); if (pSelection==NULL) return false; BYTE* plocal = (BYTE*)calloc(head.biWidth*head.biHeight, 1); RECT localbox = {head.biWidth,0,0,head.biHeight}; long x,y,i=0; POINT *current; POINT *next = NULL; POINT *start = NULL; //trace contour while (i < npoints){ current = &points[i]; if (current->x!=-1){ if (i==0 || (i>0 && points[i-1].x==-1)) start = &points[i]; if ((i+1)==npoints || points[i+1].x==-1) next = start; else next = &points[i+1]; float beta; if (current->x != next->x){ beta = (float)(next->y - current->y)/(float)(next->x - current->x); if (current->x < next->x){ for (x=current->x; x<=next->x; x++){ y = (long)(current->y + (x - current->x) * beta); if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255; } } else { for (x=current->x; x>=next->x; x--){ y = (long)(current->y + (x - current->x) * beta); if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255; } } } if (current->y != next->y){ beta = (float)(next->x - current->x)/(float)(next->y - current->y); if (current->y < next->y){ for (y=current->y; y<=next->y; y++){ x = (long)(current->x + (y - current->y) * beta); if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255; } } else { for (y=current->y; y>=next->y; y--){ x = (long)(current->x + (y - current->y) * beta); if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255; } } } } RECT r2; if (current->x < next->x) {r2.left=current->x; r2.right=next->x; } else {r2.left=next->x ; r2.right=current->x; } if (current->y < next->y) {r2.bottom=current->y; r2.top=next->y; } else {r2.bottom=next->y ; r2.top=current->y; } if (localbox.top < r2.top) localbox.top = max(0L,min(head.biHeight-1,r2.top+1)); if (localbox.left > r2.left) localbox.left = max(0L,min(head.biWidth-1,r2.left-1)); if (localbox.right < r2.right) localbox.right = max(0L,min(head.biWidth-1,r2.right+1)); if (localbox.bottom > r2.bottom) localbox.bottom = max(0L,min(head.biHeight-1,r2.bottom-1)); i++; } //fill the outer region long npix=(localbox.right - localbox.left)*(localbox.top - localbox.bottom); POINT* pix = (POINT*)calloc(npix,sizeof(POINT)); BYTE back=0, mark=1; long fx, fy, fxx, fyy, first, last; long xmin = 0; long xmax = 0; long ymin = 0; long ymax = 0; for (int side=0; side<4; side++){ switch(side){ case 0: xmin=localbox.left; xmax=localbox.right+1; ymin=localbox.bottom; ymax=localbox.bottom+1; break; case 1: xmin=localbox.right; xmax=localbox.right+1; ymin=localbox.bottom; ymax=localbox.top+1; break; case 2: xmin=localbox.left; xmax=localbox.right+1; ymin=localbox.top; ymax=localbox.top+1; break; case 3: xmin=localbox.left; xmax=localbox.left+1; ymin=localbox.bottom; ymax=localbox.top+1; break; } //fill from the border points for(y=ymin;y<ymax;y++){ for(x=xmin;x<xmax;x++){ if (plocal[x+y*head.biWidth]==0){ // Subject: FLOOD FILL ROUTINE Date: 12-23-97 (00:57) // Author: Petter Holmberg Code: QB, QBasic, PDS // Origin: [email protected] Packet: GRAPHICS.ABC first=0; last=1; while(first!=last){ fx = pix[first].x; fy = pix[first].y; fxx = fx + x; fyy = fy + y; for(;;) { if ((plocal[fxx + fyy*head.biWidth] == back) && fxx>=localbox.left && fxx<=localbox.right && fyy>=localbox.bottom && fyy<=localbox.top ) { plocal[fxx + fyy*head.biWidth] = mark; if (fyy > 0 && plocal[fxx + (fyy - 1)*head.biWidth] == back){ pix[last].x = fx; pix[last].y = fy - 1; last++; if (last == npix) last = 0; } if ((fyy + 1)<head.biHeight && plocal[fxx + (fyy + 1)*head.biWidth] == back){ pix[last].x = fx; pix[last].y = fy + 1; last++; if (last == npix) last = 0; } } else { break; } fx++; fxx++; }; fx = pix[first].x - 1; fy = pix[first].y; fxx = fx + x; fyy = fy + y; for( ;; ) { if ((plocal[fxx + fyy*head.biWidth] == back) && fxx>=localbox.left && fxx<=localbox.right && fyy>=localbox.bottom && fyy<=localbox.top ) { plocal[fxx + (y + fy)*head.biWidth] = mark; if (fyy > 0 && plocal[fxx + (fyy - 1)*head.biWidth] == back){ pix[last].x = fx; pix[last].y = fy - 1; last++; if (last == npix) last = 0; } if ((fyy + 1)<head.biHeight && plocal[fxx + (fyy + 1)*head.biWidth] == back){ pix[last].x = fx; pix[last].y = fy + 1; last++; if (last == npix) last = 0; } } else { break; } fx--; fxx--; } first++; if (first == npix) first = 0; } } } } } //transfer the region long yoffset; for (y=localbox.bottom; y<=localbox.top; y++){ yoffset = y * head.biWidth; for (x=localbox.left; x<=localbox.right; x++) if (plocal[x + yoffset]!=1) pSelection[x + yoffset]=level; } if (info.rSelectionBox.top <= localbox.top) info.rSelectionBox.top = min(head.biHeight,localbox.top + 1); if (info.rSelectionBox.left > localbox.left) info.rSelectionBox.left = min(head.biWidth,localbox.left); if (info.rSelectionBox.right <= localbox.right) info.rSelectionBox.right = min(head.biWidth,localbox.right + 1); if (info.rSelectionBox.bottom > localbox.bottom) info.rSelectionBox.bottom = min(head.biHeight,localbox.bottom); cxfree(plocal);//free(plocal); cxfree(pix);//free(pix); return true; }