Platforms to show: All Mac Windows Linux Cross-Platform

/Images/LCMS2/Convert image to sRGB JPEG


Required plugins for this example: MBS Images Plugin, MBS GraphicsMagick Plugin, MBS Util Plugin

You find this example project in your Plugins Download as a Xojo project file within the examples folder: /Images/LCMS2/Convert image to sRGB JPEG

This example is the version from Fri, 29th Jan 2015.

Project "Convert image to sRGB JPEG.xojo_binary_project"
Class App Inherits Application
Const kEditClear = "&Delete"
Const kFileQuit = "&Quit"
Const kFileQuitShortcut = ""
End Class
Class wConvertImage Inherits Window
Control pbConvertImage Inherits PushButton
ControlInstance pbConvertImage Inherits PushButton
EventHandler Sub Action() dim openDlg as OpenDialog dim saveDlg as New SaveAsDialog dim inputFile, outputFile as FolderItem openDlg = New OpenDialog openDlg.InitialDirectory = SpecialFolder.Desktop openDlg.Title = "Select an RGB or CMYK JPEG or TIFF file" openDlg.MultiSelect = False inputFile = openDlg.ShowModal if inputFile = Nil then Return if (inputFile.NameExtensionMBS <> "jpg") and (inputFile.NameExtensionMBS <> "jpeg") _ and (inputFile.NameExtensionMBS <> "tif") and (inputFile.NameExtensionMBS <> "tiff") then MsgBox( "This method only works with JPEG or TIFF files." ) Return end if saveDlg.InitialDirectory = inputFile.Parent saveDlg.Title = "Where do you want to save your sRGB JPEG?" saveDlg.SuggestedFileName = "Output sRGB image.jpg" outputFile = saveDlg.ShowModal If outputFile = Nil then Return generateRGBJPEG( inputFile, outputFile, 500 ) End EventHandler
End Control
Sub generateRGBJPEG(inputFile as FolderItem, outputFile as FolderItem, outputSize as Integer, Optional dontScaleUp as Boolean = False, Optional outputQuality as Integer = 60) // inputFile must be a JPEG or TIFF image in either RGB or CMYK mode. Other modes (e.g. greyscale) are not handled. // JPEGImporterMBS is used to read JPEG files, TiffPictureMBS is used to read TIFF files // LCMS2 is used to convert the image to the sRGB colour space // GMImageMBS is used to resize the image, and can be expanded to add borders, watermarks, etc // JPEGExporterMBS is used to save the JPEG, discarding the ICC profile to reduce file size dim sourceFormat as String dim i, rowBytes, pictureWidth, pictureHeight as Integer dim outputPicture as Picture dim convertProfile, sourceCMYK as Boolean dim rawPictureData, rawPictureRowData as MemoryBlock dim jpegImporter as JPEGImporterMBS dim jpegExporter as JPEGExporterMBS dim tiffImporter as TiffPictureMBS dim gmImage as GMImageMBS dim ct as LCMS2TransformMBS dim sourceProfile, outputProfile as LCMS2ProfileMBS dim inputBitmap, outputBitmap as LCMS2BitmapMBS if inputFile = Nil then Return if not inputFile.Exists then Return if outputFile = Nil then Return convertProfile = True outputProfile = LCMS2ProfileMBS.CreateSRGBProfile if (inputFile.NameExtensionMBS = "jpeg") or (inputFile.NameExtensionMBS = "jpg") then sourceFormat = "JPEG" // Use jpegImporterMBS to read the image jpegImporter = New JPEGImporterMBS try jpegImporter.YieldTicks = 1 jpegImporter.ReadMarkers = True jpegImporter.ReadProfileData = True jpegImporter.File = inputFile jpegImporter.Import catch err if err isa OutOfMemoryException then MsgBox( "Couldn't read image from JPEG because we ran out of memory: "+inputFile.Name ) Return end if end try if jpegImporter.Picture = Nil then MsgBox( "Couldn't read image from JPEG: "+inputFile.Name ) Return end if pictureWidth = jpegImporter.Width pictureHeight = jpegImporter.Height // Read the ICC profile from the image sourceProfile = LCMS2ProfileMBS.OpenProfileFromMemory( jpegImporter.ProfileData ) sourceCMYK = ((jpegImporter.ColorSpace = jpegImporter.ColorSpaceCMYK) or (jpegImporter.ColorSpace = jpegImporter.ColorSpaceYCCK)) if sourceCMYK then // We have to read the TIFF into a MemoryBlock so that we can convert it from CMYK to RGB later on jpegImporter.Mode = jpegImporter.ModeRaw jpegImporter.Import rawPictureData = jpegImporter.PictureData pictureWidth = jpegImporter.Width pictureHeight = jpegImporter.Height rawPictureData.InvertBytesMBS( 0, rawPictureData.size ) // Swap bytes else // Assume that the image is RGB and pass it to GraphicsMagick gmImage = New GMImageMBS( jpegImporter.Picture ) end if elseif (inputFile.NameExtensionMBS = "tiff") or (inputFile.NameExtensionMBS = "tif") then sourceFormat = "TIFF" // Use TiffPictureMBS to read the image try tiffImporter = New TiffPictureMBS tiffImporter.YieldTicks = 1 if not tiffImporter.Open( inputFile ) then MsgBox( "Unable to open TIFF: "+inputFile.Name ) Return end if if not tiffImporter.ReadRGB then MsgBox( "Unable to read TIFF: "+inputFile.Name ) Return end if pictureWidth = tiffImporter.Width pictureHeight = tiffImporter.Height // Read the ICC profile from the image sourceProfile = LCMS2ProfileMBS.OpenProfileFromMemory( tiffImporter.GetColorProfile ) if tiffImporter.SamplesPerPixel = 4 then // It looks like we've got a CMYK image sourceCMYK = True // We have to read the TIFF into a MemoryBlock so that we can convert it from CMYK to RGB later on rowBytes = tiffImporter.BytesPerRow rawPictureData = New MemoryBlock( pictureHeight * rowBytes ) for i=0 to pictureHeight -1 rawPictureRowData = tiffImporter.Scanline( i ) rawPictureData.StringValue( i * rowBytes, rowBytes ) = rawPictureRowData next else // Assume that the image is RGB and pass it to GraphicsMagick gmImage = new GMImageMBS( tiffImporter.Pict ) end if catch err if err isa OutOfMemoryException then MsgBox( "Couldn't read image from TIFF because we ran out of memory: "+inputFile.Name ) Return end if end try else Return // Not a file extension that we can work with. end if if convertProfile and (sourceProfile <> Nil) then // Convert the image to sRGB if sourceCMYK then // Use LCMS2 with a MemoryBlock to convert the image from CMYK to an RGB image in the sRGB colourspace rowBytes = pictureWidth * 4 // Create CMYK input picture from the MemoryBlock inputBitmap = New LCMS2BitmapMBS( pictureWidth, pictureHeight, LCMS2MBS.kcmsSigCMYKData, rowBytes, rawPictureData ) // Create RGB output image at same size outputBitmap = New LCMS2BitmapMBS( pictureWidth, pictureHeight, LCMS2MBS.kcmsSigRgbData ) // Transform the CMYK image to RGB ct = LCMS2TransformMBS.CreateTransform( sourceProfile, sourceProfile.FormatterForColorspace( 1 ), outputProfile, outputProfile.FormatterForColorspace( 1 ), LCMS2MBS.kINTENT_RELATIVE_COLORIMETRIC, 0 ) if ct.Transform( inputBitmap, outputBitmap ) then gmImage = New GMImageMBS( outputBitmap.Picture ) outputBitmap = Nil inputBitmap = Nil else MsgBox( "Unable to convert colour profile: "+inputFile.Name ) end if else // Assume RGB, so a straightforward conversion to the sRGB colourspace ct = LCMS2TransformMBS.CreateTransform( sourceProfile, sourceProfile.FormatterForColorspace(1, false), outputProfile, outputProfile.FormatterForColorspace(1, false), 1 ) // 1 = relative colorimetric intent outputBitmap = New LCMS2BitmapMBS( gmImage.CopyPicture ) if ct.Transform( outputBitmap ) then gmImage = New GMImageMBS( outputBitmap.Picture ) else MsgBox( "Unable to convert colour profile: "+inputFile.Name ) end if end if end if // Resize image if (gmImage.Height > outputSize) or (gmImage.Width > outputSize) or (not dontScaleUp) then // If the image is larger than the target size, or we're happy to scale it up, scale it down or up to the target size gmImage.Scale( New GMGeometryMBS( outputSize, outputSize ) ) end if outputPicture = gmImage.CopyPicture // Set up exporter jpegExporter = New JPEGExporterMBS jpegExporter.File = outputFile jpegExporter.Picture = outputPicture jpegExporter.Quality = outputQuality jpegExporter.Export End Sub
End Class
MenuBar MenuBar1
MenuItem FileMenu = "&File"
MenuItem FileQuit = "#App.kFileQuit"
MenuItem EditMenu = "&Edit"
MenuItem EditUndo = "&Undo"
MenuItem UntitledMenu1 = "-"
MenuItem EditCut = "Cu&t"
MenuItem EditCopy = "&Copy"
MenuItem EditPaste = "&Paste"
MenuItem EditClear = "#App.kEditClear"
MenuItem UntitledMenu0 = "-"
MenuItem EditSelectAll = "Select &All"
End MenuBar
End Project

See also:

The items on this page are in the following plugins: MBS Images Plugin.


The biggest plugin in space...