/** * Composites a watermark (the date strings of the image) onto the lower * left corner and the HV logo in the lower right corner. * * Layer names are added together as one string, and date strings are * added as a separate string, to line them up nicely. An example string * would be: * * -annotate +20+0 'EIT 304\nLASCO C2\n' * and: * -annotate +100+0 '2003-01-01 12:00\n2003-01-01 11:30\n' * * These two strings are then layered on top of each other and put in the * southwest corner of the image. * * @param object $imagickImage An Imagick object * * @return void */ private function _addWatermark($imagickImage) { if ($this->width < 200 || $this->height < 200) { return; } $watermark = new IMagick(HV_ROOT_DIR . '/resources/images/' . 'watermark_small_black_border.png'); // If the image is too small, use only the circle, not the url, and // scale it so it fits the image. if ($this->width / 300 < 2) { $watermark->readImage(HV_ROOT_DIR . '/resources/images/' . 'watermark_circle_small_black_border.png'); $scale = $this->width / 2 / 300; $width = $watermark->getImageWidth(); $watermark->scaleImage($width * $scale, $width * $scale); } // For whatever reason, compositeImage() doesn't carry over gravity // settings so the offsets must be relative to the top left corner of // the image rather than the desired gravity. $x = $this->width - $watermark->getImageWidth() - 10; $y = $this->height - $watermark->getImageHeight() - 10; $imagickImage->compositeImage($watermark, IMagick::COMPOSITE_DISSOLVE, $x, $y); // If the image is too small, text won't fit. Don't put a date string // on it. if ($this->width > 285) { $this->_addTimestampWatermark($imagickImage); } // Cleanup $watermark->destroy(); }
/** * Generates a portion of an ImageMagick convert command to apply an alpha mask * * Note: More accurate values for radii used to generate the LASCO C2 & C3 alpha masks: * rocc_outer = 7.7; // (.9625 * orig) * rocc_inner = 2.415; // (1.05 * orig) * * LASCO C2 Image Scale * $lascoC2Scale = 11.9; * * Solar radius in arcseconds, source: Djafer, Thuillier and Sofia (2008) * $rsunArcSeconds = 959.705; * $rsun = $rsunArcSeconds / $lascoC2Scale; * = 80.647 // Previously, used hard-coded value of 80.814221 * * Generating the alpha masks: * $rocc_inner = 2.415; * $rocc_outer = 7.7; * * // convert to pixels * $radius_inner = $rocc_inner * $rsun; * $radius_outer = $rocc_outer * $rsun; * $innerCircleY = $crpix2 + $radius_inner; * $outerCircleY = $crpix2 + $radius_outer; * * exec("convert -size 1024x1024 xc:black -fill white -draw \"circle $crpix1,$crpix2 $crpix1,$outerCircleY\" * -fill black -draw \"circle $crpix1,$crpix2 $crpix1,$innerCircleY\" +antialias LASCO_C2_Mask.png") * * Masks have been pregenerated and stored in order to improve performance. * * Note on offsets: * * The original CRPIX1 and CRPIX2 values used to determine the location of the center of the sun in the image * are specified with respect to a bottom-left corner origin. The values passed in to this method from the tile * request, however, specify the offset with respect to a top-left corner origin. This simply makes things * a bit easier since ImageMagick also treats images as having a top-left corner origin. * * Region of interest: * * The region of interest (ROI) below is specified at the original JP2 image scale. * * @param object $imagickImage an initialized Imagick object * * @return void */ protected function setAlphaChannel(&$imagickImage) { $maskWidth = 1040; $maskHeight = 1040; $mask = HV_ROOT_DIR . '/resources/images/alpha-masks/LASCO_' . $this->uiLabels[2]['name'] . '_Mask.png'; if ($this->reduce > 0) { $maskScaleFactor = 1 / pow(2, $this->reduce); } else { $maskScaleFactor = 1; } $maskTopLeftX = ($this->imageSubRegion['left'] + ($maskWidth - $this->jp2->getWidth()) / 2 - $this->offsetX) * $maskScaleFactor; $maskTopLeftY = ($this->imageSubRegion['top'] + ($maskHeight - $this->jp2->getHeight()) / 2 - $this->offsetY) * $maskScaleFactor; $width = $this->subfieldWidth * $maskScaleFactor; $height = $this->subfieldHeight * $maskScaleFactor; // $maskTopLeft coordinates cannot be negative when cropping, so if they are, adjust the width and height // by the negative offset and crop with zero offsets. Then put the image on the properly-sized image // and offset it correctly. $cropWidth = round($width + min($maskTopLeftX, 0)); $cropHeight = round($height + min($maskTopLeftY, 0)); $mask = new IMagick($mask); // Imagick floors pixel values but they need to be rounded up or down. // Rounding cannot be done in the previous lines of code because some addition needs to take place first. $maskTopLeftX = round($maskTopLeftX); $maskTopLeftY = round($maskTopLeftY); $width = round($width); $height = round($height); $mask->scaleImage($maskWidth * $maskScaleFactor, $maskHeight * $maskScaleFactor); $mask->cropImage($cropWidth, $cropHeight, max($maskTopLeftX, 0), max($maskTopLeftY, 0)); $mask->resetImagePage($width . 'x' . $height . '+0+0'); $mask->setImageBackgroundColor('black'); $mask->extentImage($width, $height, $width - $cropWidth, $height - $cropHeight); $imagickImage->setImageExtent($width, $height); $imagickImage->compositeImage($mask, IMagick::COMPOSITE_COPYOPACITY, 0, 0); if ($this->options['opacity'] < 100) { $mask->negateImage(true); $imagickImage->setImageClipMask($mask); $imagickImage->setImageOpacity($this->options['opacity'] / 100); } $mask->destroy(); }