bool ofPixels_<PixelType>::pasteInto(ofPixels_<PixelType> &dst, int xTo, int yTo) const{ if (!(isAllocated()) || !(dst.isAllocated()) || getBytesPerPixel() != dst.getBytesPerPixel() || xTo + getWidth()>dst.getWidth() || yTo + getHeight()>dst.getHeight()) return false; int bytesToCopyPerRow = (xTo + getWidth()<=dst.getWidth() ? getWidth() : dst.getWidth()-xTo) * getBytesPerPixel(); int columnsToCopy = yTo + getHeight() <= dst.getHeight() ? getHeight() : dst.getHeight()-yTo; PixelType * dstPix = dst.getData() + ((xTo + yTo*dst.getWidth())*dst.getBytesPerPixel()); const PixelType * srcPix = getData(); int srcStride = getWidth()*getBytesPerPixel(); int dstStride = dst.getWidth()*dst.getBytesPerPixel(); for(int y=0;y<columnsToCopy; y++){ memcpy(dstPix,srcPix,bytesToCopyPerRow); dstPix += dstStride; srcPix += srcStride; } return true; }
bool ofPixels_<PixelType>::blendInto(ofPixels_<PixelType> &dst, int xTo, int yTo) const{ if (!(isAllocated()) || !(dst.isAllocated()) || getBytesPerPixel() != dst.getBytesPerPixel() || xTo + getWidth()>dst.getWidth() || yTo + getHeight()>dst.getHeight() || getNumChannels()==0) return false; std::function<void(const ConstPixel&,Pixel&)> blendFunc; switch(getNumChannels()){ case 1: blendFunc = [](const ConstPixel&src, Pixel&dst){ dst[0] = clampedAdd(src[0], dst[0]); }; break; case 2: blendFunc = [](const ConstPixel&src, Pixel&dst){ dst[0] = clampedAdd(src[0], dst[0] / ofColor_<PixelType>::limit() * (ofColor_<PixelType>::limit() - src[1])); dst[1] = clampedAdd(src[1], dst[1] / ofColor_<PixelType>::limit() * (ofColor_<PixelType>::limit() - src[1])); }; break; case 3: blendFunc = [](const ConstPixel&src, Pixel&dst){ dst[0] = clampedAdd(src[0], dst[0]); dst[1] = clampedAdd(src[1], dst[1]); dst[2] = clampedAdd(src[2], dst[2]); }; break; case 4: blendFunc = [](const ConstPixel&src, Pixel&dst){ dst[0] = clampedAdd(src[0], dst[0] / ofColor_<PixelType>::limit() * (ofColor_<PixelType>::limit() - src[3])); dst[1] = clampedAdd(src[1], dst[1] / ofColor_<PixelType>::limit() * (ofColor_<PixelType>::limit() - src[3])); dst[2] = clampedAdd(src[2], dst[2] / ofColor_<PixelType>::limit() * (ofColor_<PixelType>::limit() - src[3])); dst[3] = clampedAdd(src[3], dst[3] / ofColor_<PixelType>::limit() * (ofColor_<PixelType>::limit() - src[3])); }; break; } auto dstLine = dst.getLine(yTo); for(auto line: getConstLines()){ auto dstPixel = dstLine.getPixels().begin() + xTo; for(auto p: line.getPixels()){ blendFunc(p,dstPixel); dstPixel++; } dstLine++; } return true; }
static void saveImage(ofPixels_<PixelType> & pix, ofBuffer & buffer, ofImageFormat format, ofImageQualityType qualityLevel) { //thanks to alvaro casinelli for the implementation ofInitFreeImage(); if (pix.isAllocated() == false){ ofLog(OF_LOG_ERROR,"error saving image - pixels aren't allocated"); return; } #ifdef TARGET_LITTLE_ENDIAN if(sizeof(PixelType) == 1) { pix.swapRgb(); } #endif FIBITMAP * bmp = getBmpFromPixels(pix); #ifdef TARGET_LITTLE_ENDIAN if(sizeof(PixelType) == 1) { pix.swapRgb(); } #endif if (bmp) // bitmap successfully created { // (b) open a memory stream to compress the image onto mem_buffer: // FIMEMORY *hmem = FreeImage_OpenMemory(); // (c) encode and save the image to the memory (on dib FIBITMAP image): // if(FREE_IMAGE_FORMAT(format) == FIF_JPEG) { int quality = JPEG_QUALITYSUPERB; switch(qualityLevel) { case OF_IMAGE_QUALITY_WORST: quality = JPEG_QUALITYBAD; break; case OF_IMAGE_QUALITY_LOW: quality = JPEG_QUALITYAVERAGE; break; case OF_IMAGE_QUALITY_MEDIUM: quality = JPEG_QUALITYNORMAL; break; case OF_IMAGE_QUALITY_HIGH: quality = JPEG_QUALITYGOOD; break; case OF_IMAGE_QUALITY_BEST: quality = JPEG_QUALITYSUPERB; break; } FreeImage_SaveToMemory(FIF_JPEG, bmp, hmem, quality); }else{ FreeImage_SaveToMemory((FREE_IMAGE_FORMAT)format, bmp, hmem); } /* NOTE: at this point, hmem contains the entire data in memory stored in fif format. the amount of space used by the memory is equal to file_size: long file_size = FreeImage_TellMemory(hmem); but can also be retrieved by FreeImage_AcquireMemory that retrieves both the length of the buffer, and the buffer memory address. */ #ifdef TARGET_WIN32 DWORD size_in_bytes = 0; #else uint32_t size_in_bytes = 0; #endif // Save compressed data on mem_buffer // note: FreeImage_AquireMemory allocates space for aux_mem_buffer): // unsigned char *mem_buffer = NULL; if (!FreeImage_AcquireMemory(hmem, &mem_buffer, &size_in_bytes)) cout << "Error aquiring compressed image from memory" << endl; /* Now, before closing the memory stream, copy the content of mem_buffer to an auxiliary buffer */ buffer.set((char*)mem_buffer,size_in_bytes); // Finally, close the FIBITMAP object, or we will get a memory leak: FreeImage_Unload(bmp); // Close the memory stream (otherwise we may get a memory leak). FreeImage_CloseMemory(hmem); } }
static void saveImage(ofPixels_<PixelType> & pix, string fileName, ofImageQualityType qualityLevel) { ofInitFreeImage(); if (pix.isAllocated() == false){ ofLog(OF_LOG_ERROR,"error saving image - pixels aren't allocated"); return; } #ifdef TARGET_LITTLE_ENDIAN if(sizeof(PixelType) == 1) { pix.swapRgb(); } #endif FIBITMAP * bmp = getBmpFromPixels(pix); #ifdef TARGET_LITTLE_ENDIAN if(sizeof(PixelType) == 1) { pix.swapRgb(); } #endif fileName = ofToDataPath(fileName); FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; fif = FreeImage_GetFileType(fileName.c_str(), 0); if(fif == FIF_UNKNOWN) { // or guess via filename fif = FreeImage_GetFIFFromFilename(fileName.c_str()); } if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) { if(fif == FIF_JPEG) { int quality = JPEG_QUALITYSUPERB; switch(qualityLevel) { case OF_IMAGE_QUALITY_WORST: quality = JPEG_QUALITYBAD; break; case OF_IMAGE_QUALITY_LOW: quality = JPEG_QUALITYAVERAGE; break; case OF_IMAGE_QUALITY_MEDIUM: quality = JPEG_QUALITYNORMAL; break; case OF_IMAGE_QUALITY_HIGH: quality = JPEG_QUALITYGOOD; break; case OF_IMAGE_QUALITY_BEST: quality = JPEG_QUALITYSUPERB; break; } FreeImage_Save(fif, bmp, fileName.c_str(), quality); } else { if(qualityLevel != OF_IMAGE_QUALITY_BEST) { ofLogWarning() << "ofImageCompressionType only applies to JPEG images, ignoring value"; } if (fif == FIF_GIF) { FIBITMAP* convertedBmp; if(pix.getImageType() == OF_IMAGE_COLOR_ALPHA) { // this just converts the image to grayscale so it can save something convertedBmp = FreeImage_ConvertTo8Bits(bmp); } else { // this will create a 256-color palette from the image convertedBmp = FreeImage_ColorQuantize(bmp, FIQ_NNQUANT); } FreeImage_Save(fif, convertedBmp, fileName.c_str()); if (convertedBmp != NULL){ FreeImage_Unload(convertedBmp); } } else { FreeImage_Save(fif, bmp, fileName.c_str()); } } } if (bmp != NULL){ FreeImage_Unload(bmp); } }
void ofPixels_<PixelType>::copyFrom(const ofPixels_<PixelType> & mom){ if(mom.isAllocated()) { allocate(mom.getWidth(), mom.getHeight(), mom.getPixelFormat()); memcpy(pixels, mom.getData(), getTotalBytes()); } }
bool ofPixels_<PixelType>::resizeTo(ofPixels_<PixelType>& dst, ofInterpolationMethod interpMethod) const{ if(&dst == this){ return true; } if (!(isAllocated()) || !(dst.isAllocated()) || getBytesPerPixel() != dst.getBytesPerPixel()) return false; int srcWidth = getWidth(); int srcHeight = getHeight(); int dstWidth = dst.getWidth(); int dstHeight = dst.getHeight(); int bytesPerPixel = getBytesPerPixel(); PixelType * dstPixels = dst.getData(); switch (interpMethod){ //---------------------------------------- case OF_INTERPOLATE_NEAREST_NEIGHBOR:{ int dstIndex = 0; float srcxFactor = (float)srcWidth/dstWidth; float srcyFactor = (float)srcHeight/dstHeight; float srcy = 0.5; for (int dsty=0; dsty<dstHeight; dsty++){ float srcx = 0.5; int srcIndex = int(srcy)*srcWidth; for (int dstx=0; dstx<dstWidth; dstx++){ int pixelIndex = int(srcIndex + srcx) * bytesPerPixel; for (int k=0; k<bytesPerPixel; k++){ dstPixels[dstIndex] = pixels[pixelIndex]; dstIndex++; pixelIndex++; } srcx+=srcxFactor; } srcy+=srcyFactor; } }break; //---------------------------------------- case OF_INTERPOLATE_BILINEAR: // not implemented yet ofLogError("ofPixels") << "resizeTo(): bilinear resize not implemented, not resizing"; break; //---------------------------------------- case OF_INTERPOLATE_BICUBIC: float px1, py1; float px2, py2; float px3, py3; float srcColor = 0; float interpCol; int patchRow; int patchIndex; float patch[16]; int srcRowBytes = srcWidth*bytesPerPixel; int loIndex = (srcRowBytes)+1; int hiIndex = (srcWidth*srcHeight*bytesPerPixel)-(srcRowBytes)-1; for (int dsty=0; dsty<dstHeight; dsty++){ for (int dstx=0; dstx<dstWidth; dstx++){ int dstIndex0 = (dsty*dstWidth + dstx) * bytesPerPixel; float srcxf = srcWidth * (float)dstx/(float)dstWidth; float srcyf = srcHeight * (float)dsty/(float)dstHeight; int srcx = (int) MIN(srcWidth-1, srcxf); int srcy = (int) MIN(srcHeight-1, srcyf); int srcIndex0 = (srcy*srcWidth + srcx) * bytesPerPixel; px1 = srcxf - srcx; py1 = srcyf - srcy; px2 = px1 * px1; px3 = px2 * px1; py2 = py1 * py1; py3 = py2 * py1; for (int k=0; k<bytesPerPixel; k++){ int dstIndex = dstIndex0+k; int srcIndex = srcIndex0+k; for (int dy=0; dy<4; dy++) { patchRow = srcIndex + ((dy-1)*srcRowBytes); for (int dx=0; dx<4; dx++) { patchIndex = patchRow + (dx-1)*bytesPerPixel; if ((patchIndex >= loIndex) && (patchIndex < hiIndex)) { srcColor = pixels[patchIndex]; } patch[dx*4 + dy] = srcColor; } } interpCol = (PixelType)bicubicInterpolate(patch, px1,py1, px2,py2, px3,py3); dstPixels[dstIndex] = interpCol; } } } break; } return true; }
void ofPixels_<PixelType>::copyFrom(const ofPixels_<PixelType> & mom){ if(mom.isAllocated()) { allocate(mom.getWidth(), mom.getHeight(), mom.getNumChannels()); memcpy(pixels, mom.getPixels(), mom.getWidth() * mom.getHeight() * mom.getBytesPerPixel()); } }
static void saveImage(ofPixels_<PixelType> & pix, string fileName, ofImageQualityType qualityLevel) { ofInitFreeImage(); if (pix.isAllocated() == false){ ofLogError("ofImage") << "saveImage(): couldn't save \"" << fileName << "\", pixels are not allocated"; return; } #ifdef TARGET_LITTLE_ENDIAN if(sizeof(PixelType) == 1 && (pix.getPixelFormat()==OF_PIXELS_RGB || pix.getPixelFormat()==OF_PIXELS_RGBA)) { pix.swapRgb(); } #endif FIBITMAP * bmp = getBmpFromPixels(pix); #ifdef TARGET_LITTLE_ENDIAN if(sizeof(PixelType) == 1 && (pix.getPixelFormat()==OF_PIXELS_BGR || pix.getPixelFormat()==OF_PIXELS_BGRA)) { pix.swapRgb(); } #endif ofFilePath::createEnclosingDirectory(fileName); fileName = ofToDataPath(fileName); FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; fif = FreeImage_GetFileType(fileName.c_str(), 0); if(fif == FIF_UNKNOWN) { // or guess via filename fif = FreeImage_GetFIFFromFilename(fileName.c_str()); } if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) { if(fif == FIF_JPEG) { int quality = JPEG_QUALITYSUPERB; switch(qualityLevel) { case OF_IMAGE_QUALITY_WORST: quality = JPEG_QUALITYBAD; break; case OF_IMAGE_QUALITY_LOW: quality = JPEG_QUALITYAVERAGE; break; case OF_IMAGE_QUALITY_MEDIUM: quality = JPEG_QUALITYNORMAL; break; case OF_IMAGE_QUALITY_HIGH: quality = JPEG_QUALITYGOOD; break; case OF_IMAGE_QUALITY_BEST: quality = JPEG_QUALITYSUPERB; break; } FreeImage_Save(fif, bmp, fileName.c_str(), quality); } else { if(qualityLevel != OF_IMAGE_QUALITY_BEST) { ofLogWarning("ofImage") << "saveImage(): ofImageCompressionType only applies to JPEGs," << " ignoring value for \" "<< fileName << "\""; } if (fif == FIF_GIF) { FIBITMAP* convertedBmp; if(pix.getImageType() == OF_IMAGE_COLOR_ALPHA) { // this just converts the image to grayscale so it can save something convertedBmp = FreeImage_ConvertTo8Bits(bmp); } else { // this will create a 256-color palette from the image convertedBmp = FreeImage_ColorQuantize(bmp, FIQ_NNQUANT); } FreeImage_Save(fif, convertedBmp, fileName.c_str()); if (convertedBmp != nullptr){ FreeImage_Unload(convertedBmp); } } else { FreeImage_Save(fif, bmp, fileName.c_str()); } } } if (bmp != nullptr){ FreeImage_Unload(bmp); } }
void ofPixels_<PixelType>::copyFrom(const ofPixels_<PixelType> & mom){ if(mom.isAllocated()) { allocate(mom.getWidth(), mom.getHeight(), mom.getPixelFormat()); memcpy(pixels, mom.getPixels(), mom.size() * sizeof(PixelType)); } }
static bool saveImage(const ofPixels_<PixelType> & _pix, ofBuffer & buffer, ofImageFormat format, ofImageQualityType qualityLevel) { // thanks to alvaro casinelli for the implementation ofInitFreeImage(); if (_pix.isAllocated() == false){ ofLogError("ofImage","saveImage(): couldn't save to ofBuffer, pixels are not allocated"); return false; } if(format==OF_IMAGE_FORMAT_JPEG && (_pix.getNumChannels()==4 || _pix.getBitsPerChannel() > 8)){ ofPixels pix3 = _pix; pix3.setNumChannels(3); return saveImage(pix3,buffer,format,qualityLevel); } FIBITMAP * bmp = nullptr; #ifdef TARGET_LITTLE_ENDIAN if(sizeof(PixelType) == 1 && (_pix.getPixelFormat()==OF_PIXELS_RGB || _pix.getPixelFormat()==OF_PIXELS_RGBA)) { // Make a local copy. ofPixels_<PixelType> pix = _pix; pix.swapRgb(); bmp = getBmpFromPixels(pix); }else{ #endif bmp = getBmpFromPixels(_pix); #ifdef TARGET_LITTLE_ENDIAN } #endif if (bmp) // bitmap successfully created { bool returnValue; // (b) open a memory stream to compress the image onto mem_buffer: // FIMEMORY *hmem = FreeImage_OpenMemory(); // (c) encode and save the image to the memory (on dib FIBITMAP image): // if(FREE_IMAGE_FORMAT(format) == FIF_JPEG) { int quality = JPEG_QUALITYSUPERB; switch(qualityLevel) { case OF_IMAGE_QUALITY_WORST: quality = JPEG_QUALITYBAD; break; case OF_IMAGE_QUALITY_LOW: quality = JPEG_QUALITYAVERAGE; break; case OF_IMAGE_QUALITY_MEDIUM: quality = JPEG_QUALITYNORMAL; break; case OF_IMAGE_QUALITY_HIGH: quality = JPEG_QUALITYGOOD; break; case OF_IMAGE_QUALITY_BEST: quality = JPEG_QUALITYSUPERB; break; } returnValue = FreeImage_SaveToMemory(FIF_JPEG, bmp, hmem, quality); }else{ returnValue = FreeImage_SaveToMemory((FREE_IMAGE_FORMAT)format, bmp, hmem); } /* NOTE: at this point, hmem contains the entire data in memory stored in fif format. the amount of space used by the memory is equal to file_size: long file_size = FreeImage_TellMemory(hmem); but can also be retrieved by FreeImage_AcquireMemory that retrieves both the length of the buffer, and the buffer memory address. */ #ifdef TARGET_WIN32 DWORD size_in_bytes = 0; #else std::uint32_t size_in_bytes = 0; #endif // Save compressed data on mem_buffer // note: FreeImage_AquireMemory allocates space for aux_mem_buffer): // unsigned char *mem_buffer = nullptr; if (!FreeImage_AcquireMemory(hmem, &mem_buffer, &size_in_bytes)){ ofLogError("ofImage") << "saveImage(): couldn't save to ofBuffer, aquiring compressed image from memory failed"; return false; } /* Now, before closing the memory stream, copy the content of mem_buffer to an auxiliary buffer */ buffer.set((char*)mem_buffer,size_in_bytes); // Finally, close the FIBITMAP object, or we will get a memory leak: FreeImage_Unload(bmp); // Close the memory stream (otherwise we may get a memory leak). FreeImage_CloseMemory(hmem); return returnValue; }else{ return false; } }