Bitmap Image Rotation - (1 bit image)

I have an app I created a while back that uses TiffPictureMBS to merge barcodes into printing plate file bitmap TIFFs that are 97349 w X 75600 h. I have recently been given a requirement to rotate the merged TIFF files 270 degree after the barcode merge. I have tried several ways to do this that all result in failure. The most promising method appeared to be to to first merge the files to PictureMBS and use PictureMBS.Rotate270. this works fine with a grayscale image but fails with a bitmap image. My assumption is that this is because there is not an available ImageFormat for bitmap in PictureMBS and I am forced to use Graysale, (PictureMBS.ImageFormatG) . Even so, what’s weird is if I don’t rotate and just pass though PictureMBS by commenting out the Rotate270 the bitmap works. I’m looking for suggestions and or alternative to rotate a bitmap file and retain the 1bit depth.

Here is some test code I’m using, (that does not include the barcode images being merged into the memoryblock), that gives me the gobledygook output on rotating a bitmap:

[code]Public Sub RotateTiff()
Dim desc,err As String
Dim PlateFile As FolderItem = GetOpenFolderItem(FileTypes1.ImageTiff)
Dim DestFldr As FolderItem = SpecialFolder.Desktop

Dim n As Integer
Dim oldname,newname,nameparts() As String
oldname = PlateFile.Name
nameparts = Split(oldname,".")
For n = 0 To UBound(nameparts) -1
If n = 0 Then
newname = nameparts(n)
Else
newname = newname + “.” + nameparts(n)
End If
Next
n = UBound(nameparts)
newname = newname + “.new.” + nameparts(n)
Dim PlateFileNew As FolderItem = SpecialFolder.Desktop.Child(newname)

Dim PlateTIFF As New TiffPictureMBS
Dim PlateTIFFNew As New TiffPictureMBS

If PlateTIFF.Open(PlateFile) Then
If PlateTIFFNew.Create(PlateFileNew) Then

  Dim d As Date
  Dim y,m,dy,hh,mm,ss As String
  d = New Date
  y = Right(Str(d.Year),2)
  m = Format(d.Month,"0#")
  dy = Format(d.Day,"0#")
  hh =Format(d.Hour,"0#")
  mm = Format(d.Minute,"0#")
  ss =Format(d.Second,"0#")
  
  PlateTIFFNew.Height = PlateTIFF.Height
  PlateTIFFNew.Width  = PlateTIFF.Width
  PlateTIFFNew.RowsPerStrip = PlateTIFF.RowsPerStrip
  PlateTIFFNew.PlanarConfig = PlateTIFF.PlanarConfig
  PlateTIFFNew.Photometric = PlateTIFF.Photometric
  PlateTIFFNew.BitsPerSample = PlateTIFF.BitsPerSample
  PlateTIFFNew.SamplesPerPixel = PlateTIFF.SamplesPerPixel
  PlateTIFFNew.SampleFormat = PlateTIFF.SampleFormat
  PlateTIFFNew.FillOrder = PlateTIFF.FillOrder
  PlateTIFFNew.Orientation = PlateTIFF.Orientation
  PlateTIFFNew.ResolutionUnit = PlateTIFF.ResolutionUnit
  PlateTIFFNew.VerticalResolution = PlateTIFF.VerticalResolution
  PlateTIFFNew.VerticalPosition = PlateTIFF.VerticalPosition
  PlateTIFFNew.HorizontalResolution = PlateTIFF.HorizontalResolution
  PlateTIFFNew.HorizontalPosition = PlateTIFF.HorizontalPosition
  PlateTIFFNew.Compression = PlateTIFF.Compression
  PlateTIFFNew.Copyright = PlateTIFF.Copyright
  PlateTIFFNew.DateTime = y + ":" + m + ":" + dy + " " + hh + ":" + mm + ":" + ss
  PlateTIFFNew.HostComputer = PlateTIFF.HostComputer
  PlateTIFFNew.ImageDescription = PlateTIFF.ImageDescription
  PlateTIFFNew.Make = PlateTIFF.Make
  PlateTIFFNew.Model = PlateTIFF.Model
  PlateTIFFNew.Software = PlateTIFF.Software
  
  Dim PlateMemoryBlock As MemoryBlock = NewMemoryBlock(PlateTIFF.BytesPerRow)
  Dim p As New PictureMBS(PlateTIFF.Width, PlateTIFF.Height, PictureMBS.ImageFormatG)
  
  For i as Integer = 0 to PlateTIFF.Height - 1
    // read
    Call PlateTIFF.Scanline(PlateMemoryBlock, i)
    p.RowInFormat(i, p.ImageFormatG) = PlateMemoryBlock
  Next
  
  p = p.Rotate270
  
  For i as Integer = 0 to PlateTIFF.Height - 1
    // write
    PlateTIFFNew.Scanline(i) = p.RowInFormat(i, p.ImageFormatG)
  Next
  
  PlateTIFF.Close
  PlateTIFFNew.Close
  
