Writing to stream creates border right and bottom

Jun 26, 2012 at 1:18 PM

I'm having trouble writing a constructed QR code to both stream and file.

I do the following:

 

QrEncoder qrEncoder = new QrEncoder(ErrorCorrectionLevel.H);

Gma.QrCodeNet.Encoding.QrCode code;

qrEncoder.TryEncode(UrlRelayManager.ConstructUrl(link), out code);

byte[] imageData;

using (MemoryStream stream = new MemoryStream()) {

            Renderer renderer = new Renderer(15, Brushes.Black, Brushes.White);

            renderer.WriteToStream(code.Matrix, stream, ImageFormat.Png);

            imageData = stream.ToArray();

         }

 

When I then write imageData to a file, I get a 1px border right and bottom. It also happens if I try to use renderer.CreateImageFile.

Furthermore, I would like to control the padding in the imageData. Can I do that?

 

Thanks

Coordinator
Jun 26, 2012 at 10:14 PM
Edited Jun 26, 2012 at 10:20 PM

Looks like you have been using version 0.3 from download page. For that version you can change quiet zone outside of QrCode. But it's very limited. It will be either 2 or 4 modules wide. Module size is what you set up during creation for renderer class. 15 is what you give to it. 

 

For 1px border, I'm not really sure what happen there, I will check code later. Also could you give me the image file you create, like post it on some image store website. I would like to see which kind of border it exist. That will be easier for me to find out what's going on. 

 

Another note will be, there are updated source code under this project. You can download the newest version and compile on your own. I have recreate all renderer since 0.3, but there are few more changes to the library before push out next release. But at mean time, newly created renderer and control are all working properly. I can not say that pixel border won't happen in GraphicsRenderer, as I feel that issue might relate to Microsoft's own out of box bitmap.Save method. The good thing about new renderers is that some of them allow you to draw QrCode at specific position without quiet zone(border outside QrCode). Like WriteableBitmapRenderer, you can have your own WriteableBitmap source and drop QrCode at specific location (Set up quiet zone to zero if you are doing that). Then you can do all sorts of things with WriteableBitmap. 

 

If you are locked with winform application, then quiet zone(border) will limit to zero, two, four models. But to be notice is that iMarti also created EncapsulatedPostScriptRenderer for this library. Which can create EPS files in winform or WPF. That's what's new in latest source code. Example will be inside source code project and document is under following link. 

http://qrcodenet.codeplex.com/wikipage?title=Renderer&referringTitle=Documentation

 

Edit:  For WriteableBitmap, if you want draw QrCode on some exist background that you have. Use DrawDarkModule method. That one won't draw light color module, which you can still see your own background after paint QrCode on it. Also as I said above, don't forget to set up QuietZone to zero, else QrCode will be paint at padding location. 

Jun 28, 2012 at 9:02 AM

Thank you for a quick reply.

Yes, I'm using 0.3 from the download page. How do I set QuietZone to 0?

You can get a sample QR code from my dropbox: http://db.tt/xihZFS8A. You'll have to open it in Photoshop or other image tool to actually visually see the borders, as they are transparent.

I'm not stuck with WinForm application. In fact, it's a console application responsible for encoding and storing the QR codes in a database and optionally write them to a file. No matter what I do (memory stream to database or directly to file) i get the same problem.

Any help would be greatly appreciated

Coordinator
Jun 29, 2012 at 2:51 AM

I can see what you mean now. 

I did some test. Using both 0.3 version and latest version from source code. There is issue with 0.3 but not with latest build. I think it relate to image size and actual paint area. Which inside 0.3 version, image size is equal to actual size plus one. That's what cause that happen. 

There is only one way to avoid is using latest version from source code instead. 

For quietzone, you can not set it to zero in 0.3. But you can reduce it to two after create renderer.  For example: "render.QuietZoneModules = QuietZoneModules.Two;"

I would suggest to use latest version from source code. Just compile it with release set up and grab dll file from it will do. 

Also as you want save QrCode into database, I would suggest save as vector image. Which you can create in latest version from source code using EncapsulatedPostScriptRenderer. Vector image will be superior as it can scale to any size without damage image. You can also store matrix inside database instead of image file, Same reason, matrix's memory usage will be much smaller than image file and draw it on demand. 

Detail about how to use latest renderer which I have posted at preview reply. 

Let me know if you have further question. 

Jun 29, 2012 at 12:38 PM

