Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Image rendering offset #20

Open
TheOriginalTom opened this issue Dec 17, 2024 · 7 comments
Open

Image rendering offset #20

TheOriginalTom opened this issue Dec 17, 2024 · 7 comments

Comments

@TheOriginalTom
Copy link

TheOriginalTom commented Dec 17, 2024

The implementation works well in a local dev environment, but I can't get a live site IIS to render the image properly. I must be doing something wrong. Can you help me? Here's a live site link to see the image rendering. com/account/register

@tossnet
Copy link
Owner

tossnet commented Dec 17, 2024

I can't trust a link pasted into an exit message. Share the code instead, and why not a screenshot as well..

@TheOriginalTom
Copy link
Author

Sorry, I didn't think of that. Here's a screen shot and razor.
Screenshot

Register

Create a new account.


  The security letters do not match the picture. Try again.

        <div class="form-floating mb-3">
            <InputText @bind-Value="Input.Email" class="form-control" autocomplete="username" aria-required="true" placeholder="[email protected]" />
            <label for="email">Email</label>
            <ValidationMessage For="() => Input.Email" class="text-danger" />
        </div>
        <div class="form-floating mb-3">
            <InputText type="password" @bind-Value="Input.Password" class="form-control" autocomplete="new-password" aria-required="true" placeholder="password" />
            <label for="password">Password</label>
            <ValidationMessage For="() => Input.Password" class="text-danger" />
        </div>
        <div class="form-floating mb-3">
            <InputText type="password" @bind-Value="Input.ConfirmPassword" class="form-control" autocomplete="new-password" aria-required="true" placeholder="password" />
            <label for="confirm-password">Confirm Password</label>
            <ValidationMessage For="() => Input.ConfirmPassword" class="text-danger" />
        </div>

        <div class="form-floating mb-6">
            <div class="col-lg-12">
                <Captcha @bind-CaptchaWord="@Captcha" CharNumber="@CaptchaLength" Height="80" Width="260"/>
            </div>
        </div>
        <div class="form-floating mb-3">
            <InputText type="text" @bind-Value="Input.EnteredCaptchaText" class="form-control" id="idCaptcha" placeholder="Type the security letters above" required />
            <label for="idCaptcha">Type the security letters above</label>
            <p style="color: red;" hidden=@hideSecurityMatchResults>&nbsp;&nbsp;The security letters do not match the picture. Capitalization matters. Try again.</p>
        </div>
        <button type="submit" class="w-100 btn btn-lg btn-primary">Register</button>
        <p>&nbsp;</p>
    </EditForm>
</div>

@tossnet
Copy link
Owner

tossnet commented Dec 17, 2024

MeasureText de Skia seems depreciated. I'll make a small update with GetGlyphWidths. It's hard to know what went wrong

float width = font.MeasureText(l.Value, out rect);

tossnet pushed a commit that referenced this issue Dec 17, 2024
@Govern24
Copy link

Govern24 commented Dec 19, 2024

@tossnet the following refactored code works locally and on deployed version. ` private void Initialization()
{
if (string.IsNullOrEmpty(CaptchaWord)) return;

        RandomValue = new Random();

        _bgColor = new SKColor((byte)RandomValue.Next(70, 100),
                                (byte)RandomValue.Next(60, 80),
                                (byte)RandomValue.Next(50, 90)
                              );


        var fontFamilies = new string[] { "Open Sans", "Courier", "Arial", "Times New Roman" };

        Letters = new List<Letter>();

        if (!string.IsNullOrEmpty(CaptchaWord))
        {
            foreach (char c in CaptchaWord)
            {
                var letter = new Letter
                {
                    Value = c.ToString(),
                    Angle = RandomValue.Next(-15, 25),
                    ForeColor = new SKColor((byte)RandomValue.Next(100, 256),
                                            (byte)RandomValue.Next(110, 256),
                                            (byte)RandomValue.Next(90, 256)),
                    Family = fontFamilies[RandomValue.Next(0, fontFamilies.Length)],
                };

                Letters.Add(letter);
            }

            int effectiveCaptchaLength = Math.Max(CharNumber, CharNumber);
            int dynamicWidth = Width + (effectiveCaptchaLength - CharNumber) * 10;
            int dynamicHeight = Height;
            using SKBitmap bitmap = new(dynamicWidth, dynamicHeight);
            using SKCanvas canvas = new(bitmap);
            canvas.Clear(_bgColor);

            using (SKPaint paint = new())
            {
                float x = 10;

                foreach (Letter l in Letters)
                {
                    var typeface = SKTypeface.FromFamilyName(l.Family);
                    using (var font = new SKFont(typeface, RandomValue.Next(Height / 2, (Height / 2) + (Height / 4))))
                    {
                        font.Edging = SKFontEdging.Antialias;
                        paint.Color = l.ForeColor;
                        paint.IsAntialias = true;

                        float width = font.MeasureText(l.Value);

                        float textWidth = width;
                        var y = RandomValue.Next(26, 35);
                        canvas.DrawText(l.Value, x, y, SKTextAlign.Left, font, paint);
                        x += textWidth + 10;
                    }
                }

                canvas.DrawLine(0, RandomValue.Next(0, Height), Width, RandomValue.Next(0, Height), paint);
                canvas.DrawLine(0, RandomValue.Next(0, Height), Width, RandomValue.Next(0, Height), paint);
                paint.Style = SKPaintStyle.Stroke;
                canvas.DrawOval(RandomValue.Next(-Width, Width), RandomValue.Next(-Height, Height), Width, Height, paint);
            }

            using SKImage image = SKImage.FromBitmap(bitmap);
            using SKData data = image.Encode(SKEncodedImageFormat.Jpeg, 100);

            img = ConvStreamToBase64(data);

        }

    }

    private static string ConvStreamToBase64(SKData Data)
    {
        MemoryStream ms = new();
        Data.SaveTo(ms);

        byte[] byteArray = ms.ToArray();
        string b64String = Convert.ToBase64String(byteArray);

        return $"data:image/jpg;base64,{b64String}";
    }`                                                                                        

@tossnet
Copy link
Owner

tossnet commented Dec 19, 2024

@Govern24 Nice work though, it would still need a rotation

@Andrey-2021
Copy link

Andrey-2021 commented Dec 23, 2024

I have this problem to

image

@cyrileek
Copy link

Works locally but not on the server (Azure App). Same problem on both Firefox and Microsoft Edge. Nuget Package version 1.7.1.
Image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants