Conclusion
The current solution that @tanzeeb came up with is working great for a majority of Image/PDF files and the manipulate function is a useful and dynamic way to manipulate the entire pdf, but it is too broad to be considered a viable method when generating thumbnails, whose main goal is to manipulate only the first page of a pdf.
Why?
This manipulate!
code forces the entire file to be read before continuing, and also iterates over that entire file a little later. That's counterintuitive to generating thumbnails and can be a resource problem.
Other Solutions
Inside of manipulate
there is a &read_block
that is being passed into ::Magic::Image.read/1
, and that could possibly be used to alter the image data passed into read itself, with one of the read_options
specifying a certain bit of data from the current_path
.
Though, the CarrierWave documentation is too shallow in describing it's possible usages and actually wrong in describing it's code usage. So, this was a dead-end for me.
Code
I wound up sourcing a bunch of code from the manipulate!
function to utilize inside of my own uploader, where I've removed some functionality not used in the generation of the thumbnail.
# @doc Returns the first page of a file
version :thumb, :if => :thumbable? do
process :cover
process convert: "jpg"
def full_filename(filename = model.file.filename) = "#{filename.split(".").first}.jpg"
def style = :thumb
# @doc This is an overridden function from the `manipulate!` function defined in CarrierWaves library
# @doc I removed the ability to pass in options, or a block to the function to use in processing the image.
# @doc This seemed to be the route to go because there isn't many maintainers available on CarrierWave and the documentation is trash.
def cover
cache_file
push_frames(get_frames)
rescue ::Magick::ImageMagickError
raise CarrierWave::ProcessingError, I18n.translate(:"errors.messages.processing_error")
end
private
# @doc This will store the file available on the uploader in the cache, unless it is already cached.
def cache_file
cache_stored_file! unless cached?
end
# @doc This will utilize RMagick to create an image from an altered current_path variable
# @doc Create a new ImageList, and store the image created as the first frame
def get_frames
path = "#{current_path}[0]"
image = ::Magick::Image.read(path)
frames = ::Magick::ImageList.new
frames << image.first
end
# @doc This will persist the frames created as an ImageList into the file on the uploader, essentially replacing the original pdf with the modified pdf.
def push_frames(frames)
frames.write(current_path)
end
# @doc This will destroy the ImageList that is allocating memory.
def destroy_image(frames)
frames.try(:destroy!)
end
end