Rails API create QR code and store image in active_storage - ruby-on-rails

I am working on Rails 6 API where I need to generate the QR code image and save that image to S3 using active_storage.
I am using rqrcode gem for this which gives me the SVG string. How can I convert the SVG string into the image and store that image to S3 using active_storage?
Following is my code
Controller
qrcode = RQRCode::QRCode.new("#{#order.id}")
svg = qrcode.as_svg(
offset: 0,
color: '000',
shape_rendering: 'crispEdges',
module_size: 6,
standalone: true
)
I should also generate the png image using
png = qrcode.as_png(
bit_depth: 1,
border_modules: 4,
color_mode: ChunkyPNG::COLOR_GRAYSCALE,
color: 'black',
file: nil,
fill: 'white',
module_px_size: 6,
resize_exactly_to: false,
resize_gte_to: false,
size: 120
)
But while storing I got the following error
ArgumentError (Could not find or build blob: expected attachable, got <ChunkyPNG::Image 120x120 [
Looking for a way to generate the image from the svg string or png file.
Thanks.
note: frontend is react-native

I was able to achieve this by following the answer here.
In short, after you generate the png, you can attach it to your model like so:
#model.qr_code.attach(io: StringIO.new(png.to_s), filename: "filename.png")

Related

How to store QR codes in rails generated from rqrcode

I need to generate a QR code and store it in rails. I am using rqrcode gem for generating QR code.
Here is how I am generating QR code as png.
def generate_qr_code(checkin_url)
qrcode = RQRCode::QRCode.new(checkin_url)
png = qrcode.as_png(
bit_depth: 1,
border_modules: 4,
color_mode: ChunkyPNG::COLOR_GRAYSCALE,
color: 'black',
file: nil,
fill: 'white',
module_px_size: 6,
resize_exactly_to: false,
resize_gte_to: false,
size: 120
)
self.update!(qr_code_image: png.to_s)
end
Issue:
I am facing issues while storing the QR code in qr_code_image.
self.update!(qr_code_image: png.to_s) showing following error:
*** NoMethodError Exception: undefined method `map' for #<String:0x007feb358121d0>
Did you mean? tap
Even IO.write("/tmp/github-qrcode.png", png.to_s) showing
*** Encoding::UndefinedConversionError Exception: "\x89" from ASCII-8BIT to UTF-8
I finally have to store the png image in qr_code_image where I am using
mount_uploaders :qr_code_image, QrCodeUploader
Method png.to_s return a binary content of file
To write a file from a binary contente run:
File.binwrite("/tmp/github-qrcode.png", png.to_s)
If you want save a png.to_s on your database, I think that use a base64 is a good choice.
To save a base64 in your model the code is something like that
u = User.find(1)
u.qr_code_image = Base64.encode64(png.to_s)
u.save
Finaly, to see a qrcode in browser just
<img src="data:image/png;base64,<%= user.qr_code_image %>" />

TCDPF render a pdf with a png image, problem with transparent png

If i render a pdf with a png file, i get the following error.
What's the problem with this?
Warning
Message: imagepng(/...examplepathfolder.../tmp/__tcpdf_172a5566d5e348eba254a398c0909340_imgmask_alpha_2e51083373b9767f3e6183dfb1d0d48e): failed to open stream: No such file or directory
Filename: tcpdf/tcpdf.php
it seems that is a problem with a transparent png file if i try the same with a jpeg there is no error.
There is an example to work with transparent files, https://tcpdf.org/examples/example_042/
For me i wont't understand what i have to change with my code
$info_left_column .= pdf_logo_url();
$pdf->MultiCell(($dimensions['wk'] / 2) - $dimensions['lm'], 0, $info_left_column, 0, 'J', 0, 0, '', '', true, 0, true, true, 0);
pdf_logo_url() returns the absolute path of the png file.
omg i found the problem.
So, under normal use the temp-folder ("K_PATH_CACHE") is not in use for tcpdf. If you use a png the temp-folder is important to create a second image to prepare problems with the alpha-channel.
So, in my installation was a wrong temp-folder, so i changed it and now all works fine :-)
As I showed in the picture, just uncomment this line:
//define ('K_PATH_CACHE', '/tmp/');

Alchemy CMS - Cloudinary - Image crop

In Alchemy CMS how can I use the Cloudinary feature for get the image in the size that I want?
I need this for:
a specific image, I mean that, one image could be 400x300 and another could be 200x200
for all the images of the same element
How can I do it?
In the element definition, in elements.yml, I can use the settings property:
- name: content_block
contents:
- name: title_text
type: EssenceText
default: :title_text_sample
- name: picture
type: EssencePicture
settings:
size: 400x300
crop: true
- name: multi_line_text
type: EssenceRichtext
but this is the same for all contents and I think that in this way the resize is done by the Alchemy server and not by the cloudinary.
Is there a way to edit the URLs manually? If so you can change the size of the images on the fly. For example, http://res.cloudinary.com/demo/image/upload/w_200,h_200/sample

How to read and upload ByteArray image in rails?

We are having Rails in backend and FLASH in frontend.
We wanted to upload image but we don't have any physical image we have pixes in ByteArray.
Now We want to upload that ByteArray(image) into rails through API.
How can we read that ByteArray image and convert into original image and upload to rails server. For image upload we are using carrierwave gem and rmagic in server.
Sample ByteArray image:
xÚ_# ¿PNG
IHDR,,y}u¼4IDATxÚì½i$Iv-ûæ¾{¸Ǿ瞕UUµu÷$úÄm8CÎÎ
x¾ëWêHzOo¶ޗ!G
# arr is ByteArray. 'image' is still in memory
image = Magick::Image.constitute(width, height, "RGB", arr.flatten)

Rails: Carrierwave recreate versions does not change old images

My Rails app uses carrierwave to manage image uploads. I have a watermark version of the images on my site. Previously I was overlaying an image on them, like so:
def watermark
manipulate! do |img|
logo = Magick::Image.read("#{Rails.root}/public/images/plc-watermark.png").first
img = img.composite(logo, Magick::SouthEastGravity, Magick::OverCompositeOp)
end
end
Now I'm overlaying text, like so:
def watermark
manipulate! do |img|
text = Magick::Draw.new
text.gravity = Magick::CenterGravity
text.pointsize = 12
text.font = "#{Rails.root}/public/fonts/hn300.ttf"
text.stroke = 'none'
text.annotate(img, 0, 0, 0, 0, "Photo © #{model.user.full_name}\nHosted by Placeology.ws\nPlease log in to remove this watermark")
img
end
end
Now, this works for new images, but when I call recreate_versions! the old photos are not replaced. How can I get this new watermark to replace the old one?
For what it's worth I'm using Fog with Amazon S3 for storage in both development and production.
This might not be quite the same issue, but for googleability:
We have a random hash in the filename similar to what is described in this discussion thread.
When regenerating images, it would generate new images, using a new hash, but it wouldn't update the filename stored in the database, so it would attempt to display images with the old names.
This reproduces the problem:
bundle exec rails runner "Foo.find(123).images.each { |img| uploader = img.image; puts %{before: #{img.image.inspect}}; uploader.recreate_versions!; puts %{after: #{img.reload.image.inspect}} }; p Foo.find(123).images"
It gives output like
before: /uploads/foo_123_6a34e47ef5.JPG
after: /uploads/foo_123_d9a346292d.JPG
[#<Image id: 456, foo_id: 123, image: "foo_123_6a34e47ef5.JPG">]
But adding a img.save! after recreating versions fixes it:
bundle exec rails runner "Foo.find(123).images.each { |img| uploader = img.image; puts %{before: #{img.image.inspect}}; uploader.recreate_versions!; img.save!; puts %{after: #{img.reload.image.inspect}} }; p Foo.find(123).images"
With output:
before: /uploads/foo_123_6a34e47ef5.JPG
after: /uploads/foo_123_d9a346292d.JPG
[#<Image id: 456, foo_id: 123, image: "foo_123_d9a346292d.JPG">]
Edit:
Actually, the above worked with files on disk, but not with fog. To make things easy for myself, I ended up just recreating the images and removing the old ones:
Image.all.each { |old|
new = Image.new(foo_id: old.foo_id, image: old.image)
new.save!
old.destroy
}
You need to call image.cache_stored_file! before calling recreate_versions!
It's weird because the method itself calls that if the file is cached, but for some reason it wasn't working.

Resources