Else
  // Error
  MsgBox("The PlateTIFFNew could not be created. ")
End If

Else
// Error
MsgBox("The Plate TIFF could not be opened. ")
End If
End Sub
[/code]

By commenting out p = p.Rotate270 I can use the above code and the new TIFF looks identical to the original TIFF

With p = p.Rotate270 uncommented the resulting bitmap is garbage

But it works correctly with a grayscale image

Is the image width a multiple of 4?

Have you tried the GraphicsMagik rotate?

dim image as new GMImageMBS image.read(f) dim co as new GMColorRGBMBS(1.0, 0.0, 0.0) image.BackgroundColor=co image.Rotate(50.0)

Well, as suggested by email, you can do this.
But you have to write some code yourself or hire me to write it in C.

You can load input row byte row.
But you need to have output in memory.
Than you can decode each byte in 8 rows at the same time and build the rotated bytes for the output.

Christian I won’t claim to have the knowledge base to do what you are suggesting without some additional help and I don’t have a budget to hire you to custom write it in C. Some additional clues would be helpful but that doesn’t seem to be forthcoming. The only exposure to using Memoryblocks and binary decoding I have is from your samples. Most of my apps deal with file movement and databases. I rely heavily on pros like you to produce plugins to do the heavy lifting that I don’t have the expertise for, which is why I gladly pay to license most of yours annually, (Main plugin, ChartDirector, DynaPDF). Nothing I write is for public consumption and developing applications is not my full time job. With that said TiffPictureMBS and PictureMBS are great plugins but they lack support for 1 bit color so I’m a bit irked that you aren’t being more helpful. I get the base concept of what you are saying I just don’t have a clue how to execute on it.

If anyone else has a better handle on Christian’s suggestion and can point me to some samples that show the various steps being suggested that I can decipher I welcome the input.

  1. The input image is a 2 dimensional array of pixels or bytes (97349,75600)
  2. The desire is to read each row in the array and copy to a column in another image array of pixels or bytes (75600,97349)
  3. I know how to read a row as shown in the code above.
  4. How do I decode/address the individual bytes in the row?
  5. How do I setup a MemoryBlock to copy the bytes into?
  6. How do I address the bytes so they go to the correct row and column?
  7. Lastly how do I read back the bytes a row at a time to write into a new 1 bit image?
  1. you read it via ScanLines function to get a memory block. Or row by row with ScanLine.
  2. It’s a lot of BitwiseAnd() to get the bit value for each bit.
  3. New MemoryBlock( RowBytes * Height)
  4. x and y switched from input for 90°
  5. Write with TiffPictureMBS class from memoryblock.

Maybe we better need to discuss this via email.

[quote=401230:@Christian Schmitz]1. you read it via ScanLines function to get a memory block. Or row by row with ScanLine.
4. It’s a lot of BitwiseAnd() to get the bit value for each bit.
5. New MemoryBlock( RowBytes * Height)
6. x and y switched from input for 90°
7. Write with TiffPictureMBS class from memoryblock.

Maybe we better need to discuss this via email.[/quote]

That is a bit more helpful. I’ll poke at it some later. I’m trying to get out of the house this morning for a vacation day so it may be Monday before I can give it some serious attention. I’ll happily pick up the discussion via email if that is your preference.

Next week is great. This week is busy for me and in busy times, my answers get brief.