void Composite(Magick::Image& canv_img, const Magick::Image& obj_img, FrameThemeObj& fto) { Magick::Image img; Rect mdPlc = fto.Placement(); Point sz = mdPlc.Size(); ZoomImage(img, obj_img, sz.x, sz.y); // сначала скопируем маску в изображение, // которое накладываем, используя опять же composite(CopyOpacityCompositeOp) // 1 включаем прозрачность img.matte(true); // 2 копируем прозрачность с рамки img.composite(VFrameImg(fto), 0, 0, MagickLib::CopyOpacityCompositeOp); // 3 накладываем результат c альфа-блэндингом (OverCompositeOp) canv_img.composite(FrameImg(fto), mdPlc.lft, mdPlc.top, MagickLib::OverCompositeOp); canv_img.composite(img, mdPlc.lft, mdPlc.top, MagickLib::OverCompositeOp); }
void AdjustLuminance::onInput(InputImageInfo info, Magick::Image img) { std::vector<std::pair < Magick::Color, size_t>> histogram; Magick::colorHistogram(&histogram, img); Magick::Image original = img; /* gamma correction rules: * http://www.imagemagick.org/Usage/transform/#evaluate_pow * * updatedColor = color ^ (1 / gamma) * gamma = 1 / log(color, updatedColor) * gamma = 1 / (log(updatedColor) / log(color)) * * We can't compute gamma just from current and target luminance, * but we can estimate it. * * We can compute expected luminance after gamma * correction from image histogram, it is relatively fast. * So we iterate gamma estimation ten times. Results are relatively good. */ double gamma = 1.0; double targetLuminance = info.luminanceChange + info.luminance; double expectedLuminance = info.luminance; for (int iteration = 0; iteration < 10; iteration++) { gamma *= 1 / ( std::log(Magick::Color::scaleQuantumToDouble(targetLuminance)) / std::log(Magick::Color::scaleQuantumToDouble(expectedLuminance))); expectedLuminance = ComputeLuminance::computeLuminance(histogram, gamma); *verboseOutput << QString("%1 iteration %2 changing gamma to %3 (expected luminance: %4, target %5, abs(diff) %6)") .arg(info.file.filePath()) .arg(iteration) .arg(gamma) .arg(expectedLuminance) .arg(targetLuminance) .arg(std::abs(expectedLuminance - targetLuminance)) << endl; } img.gamma(gamma); if (debugView) { original.transform( Magick::Geometry(original.columns(), original.rows()), Magick::Geometry(original.columns() / 2, original.rows()) ); img.composite(original, 0, 0, Magick::DissolveCompositeOp); } //img.brightnessContrast(brighnessChange, /* contrast */0.0); emit input(info, img); }
// returns a masked version of given image where every pixel // above / below a given value ( in quantum range ) gets transparent Magick::Image masked( bool below, double value, Magick::Image img ) { Magick::Image mask = img; mask.type( Magick::GrayscaleMatteType ); mask.normalize(); double v = below ? value : 1-value; mask.threshold( v*MaxRGB ); if( below ) mask.negate(); mask.type( Magick::TrueColorMatteType ); mask.transparent( "black" ); Magick::Image masked = img; masked.composite( mask, Magick::CenterGravity, Magick::CopyOpacityCompositeOp ); return masked; }
/** layerToImage * * Converts a layer into an ImageMagick Image */ int HandlerUtils::LayerToImage(const Map& map, const Layer& layer, std::vector<Magick::Image>& tiles, Magick::Image& image) { for (unsigned int i = 0; i < map.GetHeight(); i++) { for (unsigned int j = 0; j < map.GetWidth(); j++) { int index = i * map.GetWidth() + j; int tile = layer[index]; if (tile == -1) continue; image.composite(tiles[tile], j * map.GetTileWidth(), i * map.GetTileHeight(), Magick::AtopCompositeOp); } } return 0; }
void operator()(Magick::Image& img) const { Magick::Image old = img; img = Magick::Image(old.size(), "black"); img.composite(old, 0, 0, Magick::OverCompositeOp); img.composite(old, 0, 0, Magick::CopyOpacityCompositeOp); }
int main (int argc, char *argv[]) { MSG_db1_data db1; char *format; char *image_overlay = 0; float gfactor; if (argc > 1) { if (!strcmp(argv[1], "-V")) { std::cout << argv[0] << " " << PACKAGE_STRING << std::endl; return 0; } } if (argc < 5) { std::cerr << "Usage: " << argv[0] << " directory channel format" << " scale [overlay image]" << std::endl; std::cerr << "Example: " << argv[0] << " dati IR_120 gif 0.1 SEVIRI_OVERLAY.pgm" << std::endl; return -1; } format = strdup(argv[3]); gfactor = atof(argv[4]); if (argc > 5) image_overlay = strdup(argv[5]); db1.open(argv[1]); if (! db1.has_channel(argv[2])) { std::cerr << "Exit: this channel is not present." << std::endl; return -1; } db1.set_channel(argv[2]); if (! db1.is_data_ok( )) { std::cerr << "Exit: Data Open Error." << std::endl; return -1; } char outname[PATH_MAX]; snprintf(outname, PATH_MAX, "%s_%s_%s.%s", db1.get_INFO_satellite_name( ), db1.get_channel_INFO_name( ), db1.get_INFO_schedule_start( ), format); for (int i = 0; i < (int) strlen(outname); i ++) { if (outname[i] == '/') outname[i] = '-'; if (outname[i] == ' ') outname[i] = '_'; if (outname[i] == ':') outname[i] = '-'; } Magick::Image *image = new Magick::Image(db1.get_INFO_image_pixels( ), db1.get_INFO_image_lines( ), "I", Magick::ShortPixel, db1.get_RAW_data( )); image->normalize( ); if (! db1.get_INFO_schedule_northsouth( )) image->rotate(180.0); if (image_overlay) { Magick::Image overlay; overlay.read("SEVIRI_OVERLAY.pgm"); image->composite(overlay, 0, 0, Magick::PlusCompositeOp); } Magick::Geometry geom((int) ((float) db1.get_INFO_image_pixels( )*gfactor), (int) ((float) db1.get_INFO_image_lines( )*gfactor)); image->scale(geom); image->write(outname); db1.close( ); return 0; }
int main(int argc, char *argv[ ]) { char *directory = NULL; char *overlay_image = NULL; char *resolution = NULL; char *productid1 = NULL; char *productid2 = NULL; char *timing = NULL; char *format = NULL; char *pname = strdup(argv[0]); float geometry = 1.0; bool normalize = false; bool do_overlay = false; while (1) { int option_index = 0; int c; static struct option long_options[] = { {"directory", 1, 0, 'd'}, {"resolution", 1, 0, 'r'}, {"productid1", 1, 0, 's'}, {"productid2", 1, 0, 'c'}, {"outformat", 1, 0, 'f'}, {"outscale", 1, 0, 'g'}, {"overlay", 1, 0, 'o'}, {"time", 1, 0, 't'}, {"normalize", 0, 0, 'n'}, {"version", 0, 0, 'V'}, {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "d:r:s:c:f:g:o:t:nVh?", long_options, &option_index); if (c == -1) break; switch (c) { case 'd': directory = strdup(optarg); break; case 'r': resolution = strdup(optarg); break; case 's': productid1 = strdup(optarg); break; case 'c': productid2 = strdup(optarg); break; case 'f': format = strdup(optarg); break; case 'g': geometry = strtod(optarg, (char **)NULL); break; case 'o': do_overlay = true; overlay_image = strdup(optarg); break; case 't': timing = strdup(optarg); break; case 'n': normalize = true; break; case 'V': std::cout << pname << " " << PACKAGE_STRING << std::endl; return 0; case '?': case 'h': usage(pname); return(0); break; default: std::cerr << "?? getopt returned character code" << std::oct << c << "??" << std::endl; usage(pname); return(1); } } if (resolution == NULL || productid1 == NULL || productid2 == NULL || timing == NULL) { usage(pname); return(1); } std::string filename; if (directory) filename = directory; else filename = "."; filename = filename + PATH_SEPARATOR + resolution; filename = filename + "-\?\?\?-\?\?\?\?\?\?-"; filename = filename + underscoreit(productid1, 12) + "-"; filename = filename + underscoreit(productid2, 9) + "-"; filename = filename + "0\?\?\?\?\?___" + "-"; filename = filename + timing + "-" + "\?_"; glob_t globbuf; globbuf.gl_offs = 1; if ((glob(filename.c_str( ), GLOB_DOOFFS, NULL, &globbuf)) != 0) { std::cerr << "No such file(s)." << std::endl; return 1; } int nsegments = globbuf.gl_pathc; MSG_header *header; MSG_data *msgdat; header = new MSG_header[nsegments]; msgdat = new MSG_data[nsegments]; for (int i = 0; i < nsegments; i ++) { std::ifstream hrit(globbuf.gl_pathv[i+1], (std::ios::binary | std::ios::in)); if (hrit.fail()) { std::cerr << "Cannot open input hrit file " << globbuf.gl_pathv[i+1] << std::endl; return 1; } header[i].read_from(hrit); msgdat[i].read_from(hrit, header[i]); hrit.close( ); std::cout << header[i]; } globfree(&globbuf); if (header[0].segment_id->data_field_format == MSG_NO_FORMAT) { std::cout << "Product dumped in binary format." << std::endl; return 0; } int totalsegs = header[0].segment_id->planned_end_segment_sequence_number; int *segsindexes = new int[totalsegs]; for (int i = 0; i < totalsegs; i ++) segsindexes[i] = -1; for (int i = 0; i < nsegments; i ++) segsindexes[header[i].segment_id->sequence_number-1] = i; filename = resolution; filename = filename + "-" + productid1 + "-" + productid2 + "-" + timing; if (format) filename = filename + "." + format; else filename = filename + ".jpg"; int npix = header[0].image_structure->number_of_columns; int nlin = header[0].image_structure->number_of_lines; size_t npixperseg = npix*nlin; size_t total_size = totalsegs*npixperseg; MSG_SAMPLE *pixels = new MSG_SAMPLE[total_size]; memset(pixels, 0, total_size*sizeof(MSG_SAMPLE)); size_t pos = 0; for (int i = 0; i < totalsegs; i ++) { if (segsindexes[i] >= 0) memcpy(pixels+pos, msgdat[segsindexes[i]].image->data, npixperseg*sizeof(MSG_SAMPLE)); pos += npixperseg; } Magick::Image *image = new Magick::Image(npix, nlin*totalsegs, "I", Magick::ShortPixel, pixels); if (normalize) image->normalize( ); image->rotate(180.0); if (header[0].segment_id->spectral_channel_id < 12) { if (do_overlay) { Magick::Image overlay; overlay.read(overlay_image); image->composite(overlay, 0, 0, Magick::PlusCompositeOp); } } if (geometry < 1.0) { Magick::Geometry geom((int) ((float) npix*geometry), (int) ((float) nlin*totalsegs*geometry)); image->scale(geom); } image->write(filename); delete image; delete [ ] pixels; delete [ ] header; delete [ ] msgdat; delete [ ] segsindexes; return 0; }