Unless you tell your webserver to send headers that turn off caching for images or set a cache timeout, browsers always cache images by default (based on filename).
If you do not allready have the Firefox plugin "Firebug", install it.
After that, go to any page with images, open firebug and click the "net" menu, and after that click "Images", then reload the page. You will see "304 not modified" for all images (unless the image has a changing querystring appended to the filename, such as '?t='.time()), which means Firefox will use a cached image.
However, if your goal is to reduce DB load, and you create your page with a script that actually figures out the filenames first, then present img elements like
<img src="http://example.com/realName.jpg" />
Then you have allready called your DB before Firefox (or any other browser) realizes that a particular image exists in cache, so all you save on your side is the bandwith for loading the image(s).
You could change your script to present img elements like
<img src="http://example.com/image.php?id=1
Firefox will still cache images matching the URI, including the query string, so one image is cached for id=1, another for id=2 etc. In other words, your image.php script will only be called if the browser hasn't allready loaded this image.
The downside of this approach is that you now get 1 DB access per image (since the browser issues one get request per image), instead of 1 DB access per 20 images like you had before.
To keep DB access to a minimum, you should instead cache one static html page per 20 images. That is if an html file doesn't exist for a particular page within the paginated set, one DB access is needed to retrieve the images for that page, then you create the html and save it as a file. The next time this page is requested, the html code exists on file and can be served directly by the script without any DB access.