My goal is stamp an image on a 3D PDF that behaves like a watermark (end-user cannot select, edit, resize, or delete the image).
I tried making an Annotation as shown below, but the image ("ClassificationBlock.png" in Resources) can be resized and deleted on the output PDF. Is that an inherent behavior of "PdfAnnotation" rectangles or is there a property I can define that will keep the image essentially read-only?
using (PdfStamper stamp = new PdfStamper(reader, fs))
.
.
.
Rectangle stampRect2 = null;
System.Drawing.Image imageBTM2 = System.Drawing.Image.FromHbitmap(Properties.Resources.ClassificationBlock.GetHbitmap());
Image stampImage2 = iTextSharp.text.Image.GetInstance(imageBTM2, System.Drawing.Imaging.ImageFormat.Png);
Rectangle location2 = new Rectangle(0, 0, stampImage2.Width, stampImage2.Height);
PdfAnnotation pdfStamp2 = PdfAnnotation.CreateStamp(stamp.Writer, location2, null, "ImageText");
stampImage2.SetAbsolutePosition(0, 0);
PdfAppearance app2 = stamp.GetOverContent(1).CreateAppearance(stampImage2.Width, stampImage2.Height);
app2.AddImage(stampImage2);
pdfStamp2.SetAppearance(PdfName.N, app2);
pdfStamp2.SetPage();
stamp.AddAnnotation(pdfStamp2, 1);
stampRect2 = location2;
stamp.FormFlattening = true;
stamp.Close();
reader.Close();
fs.Close();
I've also tried it by mimicking another user's attempt at watermark text via pdfContentBytes, but I can't get the image to even display on the PDF.
stamp.FormFlattening = false;
iTextSharp.text.Rectangle pageRectangle = reader.GetPageSizeWithRotation(1);
PdfContentByte pdfData = stamp.GetOverContent(1);
pdfData.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 10);
PdfGState graphicsState = new PdfGState();
graphicsState.FillOpacity = 0.5F;
pdfData.SetGState(graphicsState);
pdfData.BeginText();
System.Drawing.Image imageBTM2 = System.Drawing.Image.FromHbitmap(Properties.Resources.TEKLAPDF_InstructionBlock.GetHbitmap());
iTextSharp.text.Image stampImage2 = iTextSharp.text.Image.GetInstance(imageBTM2, System.Drawing.Imaging.ImageFormat.Png);
float width = pageRectangle.Width;
float height = pageRectangle.Height;
stampImage2.ScaleToFit(width, height);
stampImage2.SetAbsolutePosition(width / 2 - stampImage2.Width / 2, height / 2 - stampImage2.Height / 2);
stampImage2.SetAbsolutePosition(50, 50);
stampImage2.Rotation = 0;
pdfData.AddImage(stampImage2);
pdfData.EndText();
Any ideas on how best to accomplish this? This is driving me crazy.
EDIT*****************************
These are the current avenues I've pursued. Any ideas on how to "watermark" the 3D PDF?
//Stamp Image Method (works on 2D PDF and 3D PDF BUT results in EDITABLE stamp)
System.Drawing.Image imageBTM2 = System.Drawing.Image.FromHbitmap(Properties.Resources.ClassificationBlock.GetHbitmap());
Image stampImage2 = iTextSharp.text.Image.GetInstance(imageBTM2, System.Drawing.Imaging.ImageFormat.Png);
Rectangle stampRect2 = null;
Rectangle location2 = new Rectangle(0, 0, stampImage2.Width, stampImage2.Height);
PdfAnnotation pdfStamp2 = PdfAnnotation.CreateStamp(stamp.Writer, location2, null, "ImageText");
stampImage2.SetAbsolutePosition(0, 0);
PdfAppearance app2 = stamp.GetUnderContent(1).CreateAppearance(stampImage2.Width, stampImage2.Height);
app2.AddImage(stampImage2);
pdfStamp2.SetAppearance(PdfName.N, app2);
pdfStamp2.SetPage();
stamp.AddAnnotation(pdfStamp2, 1);
stampRect2 = location2;
//Watermark Layering Method (works only on 2D PDF)
var layers = stamp.GetPdfLayers();
var imgLayer = new PdfLayer("StackoverflowImage", stamp.Writer);
PdfContentByte cb = stamp.GetUnderContent(1);
cb.BeginLayer(imgLayer);
stampImage2.ScalePercent(100f);
stampImage2.SetAbsolutePosition(pageWidth/2, pageHeight/2);
cb.AddImage(stampImage2);
cb.EndLayer();
//Jan's Watermark method (works only on 2D PDF)
PdfContentByte over = stamp.GetOverContent(1);
stampImage2.SetAbsolutePosition(pageWidth / 2, pageHeight / 2);
PdfLayer imgLayer = new PdfLayer("StackoverflowImage", stamp.Writer);
imgLayer.OnPanel = false;
over.BeginLayer(imgLayer);
over.AddImage(stampImage2);
over.EndLayer();
stamp.Close();
reader.Close();
First off: You most likely cannot prevent selection of the image.
Second: I do itext in Java, so you'll probably end up uppercasing first character of method names...
For the remainder or your question you could try to add this image to a layer:
PdfContentByte over = stamp.getOverContent(1)
Image img = ...//code to get your image;
img.setAbsolutePosition(x, y); //at your postion
PdfLayer imgLayer = new PdfLayer("StackoverflowImage", stamper.getWriter());
imgLayer.setOnPanel(false);
over.beginLayer(imgLayer);
over.addImage(img);
over.endLayer();
SOLVED! Using the "Stamp Image Method" as described above, I just needed to change the properties of the stamp itself (changing FLAGS to LOCKED and READ-ONLY). This results in a stamp that is above the 3D PDF layer AND cannot be resized, edited, or deleted. So the code is now:
//Stamp Image Method
System.Drawing.Image imageBTM2 = System.Drawing.Image.FromHbitmap(Properties.Resources.ClassificationBlock.GetHbitmap());
Image stampImage2 = iTextSharp.text.Image.GetInstance(imageBTM2, System.Drawing.Imaging.ImageFormat.Png);
Rectangle stampRect2 = null;
Rectangle location2 = new Rectangle(0, 0, stampImage2.Width, stampImage2.Height);
PdfAnnotation pdfStamp2 = PdfAnnotation.CreateStamp(stamp.Writer, location2, null, "ImageText");
pdfStamp2.Flags = iTextSharp.text.pdf.PdfAnnotation.FLAGS_LOCKED;
pdfStamp2.Flags = iTextSharp.text.pdf.PdfAnnotation.FLAGS_READONLY;
stampImage2.SetAbsolutePosition(0, 0);
PdfAppearance app2 = stamp.GetUnderContent(1).CreateAppearance(stampImage2.Width, stampImage2.Height);
app2.AddImage(stampImage2);
pdfStamp2.SetAppearance(PdfName.N, app2);
pdfStamp2.SetPage();
stamp.AddAnnotation(pdfStamp2, 1);
stampRect2 = location2;
Im using jcrop for the first time. Trying to go through the jcrop tutorial, im getting a black cropped image. This is the demo script from deepliquid with the appropriate yii changes. Here is my crop action that crops and displays the image
public function actionCrop()
{
$image_record = Images::model()->findByPk(Yii::app()->request->getParam('image'));
$imageUrl = '/images/uploads/'.$image_record->id.'/'.$image_record->image;
$model = new Crop;
if(isset($_POST['Crop']))
{
$model->attributes=$_POST['Crop'];
if($model->validate())
{
// form inputs are valid, do something here
$targ_w = $targ_h = 500;
$jpeg_quality = 90;
$src = $this->createAbsoluteUrl($imageUrl);
$img_r = imagecreatefromjpeg($src);
$dst_r = ImageCreateTrueColor( $targ_w, $targ_h );
imagecopyresampled($dst_r,$img_r,0,0,$model->x1,$model->y1,
$targ_w,$targ_h,$model->w,$model->h);
header('Content-type: image/jpeg');
imagejpeg($dst_r, null, $jpeg_quality);
}
}
Here is the situation. In my app I have an overlay layer that is composed of a transparent PNG. I have replaced the hitarea for the png with a 1x1 image using the following code:
[Bindable]
[Embed(source = "/assets/1x1image.png")]
private var onexonebitmapClass:Class;
private function loadCompleteHandler(event:Event):void
{
// Create the bitmap
var onexonebitmap:BitmapData = new onexonebitmapClass().bitmapData;
var bitmap:Bitmap;
bitmap = event.target.content as Bitmap;
bitmap.smoothing = true;
var _hitarea:Sprite = createHitArea(onexonebitmap, 1);
var rect:flash.geom.Rectangle = _box.toFlexRectangle(sprite.width, sprite.height);
var drawnBox:Sprite = new FlexSprite();
bitmap.width = rect.width;
bitmap.height = rect.height;
bitmap.x = -loader.width / 2;
bitmap.y = -loader.height / 2;
bitmap.alpha = _alpha;
_hitarea.alpha = 0;
drawnBox.x = rect.x + rect.width / 2;
drawnBox.y = rect.y + rect.height / 2;
// Add the bitmap as a child to the drawnBox
drawnBox.addChild(bitmap);
// Rotate the object.
drawnBox.rotation = _rotation;
// Add the drawnBox to the sprite
sprite.addChild(drawnBox);
// Set the hitarea to drawnBox
drawnBox.hitArea = _hitarea;
}
private function createHitArea(bitmapData:BitmapData, grainSize:uint = 1):Sprite
{
var _hitarea:Sprite = new Sprite();
_hitarea.graphics.beginFill(0x900000, 1.0);
for (var x:uint = 0; x < bitmapData.width; x += grainSize)
{
for (var y:uint = grainSize; y < bitmapData.height; y += grainSize)
{
if (x <= bitmapData.width && y <= bitmapData.height && bitmapData.getPixel(x, y) != 0)
{
_hitarea.graphics.drawRect(x, y, grainSize, grainSize);
}
}
}
_hitarea.graphics.endFill();
return _hitarea;
}
This is based off the work done here: Creating a hitarea for PNG Image with transparent (alpha) regions in Flex
Using the above code I am able to basically ignore the overlay layer for all mouse events (click, double click, move, etc.) However, I am unable to capture the right click (context menu) event for items that are beneath the overlay.
For instance I have a spell check component that checks the spelling on any textitem and like most other spell checkers if the word is incorrect or not in the dictionary underlines the word in red and if you right click on it would give you a list of suggestions in the contextmenu. This is working great when the text box is not under the overlay, but if the text box is under the overlay I get nothing back.
If anyone can give me some pointers on how to capture the right click event on a textItem that is under a transparent png that would be great.
I'm trying to get some information from pdf-files that i uploaded via move_uploaded_file().
I need thumbnails of each page to do some color analysis. further i need the width and height of each page in an actual unit of distance (not pixel).
is there a way to do the conversion from pdf to image in imagick not imagemagick. just because I'm using the imagick instace for the color analysis.
now this works for a single image file but not for a multipage pdf.
what to do know...?
/* Read the image */
$im = new Imagick($file);
/* Thumbnail the image */
$im->thumbnailImage(null, 200);
/* Overwrite it */
file_put_contents($file, $im);
/* Gather Info */
$width = $im->getImageWidth();
$height = $im->getImageHeight();
$ratio = $width / $height;
/* Calculate gray */
$pixel_count = 0;
$sum_gray = 0;
for ($row=0;$row<$height;$row++) {
for ($col=0;$col<$width;$col++) {
$pixel = $im->getImagePixelColor($col, $row);
$rgb = $pixel->getColor();
$this_gray = .299*$rgb['r'] + .587*$rgb['g'] + .114*$rgb['b'];
$sum_gray += $this_gray;
$pixel_count++;
}
}
$gray = (1-($sum_gray / $pixel_count) / 256)*100;
and if anybody knows how to get the height and width information, plaes let me know.
thanks for the help!
How do I add a drop shadow (with defined distance, size etc) using Photoshop scripting?
Current JS Code
var fontSize = 14;
var fontName = "Arial-Bold"; // NB: must be postscript name of font!
// This is the colour of the text in RGB
//Click foreground colour in Photoshop, choose your colour and read off the RGB values
//these can then be entered below.
var textColor = new SolidColor();
textColor.rgb.red = 255;
textColor.rgb.green =255;
textColor.rgb.blue = 255;
var newTextLayer = doc.artLayers.add();
newTextLayer.kind = LayerKind.TEXT;
newTextLayer.textItem.size = fontSize;
newTextLayer.textItem.font = fontName;
newTextLayer.textItem.contents = ++Count;
newTextLayer.textItem.color = textColor;
newTextLayer.textItem.kind = TextType.PARAGRAPHTEXT;
newTextLayer.textItem.height = fontSize;
newTextLayer.textItem.width = doc.width -20;
//The line below is the text position (X Y) IE; 10 Pixels Right 10 Pixels Down
newTextLayer.textItem.position = Array(10, 12);
// Can be RIGHTJUSTFIED LEFTJUSTIFIED CENTERJUSTIFIED
newTextLayer.textItem.justification=Justification.CENTERJUSTIFIED;
I believe there is no API function for this.
The best you can do is to use Scriptlistner.
The code that it generates then can be used in your script.
Here are some similar discussion with Scriptlistner-generated code:
http://ps-scripts.com/bb/viewtopic.php?t=586
or
http://ps-scripts.com/bb/viewtopic.php?t=2207