Java™Platform, Micro EditionPart 3 – Low Level Graphicsv3.0b – 02 April 20091Andreas Jakl, 2009
DisclaimerThese slides are provided free of charge at http://www.symbianresources.com and are used during Java ME courses at the University of Applied Sciences in Hagenberg, Austria at the Mobile Computing department ( http://www.fh-ooe.at/mc )Respecting the copyright laws, you are allowed to use them:for your own, personal, non-commercial usein the academic environmentIn all other cases (e.g. for commercial training), please contact andreas.jakl@fh-hagenberg.atThe correctness of the contents of these materials cannot be guaranteed. Andreas Jakl is not liable for incorrect information or damage that may arise from using the materials.This document contains copyright materials which are proprietary to Sun or various mobile device manufacturers, including Nokia, SonyEricsson and Motorola. Sun, Sun Microsystems, the Sun Logo and the Java™ Platform, Micro Edition are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. Andreas Jakl, 20092
ContentsLow Level GraphicsCanvasKey EventsGeometry & TextImagesAndreas Jakl, 20093
Hierarchy of DisplayablesAndreas Jakl, 2009DisplayOne Display instance / MIDletAvailable in all sub-classes of DisplayableCommandDisplayableMethods for drawing to a canvasCanvasScreenTickerGraphicsTextBoxFormListAlertItemSpacerCustomItemChoice (Interface)ChoiceGroupStringItemDateFieldImageItemTextFieldGauge4
CanvasCanvas = base classDerive your own class from CanvasCanvas assigned to the screen like high level UI  can be mixed with high level UI!Functionality:Key events (key codes)Pointer eventsPaint (must be implemented)Visible / invisibleQuery propertiesAndreas Jakl, 20095
Example: Canvas – Quick OverviewAndreas Jakl, 20096public class RealReplayMIDletextendsMIDlet {private booleaniFirstStart = true;private MenuCanvasiMainCanvas;publicRealReplayMIDlet() { }protected void startApp() {// Startapp also gets called when the midlet gains foreground again        // -> Only initialize everything in the very first start-up.if (iFirstStart)        {iMainCanvas = newMenuCanvas(this);     // Create the main canvasDisplay.getDisplay(this).setCurrent(iMainCanvas);   // Activate the canvasiFirstStart = false;        }    }publicvoidpauseApp() { }publicvoiddestroyApp(boolean unconditional) { }public void exit() {destroyApp(true);notifyDestroyed();    }}
Example: Canvas – Quick OverviewAndreas Jakl, 20097public class MenuCanvasextends Canvas {privateRealReplayMIDletiMidlet;    private intiWidth;    private intiHeight;publicMenuCanvas(RealReplayMIDletaMidlet) {iMidlet = aMidlet;                   // Needed to quit the gamesetFullScreenMode(true);     // Activate full screen modeiWidth = getWidth();	  // Query screen sizeiHeight = getHeight();       }public void paint(Graphics aGraphics)    {        // Draw backgroundaGraphics.setColor(255, 255, 255);aGraphics.fillRect(0, 0, iWidth, iHeight);        // [...]    }protected void keyPressed(intaKeyCode)    {        // Process key events [...]         repaint();    }}
The Life of a CanvasAndreas Jakl, 20098Canvasconstructordisplay.setCurrent(myCanvas)showNotify()paint()… events …keyPressed()pointerPressed()display.setCurrent(myForm)hideNotify()
Canvas – OverviewAndreas Jakl, 20099getWidth()(0, 0)setFullScreenMode(true)drawImage()drawString()getHeight()fillRoundRect()drawRoundRect()fillRect()
Canvas – Full ScreensetFullScreenMode(false);setFullScreenMode(true);Andreas Jakl, 200910
Canvas – Show and HideshowNotify()Is called directly before Canvas becomes visibleFor initialization, e.g. (re)starting a timerhideNotify()Called after becoming invisibleFree resources, cancel timers and threads, ...Also called by the AMS when system screens (e.g., incoming call) are displayed on topQuery visibility: Displayable.isShown()Andreas Jakl, 200911
Canvas – EventsEvents sent to (visible) CanvasCalls methods defined in Canvas base classKey- & pointer-events, commandsSerial event deliveryNo second event is sent before first event is handled (= you left the event handling method)Exception: repaint enforced by youAndreas Jakl, 200912
Key EventskeyPressed(intkeyCode)When a key is pressed downkeyRepeated(intkeyCode)Called again and again when the key is held downFrequency depends on mobile phone   better: use an own timer until …keyReleased(intkeyCode)When the key is releasedAndreas Jakl, 200913keyPressed()keyRepeated()keyReleased()
Key CodesprotectedvoidkeyPressed(intkeycode)ConstantsaredefinedforstandardkeysAndreas Jakl, 200914Defined in the Canvasclass
Key Codes – Game ActionsPhones: no standardized key layoutTherefore: game actions – appropriate keys for each phoneintgetGameAction (intkeyCode)Andreas Jakl, 200915Defined in the Canvasclass
Key Codes – ExampleAndreas Jakl, 200916protected void keyPressed(intkeycode) {SimplePlayerGUIgui = getGUI();switch (keycode) {		// This variant does not allow handling multiple simultaneous keypressescase Canvas.KEY_NUM1:	// (which are not supported by many phones)// Jump backwardgui.skip(true);break;caseCanvas.KEY_NUM2:gui.togglePlayer();break;// [...]caseCanvas.KEY_POUND:gui.changeVolume(false);break;default:	// Handle both keys and game actions – keys first, as they might be game actions as wellintgameAction = getGameAction(keycode);if (gameAction == Canvas.RIGHT) {// Jump forwardgui.skip(false);        // [...]        } elseif (gameAction == Canvas.FIRE) {gui.togglePlayer();        }    }Adapted from the Sun WTK 2.5.2. MobileMediaAPI-examle
Canvas – Soft Keys, …Problem: MIDP 2.0 does not define keycode constants for softkeys, delete, ...  Different keycodesfor every manufacturerSolutions:Use Commands (problematic: high level menu doesn’t fit to your design!)Compile an own version for every manufacturerUse generic ‘translation’-method – within certain limitsExample – left softkeykeycode: -6 (Nokia), -1 (Siemens), -21 (Motorola), 21 (Motorola)Andreas Jakl, 200917
Canvas – PaintIf repaint is necessary (e.g. info dialog was on top of MIDlet)Framework calls Canvas.paint()Request repaint yourselfCall: repaint()Optional: specify regionpaint()will be called automatically andasynchronously, at a “fitting” momentDouble BufferingUsually supported and activatedQuery: booleandblBuf = canvas.isDoubleBuffered();If not: create off-screen bitmap yourselfAndreas Jakl, 200918void keyPressed(int aKeyCode) {    // Process key events [...]     repaint();}paint() not called instantly;usually through an extra threadvoid paint(Graphics g) {    // Draw...}
GraphicsDrawing tothe ScreenAndreas Jakl, 200919
GraphicsGraphics-object sent to paint() as a parameterProvides methods for drawing of:Line (SOLID or DOTTED)Rectangle (also filled and/or with rounded corners)Arc (part of an ellipse, also filled)Triangle (also filled)TextImagesAndreas Jakl, 200920void paint(Graphics g) {    // Draw...}
ColoursColour is used for all drawing operations that follow (including text)g.setColor(int red, int green, int blue);Usually no 32 bit display:Automatic assignment of nearest displayable colour no colour fidelityAndreas Jakl, 200921void paint(Graphics g) {g.setColor(255, 255, 255); 	// Whiteg.fillRect(0, 0, getWidth(), getHeight());		// Fill the whole backgroundg.setColor(255, 0, 0);  	// Redg.drawLine(5, 5, 250, 250);        // Centered textg.drawString("Hello", getWidth() / 2, getHeight() / 2, Graphics.HCENTER|Graphics.BASELINE);}
TextDefinepositionusinganchorpointsImages: similar, but useVCenterinsteadofBaselineAndreas Jakl, 200922LeftHCenterRightTopMopiusBaselineBottom
Example:g.drawString(“Mopius”, 0, 0, Graphics.HCENTER|Graphics.BASELINE);CanvasText – PositioningAndreas Jakl, 200923Mopiusg.drawString(“Mopius”, 0, 0, Graphics.LEFT|Graphics.TOP);Mopius
Recap: ORAndreas Jakl, 200924OR executed for corresponding bits of two valuesOverview: ORBoth values that were combined withor can be retrieved later onBaseline is contained in the combinedvalue!
Text – FontChoose through Font-object, then assign to Graphics-obj.Request font based on criteria:Face: monospace, proportional, systemStyle: plain, bold, italic, underlinedSize:large, medium, smallExample:Font titleFont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD|Font.STYLE_ITALIC, Font.SIZE_LARGE);g.setFont(titleFont);g.drawString(“Test”, 0, 0, Graphics.TOP|Graphics.LEFT);Andreas Jakl, 200925
Text – FontSun WTKNokia Series 40 (Emulator)Andreas Jakl, 200926… mostgamesusetheirownbitmapfonts!
GeometryDefinesettingsg.setStrokeStyle(Graphics.DOTTED); // orGraphics.SOLIDExample:protectedvoidpaint (Graphics g) {// Draw backgroundg.setColor(255, 255, 255);g.fillRect(0, 0, getWidth(), getHeight());// Draw strokeg.setStrokeStyle(Graphics.DOTTED);g.setColor(255, 0, 0);g.drawLine(0, 0, getWidth(), getHeight());}Andreas Jakl, 200927
Coordinate SystemDefault: Top Left = 0 / 0Visible areacanbemovedthroughtranslate()Andreas Jakl, 200928protectedvoidpaint (Graphics g){  //g.translate(50, 50);g.setColor(128, 128, 128);g.fillRect(0, 0, getWidth(), getHeight());g.setStrokeStyle(Graphics.SOLID);g.setColor(255, 0, 0);g.drawLine(0, 0, getWidth(), getHeight());g.drawLine(0, getHeight(), getWidth(), 0);g.setColor (0,0, 0);g.drawString ("Hello World", 0, 0, Graphics.TOP|Graphics.HCENTER);}w/o translate()withtranslate()
ImagesPictures, Photos, Drawings, …Andreas Jakl, 200929
ImagesMain image format for JavaME (must be supported):.png (Portable Network Graphics)Similar to .gif (which was patented until 2003 because of its LZW compression)Features:Compression: works well for graphics, not so well for photosTransparency: support depends on device – 1 bit transparency or full alpha-channel. Query:int levels = [Display].numAlphaLevels()Usually used for phones:8 bit colour depth (file size), 1 bit transparency (compatibility)Andreas Jakl, 200930
Save PNGs – File Size ReductionOptimized export – Photoshop: Save for WebFurther optimization – Pngcrush:http://pmt.sourceforge.net/pngcrush/Andreas Jakl, 200931Use as few colors as possible (fine gradients compress worse)No dithering (compression gets more difficult)Transparenter Kanal kann gesetzt werdenYou can set a transparency channel
PNG Optimization – Example: 472 x 472 px Andreas Jakl, 200932256 colours, no dither30,0 kB64 colours, no dither16,3 kB8 colours, no dither6,3 kBResults:- Not much difference between 256 and 64 colours (especially on a device display), but only half of the file size- Limits of optimization: 8 colours not enough- Dithering at 8 colours: same file size as visually better 64 colours image. Often, dithering is problematic!8 colours, Diffusion dither15,9 kB
ImagesImage-class saves picture, independent of the displayVariants:Immutable: not modifiable, e.g. when loaded from files, resource bundles or a network.Examples: logos, sprites, …Mutable: modifiable, created by the applicationExamples: off-screen bitmap for double buffering, dynamically modifiable images, images created by the app at runtime for MIDlet file size reasonsAndreas Jakl, 200933
Immutable Images and MIDletsImage file has to be in .jar archiveOften, IDEs copy all files of project folders to .jar  don’t leave backups or test data in there!Andreas Jakl, 200934
Image – ExampleAdd an image to the NetBeans-projectCreate resource folder in the project folder (e.g. /res/)Add folder to the NetBeans-project “Resources”Resource-folder should be included in the packaging process ( project properties)Andreas Jakl, 200935312
Image – ExampleLoad and display the imageAndreas Jakl, 200936// Load image as an instance variable// Warning: can take a long time for multiple / large images// -> in that case: asynchronous loading in an own thread!Image titleImg = Image.createImage(“/title.png”);…protected void paint (Graphics g) {g.drawImage(titleImg, 0, 0, Graphics.TOP|Graphics.LEFT);}
Mutable ImagesCreated dynamically during runtimeAndreas Jakl, 200937classImageDemoCanvasextendsCanvas{privateImagemutableImg;publicImageDemoCanvas ()     {mutableImg= Image.createImage (10,10);mutableImg.getGraphics().fillArc (0,0,10,10,0,360);    }}
Conversion Mutable   ImmutableMutable  Immutable:Immutable  Mutable:Andreas Jakl, 200938immutableImg = Image.createImage(mutableImg);Image immutableImg; // theimagetobecopiedimmutableImg = Image.createImage(...); 	// Create theimmutableimagefrom e.g. a file// Create a mutableimagewiththe same dimensionsImage mutableImg = Image.createImage(immutableImg.getWidth(), immutableImg.getHeight());// GetthegraphicscontextofthenewmutableimageGraphics g = copy.getGraphics();// Copytheimmutableimagetothemutableimage (bydrawingit)g.drawImage(immutableImg, 0, 0, TOP|LEFT);
Thanks for your attentionThat’s it!Andreas Jakl, 200939

Java ME - 03 - Low Level Graphics E

  • 1.
    Java™Platform, Micro EditionPart3 – Low Level Graphicsv3.0b – 02 April 20091Andreas Jakl, 2009
  • 2.
    DisclaimerThese slides areprovided free of charge at http://www.symbianresources.com and are used during Java ME courses at the University of Applied Sciences in Hagenberg, Austria at the Mobile Computing department ( http://www.fh-ooe.at/mc )Respecting the copyright laws, you are allowed to use them:for your own, personal, non-commercial usein the academic environmentIn all other cases (e.g. for commercial training), please contact andreas.jakl@fh-hagenberg.atThe correctness of the contents of these materials cannot be guaranteed. Andreas Jakl is not liable for incorrect information or damage that may arise from using the materials.This document contains copyright materials which are proprietary to Sun or various mobile device manufacturers, including Nokia, SonyEricsson and Motorola. Sun, Sun Microsystems, the Sun Logo and the Java™ Platform, Micro Edition are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. Andreas Jakl, 20092
  • 3.
    ContentsLow Level GraphicsCanvasKeyEventsGeometry & TextImagesAndreas Jakl, 20093
  • 4.
    Hierarchy of DisplayablesAndreasJakl, 2009DisplayOne Display instance / MIDletAvailable in all sub-classes of DisplayableCommandDisplayableMethods for drawing to a canvasCanvasScreenTickerGraphicsTextBoxFormListAlertItemSpacerCustomItemChoice (Interface)ChoiceGroupStringItemDateFieldImageItemTextFieldGauge4
  • 5.
    CanvasCanvas = baseclassDerive your own class from CanvasCanvas assigned to the screen like high level UI  can be mixed with high level UI!Functionality:Key events (key codes)Pointer eventsPaint (must be implemented)Visible / invisibleQuery propertiesAndreas Jakl, 20095
  • 6.
    Example: Canvas –Quick OverviewAndreas Jakl, 20096public class RealReplayMIDletextendsMIDlet {private booleaniFirstStart = true;private MenuCanvasiMainCanvas;publicRealReplayMIDlet() { }protected void startApp() {// Startapp also gets called when the midlet gains foreground again // -> Only initialize everything in the very first start-up.if (iFirstStart) {iMainCanvas = newMenuCanvas(this); // Create the main canvasDisplay.getDisplay(this).setCurrent(iMainCanvas); // Activate the canvasiFirstStart = false; } }publicvoidpauseApp() { }publicvoiddestroyApp(boolean unconditional) { }public void exit() {destroyApp(true);notifyDestroyed(); }}
  • 7.
    Example: Canvas –Quick OverviewAndreas Jakl, 20097public class MenuCanvasextends Canvas {privateRealReplayMIDletiMidlet; private intiWidth; private intiHeight;publicMenuCanvas(RealReplayMIDletaMidlet) {iMidlet = aMidlet; // Needed to quit the gamesetFullScreenMode(true); // Activate full screen modeiWidth = getWidth(); // Query screen sizeiHeight = getHeight(); }public void paint(Graphics aGraphics) { // Draw backgroundaGraphics.setColor(255, 255, 255);aGraphics.fillRect(0, 0, iWidth, iHeight); // [...] }protected void keyPressed(intaKeyCode) { // Process key events [...] repaint(); }}
  • 8.
    The Life ofa CanvasAndreas Jakl, 20098Canvasconstructordisplay.setCurrent(myCanvas)showNotify()paint()… events …keyPressed()pointerPressed()display.setCurrent(myForm)hideNotify()
  • 9.
    Canvas – OverviewAndreasJakl, 20099getWidth()(0, 0)setFullScreenMode(true)drawImage()drawString()getHeight()fillRoundRect()drawRoundRect()fillRect()
  • 10.
    Canvas – FullScreensetFullScreenMode(false);setFullScreenMode(true);Andreas Jakl, 200910
  • 11.
    Canvas – Showand HideshowNotify()Is called directly before Canvas becomes visibleFor initialization, e.g. (re)starting a timerhideNotify()Called after becoming invisibleFree resources, cancel timers and threads, ...Also called by the AMS when system screens (e.g., incoming call) are displayed on topQuery visibility: Displayable.isShown()Andreas Jakl, 200911
  • 12.
    Canvas – EventsEventssent to (visible) CanvasCalls methods defined in Canvas base classKey- & pointer-events, commandsSerial event deliveryNo second event is sent before first event is handled (= you left the event handling method)Exception: repaint enforced by youAndreas Jakl, 200912
  • 13.
    Key EventskeyPressed(intkeyCode)When akey is pressed downkeyRepeated(intkeyCode)Called again and again when the key is held downFrequency depends on mobile phone  better: use an own timer until …keyReleased(intkeyCode)When the key is releasedAndreas Jakl, 200913keyPressed()keyRepeated()keyReleased()
  • 14.
  • 15.
    Key Codes –Game ActionsPhones: no standardized key layoutTherefore: game actions – appropriate keys for each phoneintgetGameAction (intkeyCode)Andreas Jakl, 200915Defined in the Canvasclass
  • 16.
    Key Codes –ExampleAndreas Jakl, 200916protected void keyPressed(intkeycode) {SimplePlayerGUIgui = getGUI();switch (keycode) { // This variant does not allow handling multiple simultaneous keypressescase Canvas.KEY_NUM1: // (which are not supported by many phones)// Jump backwardgui.skip(true);break;caseCanvas.KEY_NUM2:gui.togglePlayer();break;// [...]caseCanvas.KEY_POUND:gui.changeVolume(false);break;default: // Handle both keys and game actions – keys first, as they might be game actions as wellintgameAction = getGameAction(keycode);if (gameAction == Canvas.RIGHT) {// Jump forwardgui.skip(false); // [...] } elseif (gameAction == Canvas.FIRE) {gui.togglePlayer(); } }Adapted from the Sun WTK 2.5.2. MobileMediaAPI-examle
  • 17.
    Canvas – SoftKeys, …Problem: MIDP 2.0 does not define keycode constants for softkeys, delete, ...  Different keycodesfor every manufacturerSolutions:Use Commands (problematic: high level menu doesn’t fit to your design!)Compile an own version for every manufacturerUse generic ‘translation’-method – within certain limitsExample – left softkeykeycode: -6 (Nokia), -1 (Siemens), -21 (Motorola), 21 (Motorola)Andreas Jakl, 200917
  • 18.
    Canvas – PaintIfrepaint is necessary (e.g. info dialog was on top of MIDlet)Framework calls Canvas.paint()Request repaint yourselfCall: repaint()Optional: specify regionpaint()will be called automatically andasynchronously, at a “fitting” momentDouble BufferingUsually supported and activatedQuery: booleandblBuf = canvas.isDoubleBuffered();If not: create off-screen bitmap yourselfAndreas Jakl, 200918void keyPressed(int aKeyCode) { // Process key events [...] repaint();}paint() not called instantly;usually through an extra threadvoid paint(Graphics g) { // Draw...}
  • 19.
  • 20.
    GraphicsGraphics-object sent topaint() as a parameterProvides methods for drawing of:Line (SOLID or DOTTED)Rectangle (also filled and/or with rounded corners)Arc (part of an ellipse, also filled)Triangle (also filled)TextImagesAndreas Jakl, 200920void paint(Graphics g) { // Draw...}
  • 21.
    ColoursColour is usedfor all drawing operations that follow (including text)g.setColor(int red, int green, int blue);Usually no 32 bit display:Automatic assignment of nearest displayable colour no colour fidelityAndreas Jakl, 200921void paint(Graphics g) {g.setColor(255, 255, 255); // Whiteg.fillRect(0, 0, getWidth(), getHeight()); // Fill the whole backgroundg.setColor(255, 0, 0); // Redg.drawLine(5, 5, 250, 250); // Centered textg.drawString("Hello", getWidth() / 2, getHeight() / 2, Graphics.HCENTER|Graphics.BASELINE);}
  • 22.
    TextDefinepositionusinganchorpointsImages: similar, butuseVCenterinsteadofBaselineAndreas Jakl, 200922LeftHCenterRightTopMopiusBaselineBottom
  • 23.
    Example:g.drawString(“Mopius”, 0, 0,Graphics.HCENTER|Graphics.BASELINE);CanvasText – PositioningAndreas Jakl, 200923Mopiusg.drawString(“Mopius”, 0, 0, Graphics.LEFT|Graphics.TOP);Mopius
  • 24.
    Recap: ORAndreas Jakl,200924OR executed for corresponding bits of two valuesOverview: ORBoth values that were combined withor can be retrieved later onBaseline is contained in the combinedvalue!
  • 25.
    Text – FontChoosethrough Font-object, then assign to Graphics-obj.Request font based on criteria:Face: monospace, proportional, systemStyle: plain, bold, italic, underlinedSize:large, medium, smallExample:Font titleFont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD|Font.STYLE_ITALIC, Font.SIZE_LARGE);g.setFont(titleFont);g.drawString(“Test”, 0, 0, Graphics.TOP|Graphics.LEFT);Andreas Jakl, 200925
  • 26.
    Text – FontSunWTKNokia Series 40 (Emulator)Andreas Jakl, 200926… mostgamesusetheirownbitmapfonts!
  • 27.
    GeometryDefinesettingsg.setStrokeStyle(Graphics.DOTTED); // orGraphics.SOLIDExample:protectedvoidpaint(Graphics g) {// Draw backgroundg.setColor(255, 255, 255);g.fillRect(0, 0, getWidth(), getHeight());// Draw strokeg.setStrokeStyle(Graphics.DOTTED);g.setColor(255, 0, 0);g.drawLine(0, 0, getWidth(), getHeight());}Andreas Jakl, 200927
  • 28.
    Coordinate SystemDefault: TopLeft = 0 / 0Visible areacanbemovedthroughtranslate()Andreas Jakl, 200928protectedvoidpaint (Graphics g){ //g.translate(50, 50);g.setColor(128, 128, 128);g.fillRect(0, 0, getWidth(), getHeight());g.setStrokeStyle(Graphics.SOLID);g.setColor(255, 0, 0);g.drawLine(0, 0, getWidth(), getHeight());g.drawLine(0, getHeight(), getWidth(), 0);g.setColor (0,0, 0);g.drawString ("Hello World", 0, 0, Graphics.TOP|Graphics.HCENTER);}w/o translate()withtranslate()
  • 29.
    ImagesPictures, Photos, Drawings,…Andreas Jakl, 200929
  • 30.
    ImagesMain image formatfor JavaME (must be supported):.png (Portable Network Graphics)Similar to .gif (which was patented until 2003 because of its LZW compression)Features:Compression: works well for graphics, not so well for photosTransparency: support depends on device – 1 bit transparency or full alpha-channel. Query:int levels = [Display].numAlphaLevels()Usually used for phones:8 bit colour depth (file size), 1 bit transparency (compatibility)Andreas Jakl, 200930
  • 31.
    Save PNGs –File Size ReductionOptimized export – Photoshop: Save for WebFurther optimization – Pngcrush:http://pmt.sourceforge.net/pngcrush/Andreas Jakl, 200931Use as few colors as possible (fine gradients compress worse)No dithering (compression gets more difficult)Transparenter Kanal kann gesetzt werdenYou can set a transparency channel
  • 32.
    PNG Optimization –Example: 472 x 472 px Andreas Jakl, 200932256 colours, no dither30,0 kB64 colours, no dither16,3 kB8 colours, no dither6,3 kBResults:- Not much difference between 256 and 64 colours (especially on a device display), but only half of the file size- Limits of optimization: 8 colours not enough- Dithering at 8 colours: same file size as visually better 64 colours image. Often, dithering is problematic!8 colours, Diffusion dither15,9 kB
  • 33.
    ImagesImage-class saves picture,independent of the displayVariants:Immutable: not modifiable, e.g. when loaded from files, resource bundles or a network.Examples: logos, sprites, …Mutable: modifiable, created by the applicationExamples: off-screen bitmap for double buffering, dynamically modifiable images, images created by the app at runtime for MIDlet file size reasonsAndreas Jakl, 200933
  • 34.
    Immutable Images andMIDletsImage file has to be in .jar archiveOften, IDEs copy all files of project folders to .jar  don’t leave backups or test data in there!Andreas Jakl, 200934
  • 35.
    Image – ExampleAddan image to the NetBeans-projectCreate resource folder in the project folder (e.g. /res/)Add folder to the NetBeans-project “Resources”Resource-folder should be included in the packaging process ( project properties)Andreas Jakl, 200935312
  • 36.
    Image – ExampleLoadand display the imageAndreas Jakl, 200936// Load image as an instance variable// Warning: can take a long time for multiple / large images// -> in that case: asynchronous loading in an own thread!Image titleImg = Image.createImage(“/title.png”);…protected void paint (Graphics g) {g.drawImage(titleImg, 0, 0, Graphics.TOP|Graphics.LEFT);}
  • 37.
    Mutable ImagesCreated dynamicallyduring runtimeAndreas Jakl, 200937classImageDemoCanvasextendsCanvas{privateImagemutableImg;publicImageDemoCanvas () {mutableImg= Image.createImage (10,10);mutableImg.getGraphics().fillArc (0,0,10,10,0,360); }}
  • 38.
    Conversion Mutable  ImmutableMutable  Immutable:Immutable  Mutable:Andreas Jakl, 200938immutableImg = Image.createImage(mutableImg);Image immutableImg; // theimagetobecopiedimmutableImg = Image.createImage(...); // Create theimmutableimagefrom e.g. a file// Create a mutableimagewiththe same dimensionsImage mutableImg = Image.createImage(immutableImg.getWidth(), immutableImg.getHeight());// GetthegraphicscontextofthenewmutableimageGraphics g = copy.getGraphics();// Copytheimmutableimagetothemutableimage (bydrawingit)g.drawImage(immutableImg, 0, 0, TOP|LEFT);
  • 39.
    Thanks for yourattentionThat’s it!Andreas Jakl, 200939