#include #include #include #include #include #include #include #include #include #include #include #include "imgProcess.h" #include "smpVideo.h" imgProcess::imgProcess() { _client = 0; _image = NULL; _imageFormat = NULL; _errno = ilOKAY; _error[0] = '\0'; } imgProcess::imgProcess(int width, int height, short channels) { iflSize size(width,height,channels); _image = new ilMemoryImg(size,iflUChar); _image->setOrientation(iflUpperLeftOrigin); switch (channels) { case 1:_image->setColorModel(iflRGBPalette);break; case 3:_image->setColorModel(iflRGB);break; case 4:_image->setColorModel(iflRGBA);break; default:delete _image; _image = NULL; setError((ilStatus)ilABORTED, "Channel count not allowed"); } _imageFormat = NULL; _errno = ilOKAY; _error[0] = '\0'; } imgProcess::imgProcess(imgProcess *image) { common_init(image->_image); } imgProcess::imgProcess(ilImage *image) { common_init(image); } void imgProcess::common_init(ilImage *image) { _imageFormat = NULL; _errno = ilOKAY; _error[0] = '\0'; if (image == NULL) { _image = NULL; setError((ilStatus)ilABORTED, "No imagedata"); return; } iflSize size; iflOrder order = image->getOrder(); iflDataType dataType = image->getDataType(); image->getSize(size); ilMemoryImg *img = new ilMemoryImg(size,dataType,order); img->setOrientation(iflUpperLeftOrigin); img->copy(image); _image = img; } imgProcess::~imgProcess() { if (_client) return ;//damn il bug, dont delete my shared arena if (_image > 0) { delete _image; _image = NULL; } deleteQue(); } void imgProcess::deleteQue() { while (_que.begin() != _que.end()) { ilImage *image = _que.back(); delete image; _que.pop_back(); } } void imgProcess::setError(ilStatus status) { ilStatusToString(status, _error, ERRORSTR_LENGTH); _errno = status; } void imgProcess::setError(iflStatus status) { setError(ilStatusFromIflStatus(status)); } void imgProcess::setError(ilStatus status, const char *str) { _errno = status; strncpy(_error, str, ERRORSTR_LENGTH); } void imgProcess::printError() { printf("%s\n",getErrorString()); } char * imgProcess::getErrorString() { static char str[2048]; sprintf(str,"imgProcess: %.2007s (%d)",_error, _errno); return str; } ilStatus imgProcess::getStatus() { return _errno; } int imgProcess::getWidth() { if (_image <= 0) { setError((ilStatus)ilABORTED, "No imagedata for getX"); return -1; } return _image->getXsize(); } int imgProcess::getHeight() { if (_image <= 0) { setError((ilStatus)ilABORTED, "No imagedata for getY"); return -1; } return _image->getYsize(); } int imgProcess::getChannels() { if (_image <= 0) { setError((ilStatus)ilABORTED, "No imagedata for getC"); return -1; } return _image->getCsize(); } const char * imgProcess::getImageFormatName() { return _imageFormat; } short imgProcess::load(int fd) { return (load( fd, NULL)); } short imgProcess::load(const char *filename) { return (load( -1, filename)); } short imgProcess::load(int fd, const char *filename) { ilFileImg *file = new ilFileImg(fd, filename, O_RDONLY); if (file == NULL || file->getStatus() != ilOKAY) { setError(file->getStatus()); delete file; return -1; } if (_image > 0) { delete _image; } deleteQue(); _imageFormat = (char *)file->getImageFormatName(); _image = file; return 1; } short imgProcess::save(int fd, const char *format) { return (save(fd, NULL, format)); } short imgProcess::save(const char *filename, const char *format) { return (save( -1, filename, format)); } short imgProcess::save(int fd, const char *filename, const char *format) { ilStatus error; if (_image <= 0) { setError((ilStatus)ilABORTED, "No imagedata to save"); return -1; } iflFormat* ilformat = iflFormat::findByFormatName(format); if (! format) { setError((ilStatus)ilABORTED, "iflFormat not found"); return -1; } // hurra, hurra, there is a il bug, can not save a jpg from a (A)BGR model if ((_image->getColorModel() == iflABGR || _image->getColorModel() == iflBGR) && !strcmp(format, "JFIF")) { ilImage *img = copyImg(_image, iflRGBA); if (img == NULL) { setError((ilStatus)ilABORTED, "cant copy img for JFIF bug"); return -1; } //damn an other il bug, dont delete my shared arena if (!_client) { delete _image; deleteQue(); } _image = img; } ilFileImg *file; if (_image->getColorModel() != iflRGBA && _image->getColorModel() != iflRGB && !strcmp(format, "TIFF")) { // TIFF standard color model should me RGB(A) iflColorModel clMdl; iflFileConfig *cfg = new iflFileConfig(); switch (_image->getColorModel()) { case iflCMYK: case iflABGR:clMdl=iflRGBA;break; default:clMdl=iflRGB; } cfg->setColorModel(clMdl); file = new ilFileImg(fd, filename, _image, cfg, ilformat); delete cfg; } else { file = new ilFileImg(fd, filename, _image, NULL, ilformat); } if (file <= 0 || file->getStatus() != ilOKAY) { setError(file->getStatus()); delete file; return -1; } file->copy(_image); //file->copyTileCfg(0,0,0, _image->getXsize(), _image->getYsize(), 1, _image, 0,0,0); if (file->getStatus() != ilOKAY) { setError(file->getStatus()); delete file; return -1; } error = file->flush(); if (error != iflOKAY) { setError(error); delete file; return -1; } //_imageFormat = (char *)file->getImageFormatName(); delete file; return 1; } short imgProcess::copyTile(int destX, int destY, int width, int height, imgProcess *srcImage, int srcX, int srcY) { if (_image <= 0) { setError((ilStatus)ilABORTED, "No dst imagedata to copy"); return -1; } if (srcImage->_image <= 0) { setError((ilStatus)ilABORTED, "No src imagedata to copy"); return -1; } ilStatus status =_image->copyTile(destX, destY, width, height, srcImage->_image, srcX, srcY, NULL); if (status != ilOKAY) { setError(status); return -1; } return 1; } short imgProcess::setPixel(int x, int y, char r, char g, char b, char a) { char map[4]; int count; if (_image->isWritable() != TRUE) { ilImage *tmpImage = copyImg(_image, _image->getColorModel()); if (tmpImage == NULL) { setError((ilStatus)ilABORTED, "Cant copy image, have to coz image is not writable"); return -1; } delete _image; deleteQue(); _image = tmpImage; _errno = ilOKAY; } if (_image->getColorModel() == iflRGB) { map[0] = r; map[1] = g; map[2] = b; count = 3; } else if (_image->getColorModel() == iflRGBA) { map[0] = r; map[1] = g; map[2] = b; map[3] = a; count = 4; } else if (_image->getColorModel() == iflBGR) { map[0] = b; map[1] = g; map[2] = r; count = 3; } else if (_image->getColorModel() == iflABGR) { map[0] = a; map[1] = b; map[2] = g; map[3] = r; count = 4; } else { // todo map[0] = r; map[1] = g; map[2] = b; //map[3] = a; count = 3; //puts("ELSE"); } iflPixel pixel(iflChar, count, map); ilStatus status = _image->setPixel(x, y, pixel); if (status != ilOKAY) { setError(status); return -1; } return 1; } short imgProcess::getVideoSnapshot() { char *dataPtr; int xsize, ysize; char errorString[ERRORSTR_LENGTH]; smpVideo *vid = new smpVideo; if ((vid->openVideo()) < 0) { vid->getErrorStrFmt(errorString); setError((ilStatus)ilABORTED, errorString); delete vid; return -1; } if ((vid->setVideoInPath()) < 0) { vid->getErrorStrFmt(errorString); setError((ilStatus)ilABORTED, errorString); delete vid; return -1; } if ((vid->createBuffer(1)) < 0) { vid->getErrorStrFmt(errorString); setError((ilStatus)ilABORTED, errorString); delete vid; return -1; } if ((vid->beginTransfer()) < 0) { vid->getErrorStrFmt(errorString); setError((ilStatus)ilABORTED, errorString); delete vid; return -1; } if ((vid->waitTransferDone()) < 0) { vid->getErrorStrFmt(errorString); setError((ilStatus)ilABORTED, errorString); delete vid; return -1; } if ((vid->getVideoSize(&xsize, &ysize)) < 0) { vid->getErrorStrFmt(errorString); setError((ilStatus)ilABORTED, errorString); delete vid; return -1; } if ((dataPtr = (char *)vid->getFramePointer(1)) <= 0) { vid->getErrorStrFmt(errorString); setError((ilStatus)ilABORTED, errorString); delete vid; return -1; } iflSize imgSize(xsize, ysize, 1, 4); ilMemoryImg *tmpImage = new ilMemoryImg(NULL, imgSize, iflUChar); tmpImage->setColorModel(iflABGR); tmpImage->setOrientation(iflUpperLeftOrigin); if (tmpImage->getStatus() != ilOKAY) { setError(tmpImage->getStatus()); delete tmpImage; delete vid; return -1; } tmpImage->setTile(0,0,xsize,ysize,dataPtr); if (_image > 0) { delete _image; } deleteQue(); _image = tmpImage; _imageFormat = "RGB"; delete vid; return 1; } short imgProcess::rotateZoom(float angle, float zoomX, float zoomY, unsigned short resampleType) { if (_image <= 0) { setError((ilStatus)ilABORTED, "No imagedata to rotate/zoom"); return -1; } ilRotZoomImg *rotateZoom = new ilRotZoomImg(_image, angle, zoomX, zoomY, (ilResampType)resampleType); if (rotateZoom->getStatus() != ilOKAY) { setError(rotateZoom->getStatus()); delete rotateZoom; return -1; } _que.push_back(_image); _image = rotateZoom; return 1; } short imgProcess::blur(float blur, int width, int height, double biasValue, unsigned short edgeMode) { if (_image <= 0) { setError((ilStatus)ilABORTED, "No imagedata for blur"); return -1; } ilGBlurImg *blurImg = new ilGBlurImg(_image, blur, width, height, biasValue, (ilEdgeMode)edgeMode); if (blurImg->getStatus() != ilOKAY) { setError(blurImg->getStatus()); delete blurImg; return -1; } _que.push_back(_image); _image = blurImg; return 1; } short imgProcess::sharp(float sharpness, float radius, unsigned short edgeMode) { if (_image <= 0) { setError((ilStatus)ilABORTED, "No imagedata to draw sharp"); return -1; } ilSharpenImg *sharpImg = new ilSharpenImg(_image, sharpness, radius, (ilEdgeMode)edgeMode); if (sharpImg->getStatus() != ilOKAY) { setError(sharpImg->getStatus()); delete sharpImg; return -1; } _que.push_back(_image); _image = sharpImg; return 1; } short imgProcess::compass(float radius, double biasVal, int kernSize, unsigned short edgeMode) { if (_image <= 0) { setError((ilStatus)ilABORTED, "No imagedata for compass"); return -1; } ilCompassImg *compassImg = new ilCompassImg(_image, radius, biasVal, kernSize, (ilEdgeMode)edgeMode); if (compassImg->getStatus() != ilOKAY) { setError(compassImg->getStatus()); delete compassImg; return -1; } _que.push_back(_image); _image = compassImg; return 1; } short imgProcess::laplace(double biasVal, unsigned short edgeMode, int kernSize) { if (_image <= 0) { setError((ilStatus)ilABORTED, "No imagedata for laplace"); return -1; } ilLaplaceImg *laplaceImg = new ilLaplaceImg(_image, biasVal, (ilEdgeMode)edgeMode, kernSize); if (laplaceImg->getStatus() != ilOKAY) { setError(laplaceImg->getStatus()); delete laplaceImg; return -1; } _que.push_back(_image); _image = laplaceImg; return 1; } short imgProcess::edgeDetection(double biasVal, unsigned short edgeMode) { if (_image <= 0) { setError((ilStatus)ilABORTED, "No imagedata for edge detection"); return -1; } ilRobertsImg *edgeDetectionImg = new ilRobertsImg(_image, biasVal, (ilEdgeMode)edgeMode); if (edgeDetectionImg->getStatus() != ilOKAY) { setError(edgeDetectionImg->getStatus()); delete edgeDetectionImg; return -1; } _que.push_back(_image); _image = edgeDetectionImg; return 1; } short imgProcess::blendImg(imgProcess *dstimg, float alpha) { if (_image <= 0) { setError((ilStatus)ilABORTED, "No src imagedata for blending images"); return -1; } if (dstimg->_image <= 0) { setError((ilStatus)ilABORTED, "No dst imagedata for blending images"); return -1; } ilBlendImg *blendImg = new ilBlendImg(_image, dstimg->_image, alpha); if (blendImg->getStatus() != ilOKAY) { setError(blendImg->getStatus()); delete blendImg; return -1; } _que.push_back(_image); _image = blendImg; return 1; } short imgProcess::blendImg(imgProcess *image, imgProcess *alphaimg, ilCompose compose) { if (_image <= 0) { setError((ilStatus)ilABORTED, "No src imagedata for blending images"); return -1; } if (image->_image <= 0) { setError((ilStatus)ilABORTED, "No dst imagedata for blending images"); return -1; } if (alphaimg->_image <= 0) { setError((ilStatus)ilABORTED, "No dst imagedata for blending images"); return -1; } ilImage *useAlpha = alphaimg->_image; // convert an image with only one channel to a 4 channel image if (alphaimg->_image->getCsize() == 1) { ilImage *tmpImage = copyImg(alphaimg->_image); if (tmpImage == NULL) { return -1; } // remember the img useAlpha = tmpImage; _que.push_back(tmpImage); } ilBlendImg *blendImg = new ilBlendImg(_image, image->_image, useAlpha, NULL, compose); if (blendImg->getStatus() != ilOKAY) { setError(blendImg->getStatus()); delete blendImg; delete _que.back(); _que.pop_back(); return -1; } _que.push_back(_image); _image = blendImg; return 1; } short imgProcess::add(imgProcess *addImg, double bias) { if (_image <= 0) { setError((ilStatus)ilABORTED, "No src imagedata for adding images"); return -1; } if (addImg->_image <= 0) { setError((ilStatus)ilABORTED, "No addImg imagedata for adding images"); return -1; } ilImage *addImgCopy = copyImg(addImg->_image, addImg->_image->getColorModel()); if (addImgCopy == NULL) { return -1; } ilAddImg *addi = new ilAddImg(_image, addImgCopy, bias); if (addi->getStatus() != ilOKAY) { setError(addi->getStatus()); delete addi; delete addImgCopy; return -1; } _que.push_back(_image); _que.push_back(addImgCopy); _image = addi; return 1; } ilImage * imgProcess::copyImg(ilImage *src, iflColorModel colorModel) { int channels; switch (colorModel) { case iflCMYK: case iflRGBA: case iflABGR:channels=4;break; case iflRGBPalette: // damn an other bug, cant copy a RGBPalette pic //channels=1; channels=3; colorModel=iflRGB; break; case iflRGB: case iflBGR:channels=3;break; default:channels=3;puts("WARNING: unsupported color model\n"); } iflSize imgSize(src->getXsize(), src->getYsize(), 1, channels); ilMemoryImg *tmpImage = new ilMemoryImg(imgSize, src->getDataType(), src->getOrder()); tmpImage->setOrientation(iflUpperLeftOrigin); if (tmpImage->setColorModel(colorModel) != iflOKAY) { puts("aaaaaargh cant set color model"); delete tmpImage; return NULL; } if (tmpImage->getStatus() != ilOKAY) { //setError(tmpImage->getStatus()); delete tmpImage; return NULL; } if (src->getColorModel() == iflRGBPalette && colorModel == iflRGBPalette) tmpImage->setColormap(*(src->getColormap())); if (tmpImage->getStatus() != ilOKAY) { //setError(tmpImage->getStatus()); delete tmpImage; return NULL; } tmpImage->copy(src); if (tmpImage->getStatus() != ilOKAY) { //setError(tmpImage->getStatus()); delete tmpImage; return NULL; } return tmpImage; } void imgProcess::setClient(short st) { _client = st; }