Latest version from source code fixed the border problem. Thank you, and great idea saving the matrix in the database instead of one of the image file formats.

Now I'm facing another problem. I want to give my users the option of selecting their preferred output format and resolution. My initial test is exporting the code to a 300dpi PNG file with the following code (much like the DrawingBrushRenderer example in the online documentation):

byte[] imageData;

using (MemoryStream stream = new MemoryStream()) {

 DrawingBrushRenderer renderer = new DrawingBrushRenderer(new FixedModuleSize(15, QuietZoneModules.Two));

BitmapSource bitmapSource = renderer.WriteToBitmapSource(matrix, new Point(300, 300));

PngBitmapEncoder pngEncoder = new PngBitmapEncoder();

pngEncoder.Interlace = PngInterlaceOption.On;

pngEncoder.Frames.Add(BitmapFrame.Create(bitmapSource));

pngEncoder.Save(stream);

imageData = stream.ToArray();

}

File.WriteAllBytes(file, imageData);

But! When the file is saved to disk, it is cropped and only a small part of the QR is visible. Check this sample: http://db.tt/YIBnBOuD

 

I hope you can help me out once again. Thanks.

Coordinator
Jul 1, 2012 at 12:38 AM

Thanks for report. I just fixed that issue. Please download latest check out and it should be fixed. 

Jul 2, 2012 at 6:31 AM

Great, thanks, I'll take a look at it later today.

By the way, I had to change MStatus on TriStateMatrix from internal to public in my local version. I needed to do this in order to create a TriStateMatrix (BitMatrix) based on data from the database, but without having MStatus as public, I couldn't read the StateMatrix data and thus not save it in the first place. If you have any other ideas for this, please let me know.

Thanks again

Coordinator
Jul 2, 2012 at 8:03 AM

Good point. That's something I would like to fix before next release. I will take look at it this weekend and let you know once I commit new changes. 

Also try out EncapsulatePostScriptRenderer. Or you can call it EPS file. That's vector based image file which can print out at any size without lose quality. 

Jul 2, 2012 at 11:16 AM
Thanks so much

Cheers,

ezRover Inc.

From: silverlancer <notifications@codeplex.com>
Reply-To: <QrCodeNet@discussions.codeplex.com>
Date: Monday, July 2, 2012 1:03 AM
To: Nader Rahimizad <ardumotion@gmail.com>
Subject: Re: Writing to stream creates border right and bottom [QrCodeNet:360974]

From: silverlancer

Good point. That's something I would like to fix before next release. I will take look at it this weekend and let you know once I commit new changes.

Also try out EncapsulatePostScriptRenderer. Or you can call it EPS file. That's vector based image file which can print out at any size without lose quality.

Coordinator
Jul 7, 2012 at 11:00 PM

Done. Create SqaureBitMatrix. That should be the one you will be using later on instead of TristateBitMatrix. They all inherit from Bitmatrix, that's what Renderer need anyway.

Also to be notice that Control's GetQrMatrix method's return value is already deep copy of internal BitMatrix. You don't really have to recreate. 

One minor error will be SquareBitMatrix's InternalArray property's comment. It state that SquareBitMatrix's InternalArray return array itself, not deep copy but it actually is. I changed that right before commit, forgot to edit comment. Will fix that in next submit. 

Let me know if there are any more issues. Kind of busy recently, will try my best to keep source code update. 

Jul 30, 2012 at 3:46 PM
Edited Jul 30, 2012 at 3:46 PM

I am having a problem with the export to EPS function.
When I fill in information like the part below and export it as an EPS file, the left square isn't an square. The bottom is lost
so the QR Readers aren't able to scan the code.

This only happens with EPS.. exporting to BMP or PNG is working correct... What is wrong?

BEGIN:VCARD
VERSION:3.0
N:Braakie;Frankie;van;;
FN:Frankie van Braakie
ORG:Logisz B.V.
TITLE:Senior Webdeveloper
EMAIL;type=INTERNET;type=WORK:frank.vanbraak@domain.nl
TEL;type=WORK:+31111111145
TEL;type=FAX:+31444444455
TEL;type=CELL:+31666666665
ADR;type=WORK:;;Street 7;city;;NL 7001 CH;Nederland
URL;type=WORK:http://www.domainname.nl/fbra
END:VCARD

Developer
Jul 31, 2012 at 1:16 PM

Just for the record, this question has also been asked and resolved in the Export as EPS discussion.

Export as Encapsuled PostScript (EPS)