///////////////////////////////////////////////////////// // really open the file ! (OS dependent) // ///////////////////////////////////////////////////////// bool imageMAGICK :: load(std::string filename, imageStruct&result, gem::Properties&props) { Magick::Image image; try { ::verbose(2, "reading '%s' with ImageMagick", filename.c_str()); // Read a file into image object try { image.read( filename ); } catch (Magick::Warning e) { verbose(1, "magick loading problem: %s", e.what()); } result.xsize=static_cast<GLint>(image.columns()); result.ysize=static_cast<GLint>(image.rows()); result.setCsizeByFormat(GL_RGBA); result.reallocate(); result.upsidedown=true; try { image.write(0,0,result.xsize,result.ysize, "RGBA", Magick::CharPixel, reinterpret_cast<void*>(result.data)); } catch (Magick::Warning e) { verbose(1, "magick decoding problem: %s", e.what()); } }catch( Magick::Exception e ) { verbose(1, "magick loading image failed with: %s", e.what()); return false; } return true; }
void pix_convolve :: processGrayImage(imageStruct &image) { const int csize=image.csize; image.copy2Image(&tempImg); int initX = m_rows / 2; int initY = m_cols / 2; int maxX = tempImg.xsize - initX; int maxY = tempImg.ysize - initY; int xTimesc = tempImg.xsize * csize; int initOffset = initY * xTimesc + initX * csize; for (int y = initY; y < maxY; y++) { int realY = y * xTimesc; int offsetY = realY - initOffset; for (int x = initX; x < maxX; x++) { int offsetXY = x + offsetY; int new_val = 0; int offsetXYC = offsetXY; for (int matY = 0; matY < m_cols; matY++) { int offsetXYCMat = matY * xTimesc + offsetXYC; int realMatY = matY * m_rows; for (int matX = 0; matX < m_rows; matX++) { new_val += (tempImg.data[offsetXYCMat + matX] * m_imatrix[realMatY + matX])>>8; } } image.data[x+realY] = CLAMP(new_val); //removes insult from injury ?? // we do not use the m_irange anymore ... remove it ?? } } }
void pix_colorreduce :: processGrayImage(imageStruct &image) { tempImage.xsize=image.xsize; tempImage.ysize=image.ysize; tempImage.fromGray(image.data); processRGBAImage(tempImage); image.fromRGBA(tempImage.data); }
///////////////////////////////////////////////////////// // CreateBuffer // ///////////////////////////////////////////////////////// bool refresh_buffer(const imageStruct&reference, imageStruct&buffer) { // only 1 channel !!, to keep data-size handy unsigned char*data = buffer.data; size_t dataSize = reference.xsize * reference.xsize * reference.ysize * reference.csize * sizeof(unsigned char); bool refresh= (reference.xsize != buffer.xsize) || (reference.ysize != buffer.ysize) || (reference.csize != buffer.csize); buffer.xsize = reference.xsize; buffer.ysize = reference.ysize; buffer.setCsizeByFormat(reference.format); if(data!=buffer.reallocate( dataSize ) || refresh) { buffer.setBlack(); } return (0!=buffer.data); }
bool imageTIFF::save(const imageStruct&constimage, const std::string&filename, const std::string&mimetype, const gem::Properties&props) { TIFF *tif = NULL; if(GL_YUV422_GEM==constimage.format) { error("don't know how to write YUV-images with libTIFF"); return false; } tif=TIFFOpen(filename.c_str(), "w"); if (tif == NULL) { return false; } imageStruct image; constimage.copy2Image(&image); image.fixUpDown(); uint32 width=image.xsize, height = image.ysize; short bits=8, samps=image.csize; int npixels = width * height; //int planar_conf = PLANARCONFIG_CONTIG; const char *gemstring = "PD/GEM"; TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width); TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height); TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bits); TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, samps); TIFFSetField(tif, TIFFTAG_PLANARCONFIG, 1); TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); TIFFSetField(tif, TIFFTAG_XRESOLUTION, 72); TIFFSetField(tif, TIFFTAG_YRESOLUTION, 72); TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); TIFFSetField(tif, TIFFTAG_SOFTWARE, gemstring); int yStride = image.xsize * image.csize; unsigned char *srcLine = &(image.data[npixels * image.csize]); srcLine -= yStride; for (uint32 row = 0; row < height; row++) { unsigned char *buf = srcLine; if (TIFFWriteScanline(tif, buf, row, 0) < 0) { error("GEM: could not write line %d to image %s", row, filename.c_str()); TIFFClose(tif); delete [] buf; return(false); } srcLine -= yStride; } TIFFClose(tif); return true; }
void pix_convolve :: processYUVImage(imageStruct &image) { image.copy2Image(&tempImg); //float range = 1; int initX = m_rows / 2; int initY = m_cols / 2; int maxX = tempImg.xsize - initX; int maxY = tempImg.ysize - initY; int xTimesc = tempImg.xsize * tempImg.csize; int initOffset = initY * xTimesc + initX * tempImg.csize; // calculate3x3YUV(image,tempImg); //quick fix for Intel 3x3YUV problems #ifdef __BIG_ENDIAN__ if (m_rows == 3 && m_cols == 3) { calculate3x3YUV(image,tempImg); return; } #endif if (m_chroma) { for (int y = initY; y < maxY; y++) { int realY = y * xTimesc; int offsetY = realY - initOffset; for (int x = initX; x < maxX; x++) { int realPos = x * tempImg.csize + realY; int offsetXY = x * tempImg.csize + offsetY; // skip the UV for (int c = 1; c < 3; c+=2) { int new_val = 0; int offsetXYC = offsetXY + c; for (int matY = 0; matY < m_cols; matY++) { int offsetXYCMat = matY * xTimesc + offsetXYC; int realMatY = matY * m_rows; for (int matX = 0; matX < m_rows; matX++) { new_val += (tempImg.data[offsetXYCMat + matX * tempImg.csize] * m_imatrix[realMatY + matX])>>8; } } image.data[realPos + c] = CLAMP(new_val); // image.data[realPos + c-1] = 128; //remove the U+V } } } } else { for (int y = initY; y < maxY; y++) {
///////////////////////////////////////////////////////// // processImage // ///////////////////////////////////////////////////////// void pix_frei0r :: processRGBAImage(imageStruct &image) { static double time=0; if(!m_plugin)return; m_image.xsize=image.xsize; m_image.ysize=image.ysize; m_image.reallocate(); m_plugin->process(time, image, m_image); time++; image.data = m_image.data; image.notowned = true; image.setCsizeByFormat(m_image.format); }
void GemPixDualObj :: processImage(imageStruct &image) { if (!m_cacheRight || m_cacheRight->m_magic!=GEMCACHE_MAGIC){ m_cacheRight=NULL; return; } //if (!m_cacheRight || !&image || !&m_pixRight || !&m_pixRight->image) return; if (!m_pixRightValid || !&image || !&m_pixRight || !&m_pixRight->image) return; if (image.xsize != m_pixRight->image.xsize || image.ysize != m_pixRight->image.ysize) { error("two images do not have equal dimensions (%dx%d != %dx%d)", image.xsize, image.ysize, m_pixRight->image.xsize, m_pixRight->image.ysize); m_pixRightValid = 0; return; } if(image.upsidedown != m_pixRight->image.upsidedown) { image.fixUpDown(); m_pixRight->image.fixUpDown(); } bool found = false; switch (image.format) { case GL_RGBA: case GL_BGRA_EXT: PROCESS_COLORSPACE(PROCESS_DUALIMAGE_SIMD(RGBA), PROCESS_DUALIMAGE(RGBA, YUV), PROCESS_DUALIMAGE(RGBA, Gray)); break; case GL_LUMINANCE: PROCESS_COLORSPACE(PROCESS_DUALIMAGE(Gray, RGBA), PROCESS_DUALIMAGE(Gray, YUV), PROCESS_DUALIMAGE_SIMD(Gray)); break; case GL_YCBCR_422_GEM: PROCESS_COLORSPACE(PROCESS_DUALIMAGE(YUV, RGBA), PROCESS_DUALIMAGE_SIMD(YUV), PROCESS_DUALIMAGE(YUV, Gray)); break; default: break; } if (!found)processDualImage(image, m_pixRight->image); }
void pix_convolve :: processRGBAImage(imageStruct &image) { image.copy2Image(&tempImg); int initX = m_rows / 2; int initY = m_cols / 2; int maxX = tempImg.xsize - initX; int maxY = tempImg.ysize - initY; int xTimesc = tempImg.xsize * tempImg.csize; int initOffset = initY * xTimesc + initX * tempImg.csize; const int csize = tempImg.csize; if (m_rows == 3 && m_cols == 3) { calculateRGBA3x3(image,tempImg); return; } for (int y = initY; y < maxY; y++) { int realY = y * xTimesc; int offsetY = realY - initOffset; for (int x = initX; x < maxX; x++) { int realPos = x * csize + realY; int offsetXY = x * csize + offsetY; // skip the alpha value for (int c = 1; c < csize; c++) { int new_val = 0; int offsetXYC = offsetXY + c; for (int matY = 0; matY < m_cols; matY++) { int offsetXYCMat = matY * xTimesc + offsetXYC; int realMatY = matY * m_rows; for (int matX = 0; matX < m_rows; matX++) { new_val += (tempImg.data[offsetXYCMat + matX * csize] * m_imatrix[realMatY + matX])>>8; } } image.data[realPos + c] = CLAMP(new_val); //removes insult from injury ?? // we do not use the m_irange anymore ... remove it ?? } } } }
bool imageJPEG::save(const imageStruct&constimage, const std::string&filename, const std::string&mimetype, const gem::Properties&props) { struct jpeg_compress_struct cinfo; /* More stuff */ FILE * outfile=NULL; /* target file */ JSAMPROW row_pointer; /* pointer to JSAMPLE row[s] */ int row_stride; /* physical row width in image buffer */ // We set up the normal JPEG error routines, then override error_exit my_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; // Establish the setjmp return context for my_error_exit to use. if ( setjmp(jerr.setjmp_buffer) ) { // If we get here, the JPEG code has signaled an error. // We need to clean up the JPEG object, close the input file, and return. jpeg_destroy_compress(&cinfo); if(outfile) fclose(outfile); return(false); } double fquality=100; props.get("quality", fquality); int quality=fquality; if(GL_YUV422_GEM==constimage.format) { error("don't know how to write YUV-images with libJPEG"); return false; } /* Now we can initialize the JPEG compression object. */ jpeg_create_compress(&cinfo); if ((outfile = fopen(filename.c_str(), "wb")) == NULL) { error("can't open %s\n", filename.c_str()); return (false); } jpeg_stdio_dest(&cinfo, outfile); imageStruct image; constimage.convertTo(&image, GL_RGB); // image.fixUpDown(); JSAMPLE *image_buffer = image.data; cinfo.image_width = image.xsize; /* image width and height, in pixels */ cinfo.image_height = image.ysize; cinfo.input_components = 3; /* # of color components per pixel */ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); jpeg_start_compress(&cinfo, TRUE); row_stride = image.xsize * image.csize; /* JSAMPLEs per row in image_buffer */ while (cinfo.next_scanline < cinfo.image_height) { /* jpeg_write_scanlines expects an array of pointers to scanlines. * Here the array is only one element long, but you could pass * more than one scanline at a time if that's more convenient. */ int rowindex=cinfo.next_scanline; if(!image.upsidedown) rowindex=(cinfo.image_height-cinfo.next_scanline-1); row_pointer = & image_buffer[rowindex * row_stride]; if(jpeg_write_scanlines(&cinfo, &row_pointer, 1) < 0){ error("GEM: could not write line %d to image %s", cinfo.next_scanline, filename.c_str()); jpeg_finish_compress(&cinfo); fclose(outfile); jpeg_destroy_compress(&cinfo); return(false); } } jpeg_finish_compress(&cinfo); fclose(outfile); jpeg_destroy_compress(&cinfo); return true; }
///////////////////////////////////////////////////////// // really open the file ! (OS dependent) // ///////////////////////////////////////////////////////// bool imageJPEG :: load(std::string filename, imageStruct&result, gem::Properties&props) { // open up the file FILE * infile; ::verbose(2, "reading '%s' with libJPEG", filename.c_str()); if ((infile = fopen(filename.c_str(), "rb")) == NULL) { //verbose(2, "GemImageLoad(JPEG): Unable to open image file: %s", filename.c_str()); return(false); } // create the jpeg structures jpeg_decompress_struct cinfo; my_error_mgr jerr; // We set up the normal JPEG error routines, then override error_exit cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; // Establish the setjmp return context for my_error_exit to use. if ( setjmp(jerr.setjmp_buffer) ) { // If we get here, the JPEG code has signaled an error. // We need to clean up the JPEG object, close the input file, and return. jpeg_destroy_decompress(&cinfo); fclose(infile); return(false); } // create the decompression structure jpeg_create_decompress(&cinfo); // associate the decompress struct with the file jpeg_stdio_src(&cinfo, infile); // read in the file info jpeg_read_header(&cinfo, TRUE); // do we have an RGB image? if (cinfo.jpeg_color_space == JCS_RGB) { result.setCsizeByFormat(GL_RGBA); } else if (cinfo.jpeg_color_space == JCS_GRAYSCALE) { // do we have a gray8 image? result.setCsizeByFormat(GL_LUMINANCE); } else { // something else, so decompress as RGB result.setCsizeByFormat(GL_RGBA); cinfo.out_color_space = JCS_RGB; } // start the decompression jpeg_start_decompress(&cinfo); int xSize = cinfo.output_width; int ySize = cinfo.output_height; int cSize = result.csize; result.upsidedown=true; result.xsize = xSize; result.ysize = ySize; result.reallocate(); // cycle through the scan lines unsigned char *srcLine = new unsigned char[xSize * cSize]; unsigned char *dstLine = result.data; int yStride = xSize * cSize; int lines = ySize; int pixes = xSize; // do RGBA/RGB data if (cSize == 4) { while (lines--) { unsigned char *src = srcLine; unsigned char *dst = dstLine; jpeg_read_scanlines(&cinfo, &src, 1); pixes = xSize; while (pixes--) { dst[chRed] = src[0]; dst[chGreen] = src[1]; dst[chBlue] = src[2]; dst[chAlpha] = 255; dst += 4; src += 3; } dstLine += yStride; } } else { // do grayscale data while (lines--) { unsigned char *src = srcLine; unsigned char *dst = dstLine; jpeg_read_scanlines(&cinfo, &src, 1); pixes = xSize; while (pixes--) { *dst++ = *src++; } dstLine += yStride; } } // finish the decompression jpeg_finish_decompress(&cinfo); // cleanup jpeg_destroy_decompress(&cinfo); fclose(infile); delete [] srcLine; return true; }
///////////////////////////////////////////////////////// // processImage // ///////////////////////////////////////////////////////// void pix_flip :: processRGBAImage(imageStruct &image) { // eventually should do this inline, but in the interest of getting it done... imageStruct tempImg; if (image.data==0)return; image.copy2Image(&tempImg); int ySrcStride = image.xsize * image.csize; int yDstStride = image.xsize * image.csize; int xSrcStride = image.csize; int xDstStride = image.csize; unsigned char *srcLine = tempImg.data; unsigned char *dstLine = image.data; FlipType flip=m_flip; if(!image.upsidedown) { switch(flip) { case(HORIZONTAL) : flip=BOTH;break; case(VERTICAL) : flip=NONE;break; case(BOTH) : flip=HORIZONTAL;break; case(NONE) : flip=VERTICAL ;break; default :break; } } image.upsidedown=true; switch(flip) { case(HORIZONTAL): srcLine = tempImg.data + ySrcStride - xSrcStride; xSrcStride = -xSrcStride; break; case(VERTICAL): srcLine = tempImg.data + ySrcStride * image.ysize - ySrcStride; ySrcStride = -ySrcStride; break; case(BOTH): srcLine = tempImg.data + ySrcStride * image.ysize - xSrcStride; xSrcStride = -xSrcStride; ySrcStride = -ySrcStride; break; default: return; // break; } int ySize = image.ysize; int xHold = image.xsize; while(ySize--) { unsigned char *srcPixels = srcLine; unsigned char *dstPixels = dstLine; int xSize = xHold; while(xSize--) { dstPixels[chRed] = srcPixels[chRed]; dstPixels[chGreen] = srcPixels[chGreen]; dstPixels[chBlue] = srcPixels[chBlue]; dstPixels[chAlpha] = srcPixels[chAlpha]; dstPixels += xDstStride; srcPixels += xSrcStride; } dstLine += yDstStride; srcLine += ySrcStride; } }
///////////////////////////////////////////////////////// // really open the file ! (OS dependent) // ///////////////////////////////////////////////////////// bool imageTIFF :: load(std::string filename, imageStruct&result, gem::Properties&props) { ::logpost(NULL, 6, "reading '%s' with libTIFF", filename.c_str()); TIFF *tif = TIFFOpen(filename.c_str(), "r"); if (tif == NULL) { return(NULL); } uint32 width, height; short bits, samps; TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height); TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bits); TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samps); int npixels = width * height; result.xsize=width; result.ysize=height; result.upsidedown=true; result.type=GL_UNSIGNED_BYTE; //? bool knownFormat = false; // Is it a gray8 image? if (bits == 8 && samps == 1) { result.setCsizeByFormat(GL_LUMINANCE); knownFormat = true; } // Is it an RGB image? else if (bits == 8 && samps == 3) { result.setCsizeByFormat(GL_RGBA); knownFormat = true; } // Is it an RGBA image? else if (bits == 8 && samps == 4) { result.setCsizeByFormat(GL_RGBA); knownFormat = true; } // can we handle the raw data? if (knownFormat) { unsigned char *buf = new unsigned char [TIFFScanlineSize(tif)]; if (buf == NULL) { error("GemImageLoad(TIFF): can't allocate memory for scanline buffer: %s", filename.c_str()); TIFFClose(tif); return(false); } result.reallocate(); unsigned char *dstLine = result.data; int yStride = result.xsize * result.csize; for (uint32 row = 0; row < height; row++) { unsigned char *pixels = dstLine; if (TIFFReadScanline(tif, buf, row, 0) < 0) { error("GemImageLoad(TIFF): bad image data read on line: %d: %s", row, filename.c_str()); TIFFClose(tif); return false; } unsigned char *inp = buf; if (samps == 1) { for (uint32 i = 0; i < width; i++) { *pixels++ = *inp++; // Gray8 } } else if (samps == 3) { for (uint32 i = 0; i < width; i++) { pixels[chRed] = inp[0]; // Red pixels[chGreen] = inp[1]; // Green pixels[chBlue] = inp[2]; // Blue pixels[chAlpha] = 255; // Alpha pixels += 4; inp += 3; } } else { for (uint32 i = 0; i < width; i++) { pixels[chRed] = inp[0]; // Red pixels[chGreen] = inp[1]; // Green pixels[chBlue] = inp[2]; // Blue pixels[chAlpha] = inp[3]; // Alpha pixels += 4; inp += 4; } } dstLine += yStride; } delete [] buf; } // nope, so use the automatic conversion else { char emsg[1024]; TIFFRGBAImage img; if (TIFFRGBAImageBegin(&img, tif, 0, emsg) == 0) { //error("GemImageLoad(TIFF): Error reading in image file: %s : %s", filename, emsg); TIFFClose(tif); return(false); } uint32*raster = reinterpret_cast<uint32*>(_TIFFmalloc(npixels * sizeof(uint32))); if (raster == NULL) { error("GemImageLoad(TIFF): Unable to allocate memory for image: %s", filename.c_str()); TIFFClose(tif); return(false); } if (TIFFRGBAImageGet(&img, raster, width, height) == 0) { //error("GemImageLoad(TIFF): Error getting image data in file: %s, %s", filename, emsg); _TIFFfree(raster); TIFFClose(tif); return(false); } TIFFRGBAImageEnd(&img); result.setCsizeByFormat(GL_RGBA); result.reallocate(); unsigned char *dstLine = result.data; int yStride = result.xsize * result.csize; // transfer everything over int k = 0; for (uint32 i = 0; i < height; i++) { unsigned char *pixels = dstLine; for (uint32 j = 0; j < width; j++) { pixels[chRed] = static_cast<unsigned char>(TIFFGetR(raster[k])); // Red pixels[chGreen] = static_cast<unsigned char>(TIFFGetG(raster[k])); // Green pixels[chBlue] = static_cast<unsigned char>(TIFFGetB(raster[k])); // Blue pixels[chAlpha] = static_cast<unsigned char>(TIFFGetA(raster[k])); // Alpha k++; pixels += 4; } dstLine += yStride; } _TIFFfree(raster); } TIFFClose(tif); return true; }
bool convertTo(imageStruct&img) { img.convertFrom(&image); return true; }
static bool QuickTimeImage2mem(GraphicsImportComponent inImporter, imageStruct&result) { Rect r; if (::GraphicsImportGetNaturalBounds(inImporter, &r)) { return NULL; //get an image size } ::OffsetRect(&r, -r.left, -r.top); if (::GraphicsImportSetBoundsRect(inImporter, &r)) { return NULL; } ImageDescriptionHandle imageDescH = NULL; if (::GraphicsImportGetImageDescription(inImporter, &imageDescH)) { return NULL; } result.xsize = (*imageDescH)->width; result.ysize = (*imageDescH)->height; result.upsidedown = true; OSType pixelformat = 0; /* afaik, there is no 8bit grayscale format.... * and even if it was, k8GrayPixelFormat would not be a define... */ #ifdef k8GrayPixelFormat /* from the docs on "depth": what depth is this data (1-32) or ( 33-40 grayscale ) */ if ((*imageDescH)->depth <= 32) { result.setCsizeByFormat(GL_RGBA_GEM); pixelformat = IMAGEQT_RGBA_PIXELFORMAT; } else { result.setCsizeByFormat(GL_LUMINANCE); pixelformat = k8GrayPixelFormat; } #else result.setCsizeByFormat(GL_RGBA_GEM); pixelformat = IMAGEQT_RGBA_PIXELFORMAT; #endif ::DisposeHandle(reinterpret_cast<Handle>(imageDescH)); imageDescH = NULL; result.reallocate(); verbose(1, "[GEM:imageQT] QuickTimeImage2mem() allocate %d bytes", result.xsize*result.ysize*result.csize); if (result.data == NULL) { verbose(0, "[GEM:imageQT] Can't allocate memory for an image."); return false; } GWorldPtr gw = NULL; OSErr err = QTNewGWorldFromPtr(&gw, /* taken from pix_filmDarwin */ pixelformat, // gives noErr &r, NULL, NULL, 0, // keepLocal, //useDistantHdwrMem, result.data, static_cast<long>(result.xsize * result.csize)); if (err) { verbose(0, "[GEM:imageQT] Can't create QTNewWorld"); } ::GraphicsImportSetGWorld(inImporter, gw, NULL); ::GraphicsImportDraw(inImporter); ::DisposeGWorld(gw); //dispose the offscreen gw = NULL; return true; }
///////////////////////////////////////////////////////// // processImage // ///////////////////////////////////////////////////////// void pix_freeframe :: processImage(imageStruct &image) { unsigned int format=m_image.format; unsigned char*data=image.data; if(m_plugin==NULL)return; // convert the current image into a format that suits the FreeFrame-plugin if(image.format!=format){ switch (image.format){ case GL_RGBA: m_image.fromRGBA(image.data); break; case GL_BGRA_EXT: /* "RGBA" on apple */ m_image.fromBGRA(image.data); break; case GL_LUMINANCE: // greyscale m_image.fromGray(image.data); break; case GL_YUV422_GEM: // YUV m_image.fromYUV422(image.data); break; } m_plugin->processFrame(m_image); data=m_image.data; } else { m_plugin->processFrame(image); data=image.data; } // check whether we have converted our image data if(image.data!=data) // it seems, like we did: convert it back // just copied the code from [pix_rgba] switch(format) { case GL_RGBA: image.fromRGBA(m_image.data); break; case GL_RGB: image.fromRGB(m_image.data); break; case GL_BGR_EXT: image.fromBGR(m_image.data); break; case GL_BGRA_EXT: /* "RGBA" on apple */ image.fromBGRA(m_image.data); break; case GL_LUMINANCE: image.fromGray(m_image.data); break; case GL_YCBCR_422_GEM: // YUV image.fromUYVY(m_image.data); break; default: error("no method for this format !!!"); error("if you know how to convert this format (%X),\n" "please contact the authors of this software", image.format); return; } }
bool imageTIFF::save(const imageStruct&constimage, const std::string&filename, const std::string&mimetype, const gem::Properties&props) { TIFF *tif = NULL; if(GL_YUV422_GEM==constimage.format) { error("don't know how to write YUV-images with libTIFF"); return false; } tif=TIFFOpen(filename.c_str(), "w"); if (tif == NULL) { return false; } imageStruct image; constimage.copy2Image(&image); image.fixUpDown(); uint32 width=image.xsize, height = image.ysize; short bits=8, samps=image.csize; int npixels = width * height; //int planar_conf = PLANARCONFIG_CONTIG; std::string software = "PD/GEM"; std::string artist; std::string hostcomputer; double xresolution = 72., yresolution=72.; short resunit = RESUNIT_INCH; props.get("xresolution", xresolution); props.get("yresolution", yresolution); std::string resunit_s; if(props.get("resolutionunit", resunit_s)) { if(("inch"==resunit_s) || ("english"==resunit_s) || ("imperial"==resunit_s)) resunit=RESUNIT_INCH; else if(("centimeter"==resunit_s) || ("metric"==resunit_s)) resunit=RESUNIT_CENTIMETER; else resunit=RESUNIT_NONE; } props.get("software", software); props.get("artist", artist); props.get("hostcomputer", hostcomputer); TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width); TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height); TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bits); TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, samps); TIFFSetField(tif, TIFFTAG_PLANARCONFIG, 1); TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); TIFFSetField(tif, TIFFTAG_XRESOLUTION, xresolution); // RATIONAL TIFFSetField(tif, TIFFTAG_YRESOLUTION, yresolution); // RATIONAL TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, resunit); if(!software.empty()) TIFFSetField(tif, TIFFTAG_SOFTWARE, software.c_str()); if(!artist.empty()) TIFFSetField(tif, TIFFTAG_ARTIST, artist.c_str()); if(!hostcomputer.empty()) TIFFSetField(tif, TIFFTAG_HOSTCOMPUTER, hostcomputer.c_str()); int yStride = image.xsize * image.csize; unsigned char *srcLine = &(image.data[npixels * image.csize]); srcLine -= yStride; for (uint32 row = 0; row < height; row++) { unsigned char *buf = srcLine; if (TIFFWriteScanline(tif, buf, row, 0) < 0) { error("GEM: could not write line %d to image %s", row, filename.c_str()); TIFFClose(tif); delete [] buf; return(false); } srcLine -= yStride; } TIFFClose(tif); return true; }