Rotate image by 180 degrees (libtiff code)
Fastish inplace rotation of an image by 180 degrees:
void rotate180() {
size_t h;
if((m_height%2) == 1) {
h = (m_height/2)-1;
size_t ymid = ((m_height-1)/2);
for(size_t x=0;x<(m_width/2);x++) {
swap_pixel(x,ymid,(m_width-x-1),ymid);
}
} else h = (m_height/2)-1;
for(size_t x=0;x<m_width;x++) {
for(size_t y=0;y<=h;y++) {
swap_pixel(x,y,m_width-x-1,m_height-y-1);
}
}
}
You need to provide image get and set, and swap_pixel. Complete example below:
#include "tiffio.h"
#include <iostream>
#include <math.h>
#include <vector>
#include <map>
#include <sys/stat.h>
#include <sys/types.h>
#include <sstream>
#include <stdexcept>
#define TIFFSetR(pixel, x) ((unsigned char *)pixel)[0] = x
#define TIFFSetG(pixel, x) ((unsigned char *)pixel)[1] = x
#define TIFFSetB(pixel, x) ((unsigned char *)pixel)[2] = x
#define TIFFSetA(pixel, x) ((unsigned char *)pixel)[3] = x
class BadConversion : public std::runtime_error {
public:
BadConversion(const std::string& s)
: std::runtime_error(s) {}
};
template<class _type>
inline std::string stringify(_type x)
{
std::ostringstream o;
if (!(o << std::fixed << x))
throw BadConversion("stringify()");
return o.str();
}
using namespace std;
class Image {
public:
Image() {
}
enum fragment_type { frag_type_arrow, frag_type_rectange } ;
void load_tiff(string input_filename) {
m_image_data.clear();
TIFF* tif = TIFFOpen(input_filename.c_str(), "r");
if (tif) {
uint32 w, h;
size_t npixels;
uint32* raster;
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
npixels = w * h;
m_width = w;
m_height = h;
raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
if (raster != NULL) {
if (TIFFReadRGBAImageOriented(tif, w, h, raster,ORIENTATION_TOPLEFT, 0)) {
for(size_t n=0;n<npixels;n++) m_image_data.push_back(raster[n]);
}
_TIFFfree(raster);
}
TIFFClose(tif);
}
}
void save_tiff_rgb(string output_filename) {
TIFF *output_image;
// Open the TIFF file
if((output_image = TIFFOpen(output_filename.c_str(), "w")) == NULL){
cerr << "Unable to write tif file: " << output_filename << endl;
}
// We need to set some values for basic tags before we can add any data
TIFFSetField(output_image, TIFFTAG_IMAGEWIDTH, m_width);
TIFFSetField(output_image, TIFFTAG_IMAGELENGTH, m_height);
TIFFSetField(output_image, TIFFTAG_BITSPERSAMPLE, 8);
TIFFSetField(output_image, TIFFTAG_SAMPLESPERPIXEL, 4);
TIFFSetField(output_image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(output_image, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
TIFFSetField(output_image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
// Write the information to the file
TIFFWriteEncodedStrip(output_image, 0, &m_image_data[0], m_width*m_height * 4);
// Close the file
TIFFClose(output_image);
}
bool is_on_image(size_t x,size_t y) {
if((x < m_width) && (y < m_height)) return true;
return false;
}
uint32_t get(size_t x,size_t y) {
return m_image_data[(y*m_width)+x];
}
void set(size_t x,size_t y,uint32_t value) {
m_image_data[(y*m_width)+x] = value;
}
void swap_pixel(size_t x1,size_t y1,
size_t x2,size_t y2) {
uint32_t t = get(x1,y1);
set(x1,y1,get(x2,y2));
set(x2,y2,t);
}
// Inplace 180 degree rotation.
void rotate180() {
size_t h;
if((m_height%2) == 1) {
h = (m_height/2)-1;
size_t ymid = ((m_height-1)/2);
for(size_t x=0;x<(m_width/2);x++) {
swap_pixel(x,ymid,(m_width-x-1),ymid);
}
} else h = (m_height/2)-1;
for(size_t x=0;x<m_width;x++) {
for(size_t y=0;y<=h;y++) {
swap_pixel(x,y,m_width-x-1,m_height-y-1);
}
}
}
vector<uint32_t> m_image_data;
size_t m_width;
size_t m_height;
};
int main(int argc, char* argv[]) {
Image i;
i.load_tiff(argv[1]);
i.rotate180();
i.save_tiff_rgb(string(argv[2]));
}