Skip to content

Skewed Landscape Images #94

@johneightyone

Description

@johneightyone

I'm using the following code to save images to JPG compressed TIFs.

This works if the width of the input image is divisible by 8. If it's not, then the image will be skewed.

Using memStream As New IO.MemoryStream()

                Using output As BitMiracle.LibTiff.Classic.Tiff = BitMiracle.LibTiff.Classic.Tiff.ClientOpen("in-memory", "w", memStream, New BitMiracle.LibTiff.Classic.TiffStream())
                    Dim page As Integer = 0
                    Dim pages As Integer = InputImages.Count

                    For Each inImage As Drawing.Image In InputImages

                        output.SetField(BitMiracle.LibTiff.Classic.TiffTag.IMAGEWIDTH, inImage.Width)
                        output.SetField(BitMiracle.LibTiff.Classic.TiffTag.IMAGELENGTH, inImage.Height)

                        output.SetField(BitMiracle.LibTiff.Classic.TiffTag.COMPRESSION, BitMiracle.LibTiff.Classic.Compression.JPEG)
                        output.SetField(BitMiracle.LibTiff.Classic.TiffTag.PHOTOMETRIC, BitMiracle.LibTiff.Classic.Photometric.YCBCR)
                        output.SetField(BitMiracle.LibTiff.Classic.TiffTag.SUBFILETYPE, BitMiracle.LibTiff.Classic.FileType.PAGE)
                        output.SetField(BitMiracle.LibTiff.Classic.TiffTag.ROWSPERSTRIP, inImage.Height)
                        output.SetField(BitMiracle.LibTiff.Classic.TiffTag.ORIENTATION, BitMiracle.LibTiff.Classic.Orientation.TOPLEFT)
                        output.SetField(BitMiracle.LibTiff.Classic.TiffTag.XRESOLUTION, inImage.HorizontalResolution)
                        output.SetField(BitMiracle.LibTiff.Classic.TiffTag.YRESOLUTION, inImage.VerticalResolution)
                        output.SetField(BitMiracle.LibTiff.Classic.TiffTag.RESOLUTIONUNIT, BitMiracle.LibTiff.Classic.ResUnit.INCH)
                        output.SetField(BitMiracle.LibTiff.Classic.TiffTag.BITSPERSAMPLE, 8)
                        output.SetField(BitMiracle.LibTiff.Classic.TiffTag.SAMPLESPERPIXEL, 3)
                        output.SetField(BitMiracle.LibTiff.Classic.TiffTag.PLANARCONFIG, BitMiracle.LibTiff.Classic.PlanarConfig.CONTIG)
                        output.SetField(BitMiracle.LibTiff.Classic.TiffTag.YCBCRPOSITIONING, 1)
                        output.SetField(BitMiracle.LibTiff.Classic.TiffTag.YCBCRSUBSAMPLING, 1, 1)
                        output.SetField(BitMiracle.LibTiff.Classic.TiffTag.JPEGTABLESMODE, BitMiracle.LibTiff.Classic.JpegTablesMode.NONE)
                        output.SetField(BitMiracle.LibTiff.Classic.TiffTag.PAGENUMBER, page, pages)




                        Dim bytes As Byte() = GetImageRasterBytes(CType(inImage, Bitmap), PixelFormat.Format24bppRgb)

                        convertSamples(bytes, inImage.Width, inImage.Height)

                        output.WriteEncodedStrip(0, bytes, bytes.Length)
                        page += 1

                        output.WriteDirectory()
                    Next

                    output.Close()

                    Dim byteArray() As Byte = memStream.ToArray()

                    Return byteArray

                End Using

            End Using

The helper functions i have are as follows:

Private Function GetImageRasterBytes(ByVal bmp As Bitmap, ByVal format As PixelFormat) As Byte()
        Dim rect = New Rectangle(0, 0, bmp.Width, bmp.Height)
        Dim bits As Byte()

        Try
            Dim bmpdata = bmp.LockBits(rect, ImageLockMode.ReadWrite, format)
            bits = New Byte(bmpdata.Stride * bmpdata.Height - 1) {}
            System.Runtime.InteropServices.Marshal.Copy(bmpdata.Scan0, bits, 0, bits.Length)
            bmp.UnlockBits(bmpdata)
        Catch
            Return Nothing
        End Try

        Return bits
    End Function
    Private Sub convertSamples(ByVal data As Byte(), ByVal width As Integer, ByVal height As Integer)
        Dim stride As Integer = data.Length \ height
        Const samplesPerPixel As Integer = 3

        For y As Integer = 0 To height - 1
            Dim offset As Integer = stride * y
            Dim strideEnd As Integer = offset + width * samplesPerPixel

            Dim i As Integer = offset
            While i <strideEnd
                Dim temp As Byte = data(i + 2)
                data(i + 2) = data(i)
                data(i) = temp
                i += samplesPerPixel
            End While
        Next
    End Sub

If you run the above the 1040x800 document will look fine.
The same code will result in a skewed output for the 1035x800 one.
image

In addition, when this skewing happens, the console does print out a warning:
in-memory: Warning, fractional scanline discarded

Anyone have any idea what may be going on, and how I can fix this?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions