Asked  1 Year ago    Answers:  5   Viewed   14 times

I am looking for a way to add a drop shadow to an image using PHP. Before you answer or vote to close: I am not looking to do this using CSS or HTML. I want to generate an image file. This is not a duplicate of this question nor this one.

I am looking for a very specific effect. For example, given this input image:

I want to produce the following image:


TL;DR: This image above was generated using Photoshop's Drop Shadow effect. I want a look very similar to that. For reference, here's the settings our design team used. Ideally, I'd have similar control in my code for angle, distance, opacity, etc:

I have full access to our debian-linus-based servers, so any GD or ImageMagick solution will work. As will any FOSS linux software solution, although I'd prefer a way to do it with IM or GD as those are already installed and don't require new software to be installed.

The shadow must be able to be placed on a transparent, non-rectangular PNG!

I'm asking the question mainly because the scripts and solutions I have found on the web either only produce rectangular shadows, look like total poo, or just plain don't work at all.

 Answers

1

You're not going to be able to do this in PHP without building in a full edge-detector algorithm and significant processing overhead. Look into using GIMP with some script-fu, and let it do the hard work for you.

Thursday, April 1, 2021
 
Nil
 
Nil
3

Check permissions on the .dll file to make sure the Apache user has read access to the file. Better change the permission of the [PHP]/extension directory.

To change the permission

  1. Right click the file(s) or folder(s)
  2. Select "Properties"
  3. Select "Security" tab
  4. Click on "Edit" button.

Change the permission of user to Full Control.

Thursday, April 1, 2021
 
Oshrib
 
4

Instead of move_uploaded_file(), you'd load the file into the image processing library, resize it, and save it out.

eg. using GD, start with imagecreatefromgif(), imagecreatefromjpeg() or imagecreatefrompng() (depending on what format you've got), then create a new image of the desired thumbnail size using imagecreatetruecolor() and resize the original image into it using imagecopyresampled(). Finally save the results using imagegif()/imagejpeg()/imagepng() depending on what format you want.

Determining the target size is pretty easy if you just want a fixed width whilst retaining the aspect ratio: new_height= round_to_whole_pixels(new_width*original_height/original_width). However it is worth putting some sanity checks in: say someone uploads a 1x2000 pixel image. Aiming for a width of (say) 200 pixels, you'd then be blowing it up to 200x400000, an enormous image that might eat all your server's memory! So have a max_height as well.

Finally, your script as it stands contains too many severe security holes to list. Before you put anything like that on the public internet you need to learn about directory traversal attacks, SQL injection, HTML injection (XSS) and file upload type sniffing vulnerabilities (eg. embedding JavaScript in HTML disguised as an image file).

ETA:

Do you think this web site covers most bases?

Not quite, but it's a start. This advice:

When you place any uploaded files in your upload folder, rename the file to some random names and track the filename in the database.

is very important. You can never trust a filename submitted by the user. Filenames are more complicated than you think, and even if they're not trying to be malicious, there are many weird ways filenames can go wrong:

  • some browsers submit file leafnames, some whole paths, and you don't know the format of filepaths on the client machine (directory separators on various platforms include ‘/’, ‘’, ‘:’, ‘.’ and probably others).

  • what's going to happen if the given filenames contain disallowed characters? Control characters? Unicode characters?

  • if you're on a Windows server, try to create files with innocuous-looking but reserved names like ‘com’ and you'll come a cropper. Also Windows silently throws away trailing spaces and dots in a way that can easily confuse your scripts.

The latter is a potential security hole in the script you linked. It checks for ‘bad’ file extensions like ‘.php’ at the end of the filename. But if you uploaded a file called ‘x.php ’ (with a space) to a Windows server it would happily accept it and save it as ‘x.php’. (There is also a bug in the script, as it uses ‘.’ in a regular expression, which stands for any character. So the filename ‘poo.potatophp’ would be taken as having a .php extension.)

As usual, whitelisting is better than blacklisting. Allowing only eg. ‘.jpeg’ extensions is more likely to work than disallowing known-bad ones. However, this is still insufficient, because there is no guarantee a submitted JPEG file will actually have the extension ‘.jpeg’. On Windows it might have an extension ‘.jpg’ or ‘.pjpeg’ or something else completely that happens to be mapped to JPEG on the client machine. On Mac or Linux it might have no filename extension at all!

So to sum up: it is best to ignore any filename/path submitted with file upload fields. Maybe you can have a look at it to guess what format the file might be in if you don't already know, but you can't rely on that and you should never ever take the user's word for it and actually save it under that name.

The page also does not cover the ‘HTML disguised as an image file’ case I mentioned. If you allow anyone to upload files that you don't completely trust with full access to everything on your site, you need to worry about this. You can read about it here. See more discussion of PHP file upload script risks here.

ETA2:

I have seen a lot of suggestions of uploading above the web directory. Yet my script will still display these files to the visitors of the web site.

Yeah, that's a good place to start. By taking control of the serving process into your own hands you avoid any problems with the webserver handling filetypes in unexpected ways, you can use your own known-safe filenames, and by having your script add a “Content-Disposition: attachment” header, you can mostly prevent browsers from treating active content like JavaScript as originating from your site's security context, causing cross-site scripting problems.

The drawback of this method is that serving a file through PHP is much, much slower than letting the web server do it. You can improve matters by implementing a load of HTTP cacheing header stuff in your file serving script, but it's a lot of work and it still won't be anywhere near as fast as a typical webserver written in C and maybe using kernel-level network efficiency hacks. For a file you serve up occasionally, that's no problem. For a popular image being viewed all the time on a busy site, it's no good at all.

Also, there used to be some issues where Flash would ignore the Content-Disposition header, which could still cause sneaky files to XSS via that plugin. These are fixed now, but who knows what other plugins and odd browser behaviours might be out there. So for safety, it may be best to serve your untrusted user-uploaded files from a different hostname, eg. a subdomain like data.example.com. This stops cookies and authentication details leaking across the two security contexts. If you go for a webserver-based way of spitting out files, you definitely need to take this precaution.

I just want to get this done, its way too complicated

Yeah, it looks like a deceptively simple task, but it's really not. Some very high-profile web sites have suffered with security problems due to untrusted uploads; if Microsoft and Google's web guys can't always get it right, it probably is quite complicated...

It doesn't help that (as usual for PHP) 99% of the tutorials out there covering this sort of thing are utter crap.

Saturday, May 29, 2021
 
Juicy
 
2

I found great tutorial on Android Image Processing here.

public static Bitmap mark(Bitmap src, String watermark, Point location, Color color, int alpha, int size, boolean underline) {
    int w = src.getWidth();
    int h = src.getHeight();
    Bitmap result = Bitmap.createBitmap(w, h, src.getConfig());

    Canvas canvas = new Canvas(result);
    canvas.drawBitmap(src, 0, 0, null);

    Paint paint = new Paint();
    paint.setColor(color);
    paint.setAlpha(alpha);
    paint.setTextSize(size);
    paint.setAntiAlias(true);
    paint.setUnderlineText(underline);
    canvas.drawText(watermark, location.x, location.y, paint);

    return result;
}

Thanks to Pete Houston who shares such useful tutorial on basic image processing.

Monday, June 21, 2021
 
nika
 
1

iFrames just take a url - and parameters can be embedded in urls just fine.

The problem, if I understand the question clearly, is that you're mixing up your quotes:

 echo "<iframe src='sitename.com.au/directory/app/pagename.cfm?memberid='$val'
        width='100%' scrolling='vertical'></iframe>";

will be outputted as

 <iframe src='sitename.com.au/directory/app/pagename.cfm?memberid=' 21254545' 
  width='100%' scrolling='vertical'></iframe>

where 21254545 is an attribute of the iframe instead of part of the url.

Assuming that you don't actually need the quotes in the url, change the echo line to:

echo "<iframe src='sitename.com.au/directory/app/pagename.cfm?memberid=$val' width='100%' scrolling='vertical'></iframe>";

And it should work.

Monday, August 23, 2021
 
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :