Opnemen en registreren van medische foto´s via een mobile...

76
Academiejaar 2013–2014 Faculteit Ingenieurswetenschappen en Architectuur Valentin Vaerwyckweg 1 – 9000 Gent Opnemen en registreren van medische foto´s via een mobile app Begeleider: Kristof COUCKE (Dobco Medical Systems) Promotoren: dr. Marleen DENERT Jan DOBBENIE (Dobco Medical Systems) Joachim VAN DEN ABEELE Masterproef voorgedragen tot het behalen van het diploma van Master in de industriële wetenschappen: informatica Powered by TCPDF (www.tcpdf.org)

Transcript of Opnemen en registreren van medische foto´s via een mobile...

Page 1: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Academiejaar 2013–2014 Faculteit Ingenieurswetenschappen en Architectuur

Valentin Vaerwyckweg 1 – 9000 Gent

Opnemen en registreren van medische

foto´s via een mobile app

Begeleider: Kristof COUCKE (Dobco Medical Systems)

Promotoren: dr. Marleen DENERT

Jan DOBBENIE (Dobco Medical Systems)

Joachim VAN DEN ABEELE

Masterproef voorgedragen tot het behalen van het diploma van

Master in de industriële wetenschappen: informatica

Powered by TCPDF (www.tcpdf.org)

Page 2: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Woord vooraf

Na een zwaar en intens schakel- en masterjaar is deze masterproef de kers op de taart van

mijn opleiding Master of Science in de industriele wetenschappen informatica. Zonder de

steun en hulp van enkele mensen had ik deze masterproef niet kunnen waarmaken. Daarom

zou ik graag mijn oprechte dank betuigen aan allen die mij hebben gesteund en geholpen bij

het uitwerken van deze masterproef.

Allereerst dank ik mijn externe promotor, dr. Marleen Denert, voor haar professionele advies,

opbouwende kritiek en de nodige bemerkingen.

Verder zou ik ook graag mijn interne promotoren bij Dobco Medical Systems, de heer Jan

Dobbenie en de heer Kristof Coucke, willen bedanken voor de uitstekende begeleiding tijdens

de realisatie van deze masterproef.

Ook hartelijk dank aan mijn vrienden voor hun steun, empathie en bereidheid om steeds

naar mij te willen luisteren en mij te helpen.

In het bijzonder wil ik ook mijn ouders, mijn grootvader en mijn vriendin, Valerie Carlier,

bedanken voor hun financiele en morele steun tijdens mijn opleiding. Hun onvoorwaarde-

lijke liefde en vertrouwen in mij vormden een enorme motivatie bij het realiseren van deze

masterproef.

ii

Page 3: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Abstract

In deze thesis werd de mobiele applicatie iSentToPacs ontwikkeld die tot doel heeft de alle-

daagse handelingen van een verpleegkundige te vereenvoudigen en informatiseren. Waar vroe-

ger foto′s van huidaandoeningen of brandwonden met een fototoestel werden genomen en ver-

volgens handmatig werden toegevoegd aan het medisch dossier van de patient, wordt nu de

applicatie iSentToPacs gebruikt. Via deze applicatie kunnen medische beelden opgenomen en

geregistreerd worden en op die manier functioneert het als hulpmiddel bij het afnemen van

een onderzoek. Naast het nemen en registreren van foto′s kunnen deze ook bewerkt worden:

de afbeelding kan worden bijgesneden en de helderheid ervan aangepast. Voor de registratie

van de foto′s werd een backend ontwikkeld. Bij het inscannen van het polsbandje wordt deze

backend aangeroepen om de patient samen met zijn onderzoek op te halen van de server.

Zodra de registratie voltooid is, bestaat de mogelijkheid om de afbeeldingen te uploaden naar

de server via diezelfde backend. Vervolgens worden de afbeeldingen via een reeds bestaande

tool omgezet naar DICOM-bestanden om deze beschikbaar te stellen in het PACS (Picture

Archiving and Communications System).

Er werden vier verschillende technologien (iOS, PhoneGap, Android, HTML5) besproken

en de performantie ervan met elkaar vergeleken. iOS bleek de meest geschikte technologie

voor deze toepassing.

Tot slot wordt de mogelijkheid onderzocht om het inloggen op de iSentTopacs applicatie

te integreren met iPacsOnWeb. iPacsOnWeb werd ontwikkeld door mijn collega-student

Pieter-Jan Van Robays en functioneert als de alternatieve native applicatie van de website

PacsOnWeb [1].

iii

Page 4: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Abstract

The goal of this thesis is to create a mobile application which aims to simplify the everyday

actions of a nurse. Where formerly photos of skin conditions or burns were taken with a

camera and then manually added to the patient record, now the application iSentToPacs is

used. Through this application images can be registered and recorded and in this way it func-

tions as a tool when conducting a medical examination. For the registration of the images

a backend was created. By scanning the wristband of the patient the backend gets called

and returns the patient information with the examination. After registering it is possible

to upload the images by using the same backend. When the images are fully uploaded an

existing tool can convert these images to DICOM-files which can then be stored in the PACS

(Picture Archiving and Communications System).

Four different technologies (iOS, PhoneGap, Android, HTML5) were analyzed and their per-

formance was compared. iOS showed the most promising results.

Finally, the possibility to integrate the login part of iSentToPacs and iPacsOnWeb was exa-

mined. iPacsOnWeb is an application developed by my fellow student Pieter-Jan Van Robays

and functions as an alternative native application for the website PacsOnWeb [1].

iv

Page 5: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Inhoudsopgave

1 Mobiele applicaties 1

1.1 Inleiding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

1.2 Native applicaties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

1.3 Mobiele webapplicaties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

1.4 Hybride applicaties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

1.5 Criteria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

1.5.1 Criteria vanuit het infrastructuur perspectief . . . . . . . . . . . . . . 3

1.5.2 Criteria vanuit het ontwikkelingsperspectief . . . . . . . . . . . . . . . 4

2 Onderzoek van de performantie bij mobiele technologieen 6

2.1 Doelstelling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

2.2 Omschrijving . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

2.3 Uitwerking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

2.3.1 iOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

2.3.2 iOS met OpenCV . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

2.3.3 PhoneGap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

2.3.4 Android . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

2.3.5 HTML5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

2.4 Resultaten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

2.4.1 Resultaat in iOS, iOS met OpenCV, PhoneGap . . . . . . . . . . . . . 18

2.4.2 Resultaat in Android . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

2.4.3 Resultaat in HTML5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

2.5 Conclusie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

3 Applicatie 20

3.1 Doel van de applicatie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

3.2 Authenticatie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

3.2.1 ASP.NET authenticatie . . . . . . . . . . . . . . . . . . . . . . . . . . 21

3.2.2 ASP.NET State Management . . . . . . . . . . . . . . . . . . . . . . . 23

3.2.3 Authenticatie in iOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

3.3 Beveiliging van de applicatie . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

3.3.1 The sandbox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

3.3.2 Beveiliging van de bestanden . . . . . . . . . . . . . . . . . . . . . . . 28

3.3.3 Opslag van de credentials en de pincode . . . . . . . . . . . . . . . . . 29

v

Page 6: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Inhoudsopgave vi

3.3.4 Encryptie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

3.4 Opslag van de data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

3.4.1 NSFileManager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

3.4.2 Lokale database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

3.4.3 Creatie lokale database . . . . . . . . . . . . . . . . . . . . . . . . . . 37

3.5 UIImagePickerController . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

3.5.1 Camera Overlay View . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

3.6 Editeren van afbeeldingen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

3.6.1 PEPhotoCropEditor . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

3.7 Scannen van de barcode/QR-code . . . . . . . . . . . . . . . . . . . . . . . . 43

3.7.1 AVCaptureMetadataOutput . . . . . . . . . . . . . . . . . . . . . . . . 43

3.8 Uploaden van de afbeeldingen . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

3.8.1 Multipart message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

4 Backend 47

4.1 ASP.NET Web API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

4.2 Database model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

4.2.1 PostFormData methode . . . . . . . . . . . . . . . . . . . . . . . . . . 49

5 Integratie van de applicaties 53

5.1 Huidige situatie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

5.2 Probleemstelling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

5.3 Delen van logingegevens tussen applicaties . . . . . . . . . . . . . . . . . . . . 53

5.4 Delen van andere data tussen applicaties . . . . . . . . . . . . . . . . . . . . . 54

5.4.1 Webservice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

5.4.2 Custom URL Schemes . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

5.4.3 UIPasteBoard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

5.5 Conclusie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

A OpenCV linken met iOS 57

B Aangepaste keychain wrapper 58

C Herstellen van de orientatie van een afbeelding 63

Page 7: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Lijst van figuren

2.1 Core image in relatie met het besturingssysteem . . . . . . . . . . . . . . . . 7

2.2 PhoneGap build . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2.3 Totaal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

2.4 Cirkeldiagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

2.5 Timeline . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

3.1 Forms Authentication Control Flow . . . . . . . . . . . . . . . . . . . . . . . 23

3.2 Sandbox indeling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

3.3 Lokaal database model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

3.4 Zonder overlay view . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

3.5 Met overlay view . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

4.1 Server database model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

vii

Page 8: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Listings

2.1 Basisaanpak om een filter toe te passen . . . . . . . . . . . . . . . . . . . . . 8

2.2 Real-time aanpak om een filter toe te passen . . . . . . . . . . . . . . . . . . 8

2.3 Actiemethode UISlider . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

2.4 Asynchroon uitvoeren van de aanpassing . . . . . . . . . . . . . . . . . . . . . 10

2.5 Aanpassen van de helderheid . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

2.6 UIImage * naar Mat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

2.7 Mat naar UIImage * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

2.8 Actie methode UISlider OpenCV . . . . . . . . . . . . . . . . . . . . . . . . . 12

2.9 Toevoegen touch events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2.10 getPos functie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

2.11 Brightness filter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

2.12 Brightness filter android . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

2.13 addValue methode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

2.14 onSeekBarChangeListener . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

3.1 ValidateUser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

3.2 Creatie van een NSURLConnection . . . . . . . . . . . . . . . . . . . . . . . . 25

3.3 Creatie van een NSURLSessie . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

3.4 Keychainitem toevoegen aan de keychain . . . . . . . . . . . . . . . . . . . . 31

3.5 Paswoord of pincode ophalen uit de keychain . . . . . . . . . . . . . . . . . . 32

3.6 Encryptie van data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

3.7 Decryptie van data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

3.8 Data wegschrijven naar een bestand . . . . . . . . . . . . . . . . . . . . . . . 34

3.9 Ophalen van een bestand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

3.10 Creatie database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

3.11 Singleton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

3.12 Creatie tabellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

3.13 Initialisatie van de UIImagePickerController . . . . . . . . . . . . . . . . . . . 39

3.14 Nemen van een foto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

3.15 PECropView . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

3.16 Initialisatie capture session . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

viii

Page 9: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Listings ix

3.17 NSURLSession aanmaken met juiste configuratie . . . . . . . . . . . . . . . . 45

3.18 Opbouw multipart body . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

4.1 PostFormData methode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

4.2 Afbeelding aan een bestaande sessie toevoegen . . . . . . . . . . . . . . . . . 51

4.3 Nieuwe sessie aanmaken en afbeelding toevoegen . . . . . . . . . . . . . . . . 52

A.1 Build OpenCV framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

A.2 Import OpenCV . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

B.1 Aangepaste keychain wrapper . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

C.1 Herstellen orientatie afbeelding . . . . . . . . . . . . . . . . . . . . . . . . . . 63

Page 10: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 1

Mobiele applicaties

1.1 Inleiding

Smartphones vind je in alle kleuren en formaten. Ze combineren functies zoals een media-

speler, camera en GPS met touchscreens en genieten een sterk groeiende populariteit. Smart-

phones laten toe om gebruik te maken van innovatieve mobiele informatiesystemen die ook

wel apps genoemd worden. De smartphonemarkt is door het grote aanbod van platformen

echter zeer gefragmenteerd en verandert voortdurend. Elk van deze platformen verschillen

van elkaar waardoor software ontwikkelaars die een breed publiek willen bereiken bijna ge-

noodzaakt zijn om voor elk platform afzonderlijk te ontwikkelen. Gelukkig zijn er ook nog

andere mogelijkheden. Zo kunnen ontwikkelaars ervoor kiezen om een hybride applicatie

of een mobiele webapplicatie te maken zodat een grotere groep van platformen kan worden

bereikt met dezelfde applicatie.

In de secties die volgen, worden enkele verschillende mogelijkheden besproken om mobiele

applicaties te maken. De laatste sectie behandelt de criteria waarmee men rekening moet

houden bij het kiezen tussen de varianten.

1

Page 11: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 1. Mobiele applicaties 2

1.2 Native applicaties

Een native applicatie wordt gemaakt voor een specifiek platform en maakt gebruik van een

Software Development Kit (SDK) en de frameworks voor dit platform. Hierdoor is de appli-

catie platformgebonden. Android wordt bijvoorbeeld geprogrammeerd in Java en hardware

specifieke functies worden aangesproken via het framework van Android. IOS daarentegen

wordt geprogrammeerd in Objective-C en gebruikt de frameworks van Apple. Wanneer meer-

dere platformen ondersteund moeten worden, is men genoodzaakt om voor elk platform een

nieuwe native applicatie te ontwikkelen. In tegenstelling tot mobiele webapplicaties en hy-

bride applicaties is de ontwikkeling van native applicaties dus alles behalve cross-platform.

Native applicaties hebben tot voordeel dat ze sneller werken dan hybride applicaties en mo-

biele webapplicaties en meer toegang hebben tot specifieke hardwarefuncties.

1.3 Mobiele webapplicaties

Mobiele webapplicaties (Web apps) geımplementeerd met HTML5, CSS en JavaScript maken

gebruik van de browser als runtime environment en vertrouwen daarbij op de ondersteuning

van browsers op de mobiele platformen. Deze methode maakt dus een website die geop-

timaliseerd wordt voor mobiele toestellen. De optimalisatie houdt hierbij rekening met de

verschillende groottes van de schermen en de gebruikersfilosofie van de verschillende mobiele

toestellen. Mobiele webapplicaties hebben echter niet altijd toegang tot de verschillende toe-

stelspecifieke hardwarefuncties. Gelukkig biedt HTML5 voor sommige hardwarefuncties een

oplossing. Webapplicaties steunen op de browser van het toestel en hebben dus voor de uit-

werking geen nood aan frameworks. Doch bestaan er een aantal frameworks die het creeren

van mobiele webapplicaties en de gebruikersinterface sterk kunnen vereenvoudigen. Enkele

mogelijkheden zijn bijvoorbeeld:

• jQuery Mobile

• Sencha Touch

• The M Project

• WINK (Webapp INovation Kit). . .

Mobiele webapplicaties zien er doorgaans uit als gewone websites en verschillen van native

applicaties in uitzicht en gedrag die worden geleverd door de native UI elementen.

Page 12: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 1. Mobiele applicaties 3

1.4 Hybride applicaties

Hybride applicaties zijn ontstaan als een combinatie van webtechnologieen en native func-

tionaliteit om het gebrek aan toegang tot de toestelspecifieke hardwarefuncties te verhelpen.

Daarvoor maken ze gebruik van webtechnologieen. Hun runtime environment bestaat voor

het grootste deel uit een web rendering engine die verpakt is in een native engine. De source

code van de hybride applicatie gebruikt dezelfde technologie als de mobiele webapplicaties,

maar verschilt in de toegang tot de platformspecifieke hardwarefuncties. Elke aanroep van

hardwarefuncties wordt afgehandeld door de native verpakker. In tegenstelling tot mobiele

webapplicaties, zijn hybride applicaties native verpakt en kunnen deze dus ook geınstalleerd

worden zoals een native applicatie. Hoewel deze applicaties de look and feel hebben van een

mobiele webapplicatie, hebben ze een grotere toegang tot de hardware specifieke functies van

het toestel. Voor de uitwerking van een hybride applicatie is het meest belovende framework

PhoneGap.

1.5 Criteria

Wanneer de keuze moet worden gemaakt tussen een native, hybride of mobiele webapplicatie

is het belangrijk om eerst enkele criteria na te gaan en op basis van deze criteria een keuze

te maken. Om een beter overzicht te geven, worden de criteria in het artikel ”Evaluating

Cross-Platform Development Approaches for Mobile Applications”[2] opgedeeld volgens het

infrastructuur- en ontwikkelingsperspectief. Het infrastructuurperspectief bevat de criteria die

rekening houden met the life-cycle van de applicatie, het gebruik en de functionaliteit ervan.

Het ontwikkelingsperspectief omvat de criteria die gerelateerd zijn aan het ontwikkelingsproces

van de applicatie. Testen, debuggen en development tools zijn hier enkele voorbeelden van.

1.5.1 Criteria vanuit het infrastructuur perspectief

• Licentie en kosten

Dit criterium onderzoekt of het gebruikte framework gedistribueerd is als gratis software

of open source, onder welke licentie het gepubliceerd is en of de ontwikkelaar vrij is om

de commerciele software te ontwikkelen.

• Ondersteunde platformen

Bij dit criterium wordt nagegaan of de applicatie op elk platform even goed ondersteund

wordt en welk platform het belangrijkst is.

• Toegang tot platformspecifieke functies

Er wordt gecontroleerd of er toegang is tot de hardware van het toestel zoals de camera

en de GPS. Ook wordt nagegaan of men toegang heeft tot de contacten van het mobiele

toestel.

Page 13: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 1. Mobiele applicaties 4

• Look and feel

Bij dit criterium wordt er gekeken naar hoe de applicatie eruit ziet. Bij een hybride

applicatie of een mobiele webapplicatie wordt gestreefd naar de look and feel van een

native applicatie.

• Applicatie snelheid

Dit criterium vergelijkt de snelheid van de applicatie tijdens het opstarten en de runtime.

Hoe snel reageert de applicatie op de gebruikersinteractie?

• Distributie

Dit criterium evalueert hoe eenvoudig de applicaties verspreid kunnen worden. Een

mogelijkheid is het gebruik maken van the app store van het mobiele platform.

1.5.2 Criteria vanuit het ontwikkelingsperspectief

• Ontwikkelomgeving

Dit criterium evalueert de functies van de ontwikkelomgeving die typisch geassocieerd

worden met het framework . Er wordt vooral gekeken naar de beschikbare tools (IDE,

debugger en emulator). Ook functies zoals auto completion en automated testing zijn

belangrijk.

• GUI ontwerp

Dit criterium behandelt het creeren van de gebruikersinterface en de beschikbare soft-

ware ondersteuning. Een onafhankelijke WYSIWYG (What You See Is What You Get)

editor en de mogelijkheid om de gebruikersinterface te ontwikkelen en testen zonder

telkens opnieuw te hoeven deployen zijn wenselijk.

• Eenvoud van ontwikkeling

Hierbij wordt de kwaliteit van de API en de documentatie geevalueerd. Er wordt zowel

gekeken naar beschikbare codevoorbeelden als de gedocumenteerde code.

• Onderhoudbaarheid

De Lines Of Code indicator wordt gebruikt om de onderhoudbaarheid te evalueren. De

keuze van deze indicator is gebaseerd op de veronderstelling dat een applicatie eenvou-

diger te ondersteunen is wanneer de applicatie minder lines of code bevat.

• Schaalbaarheid

De schaalbaarheid is gebaseerd op hoe goed grote ontwikkelaarteams projecten kunnen

uitvoeren gebruik makend van eenzelfde framework .

• Opportuniteiten voor verdere ontwikkeling

Dit criterium gaat na in welke mate de geschreven code voor een bepaald framework

hergebruikt kan worden wanneer later beslist wordt om een andere aanpak te hanteren.

Page 14: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 1. Mobiele applicaties 5

• Snelheid en kost van de ontwikkeling

Dit criterium evalueert de snelheid van het ontwikkelingsproces en de factoren die

straightforward development verhinderen.

Page 15: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 2

Onderzoek van de performantie bij

mobiele technologieen

2.1 Doelstelling

De doelstelling van het onderzoek bestaat uit het bepalen van de technologie die het best

gebruikt wordt voor de uitwerking van de masterproefapplicatie. Om te bepalen welke tech-

nologie het meest geschikt is, wordt de performantie van de verschillende technologieen met

elkaar vergeleken. Dit onderzoek wordt vooraf uitgevoerd en staat los van de applicatie die

in deze masterproef werd ontwikkeld. Afhankelijk van het resultaat van het onderzoek en de

voorkeur van het bedrijf, wordt vervolgens een technologie gekozen voor de uitwerking van de

masterproefapplicatie.

2.2 Omschrijving

Voor het onderzoek worden in verschillende technologieen een aantal applicaties gemaakt. De

verschillende technologieen zijn:

1. iOS

2. PhoneGap

3. Android

4. HTML5

De applicatie zal een afbeelding op het scherm tonen en toelaten dat de helderheid van deze

afbeelding real time kan worden aangepast. Voor elke technologie wordt bij de uitvoering

van de mobiele applicatie op het toestel het aantal frames per seconde bepaald. Het aantal

frames per seconde geeft aan hoe snel de technologie zijn beelden kan aanpassen. Hoe hoger

6

Page 16: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 2. Onderzoek van de performantie bij mobiele technologieen 7

deze snelheid, hoe beter. Dit bepaalt in grote mate welke technologie het best gebruikt wordt

voor de uitwerking van de masterproefapplicatie.

2.3 Uitwerking

2.3.1 iOS

De applicatie is een single view application. Dit betekent dat de applicatie slechts een scherm

heeft. Het scherm bevat een afbeelding view (UIImageView) en een schuifbalk (UISlider).

De afbeelding view bevat de afbeelding die op het scherm getoond moet worden. Bij het

verschuiven van de schuifbalk moet de helderheid van de afbeelding aangepast worden. Om

te begrijpen hoe de afbeelding aangepast wordt, moeten er enkele begrippen zoals de Core

Image Context en de Core Image Filter worden uitgelegd.

Core Image Context

Core Image [3] is een beeldverwerkende technologie die ontworpen is om real-time aanpassin-

gen te maken aan afbeeldingen of videobeelden. Core Image kan omgaan met afbeeldingen

van verschillende datatypes uit de Core Graphics, Core Video en de Image I/O frameworks.

Zoals in Figuur 2.1 zichtbaar is, kunnen op elk van deze datatypes filters toegepast worden.

De berekeningen die deze filters uitvoeren, kunnen via de GPU of de CPU en verder hoeft

men zich geen zorgen te maken over de low level details van OpenGL of OpenGL ES die

onderliggend door Core Image gebruikt worden.

Figuur 2.1: Core image in relatie met het besturingssysteem

Page 17: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 2. Onderzoek van de performantie bij mobiele technologieen 8

De basisaanpak om een afbeelding te bewerken, wordt getoond in Listing 2.1. De aanpak

bestaat uit vijf stappen.

Listing 2.1: Basisaanpak om een filter toe te passen

1 CIContext *context = [CIContext contextWithOptions:nil];

2 CIImage *image = [CIImage imageWithContentsOfURL:myURL];

3 CIFilter *filter = [CIFilter filterWithName:@"CISepiaTone"];

4 [filter setValue:image forKey:kCIInputImageKey];

5 [filter setValue:@0.8f forKey:kCIInputIntensityKey];

6 CIImage *result = [filter valueForKey:kCIOutputImageKey];

7 CGRect extent = [result extent];

8 CGImageRef cgImage = [context createCGImage:result fromRect:extent];

Eerst wordt er een CIContext (Core Image Context) aangemaakt. De volgende stap bestaat uit

het maken van een CIImage (Core Image Image) object van de afbeelding dat hier afkomstig

is van myURL. Vervolgens moet er een filter object aangemaakt worden om deze te kunnen

toepassen op de afbeelding. Afhankelijk van het soort CIFilter zal de CISepiaTone op de derde

lijn iets anders weergeven. Lijn zes geeft het resultaat weer en om dit op het scherm te tonen

of op te slaan, wordt hiervan de CGImageRef (Core Graphics Image Reference) genomen zoals

te zien is op lijn acht.

De aanpak voor real-time image manipulatie ziet er als volgt uit:

Listing 2.2: Real-time aanpak om een filter toe te passen

1 EAGLContext *myEAGLContext = [[EAGLContext alloc]

2 initWithAPI:kEAGLRenderingAPIOpenGLES2];

3 NSDictionary *options = @{ kCIContextWorkingColorSpace : [NSNull null] };

4 CIContext *myContext = [CIContext contextWithEAGLContext:myEAGLContext

5 options:options];

6 CIImage *image = [CIImage imageWithContentsOfURL:myURL];

7 CIFilter *filter = [CIFilter filterWithName:@"CIColorControls"];

8 [filter setValue:image forKey:kCIInputImageKey];

9 [filter setValue:@0.8f forKey:kCIInputIntensityKey];

10 CIImage *result = [filter valueForKey:kCIOutputImageKey];

11 CGRect extent = [result extent];

12 CGImageRef cgImage = [myContext createCGImage:result fromRect:extent];

Wanneer er nood is aan real-time performance is het aangeraden om een CIContext te maken

van een EAGLContext. Dit heeft als voordeel dat de gerenderde afbeelding op de GPU blijft

en nooit gekopieerd wordt naar het CPU geheugen. Hoe een EAGLContext wordt gemaakt, is

te zien in Listing 2.2 op de eerste lijn. Om de performantie nog beter te maken, raadt

Apple aan om het color management uit te schakelen. Color management zorgt voor extra

nauwkeurigheid en vereist extra berekeningen bij het toepassen van een filter. Om over de

hoogste performantie te beschikken, wordt dit dus het best uitgeschakeld. Dit uitschakelen

kan door null mee te geven aan de working color space zoals aangegeven in Listing 2.2 op lijn

Page 18: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 2. Onderzoek van de performantie bij mobiele technologieen 9

drie. Vervolgens wordt een CIContext van de EAGLContext gemaakt met de opties ingesteld op

null. Net zoals in de basisaanpak bestaat de volgende stap uit het maken van een CIFilter.

Afhankelijk van het soort filter object dat gemaakt wordt, zal er een andere bewerking op

de afbeelding worden toegepast. Meer informatie over de verschillende soorten filters vind

je terug in de Core Image Filter Reference [4]. Om de helderheid van een afbeelding aan te

passen is er nood aan een CIColorControls filter object. Zodra het filter object is aangemaakt,

kan het gebruikt worden om de afbeelding aan te passen. De bedoeling is dat de afbeelding

wordt aangepast bij verschuivingen van de schuifbalk. Het is dus vanzelfsprekend dat de

afbeelding wordt aangepast in de actiemethode van de schuifbalk. Dit is echter niet efficient

omdat het bewerken van de afbeelding in de actiemethode de main thread blokkeert waardoor

de schuifbalk en de afbeelding niet vloeiend aangepast worden. Een oplossing hiervoor is het

bewerken van de afbeelding in een andere thread . Apple beschikt echter over een hulpmiddel

dat veel eenvoudiger is dan het zelf creeren en afhandelen van threads. Dit hulpmiddel wordt

Dispatch Queues [5] genoemd en laat toe om een blok code asynchroon uit te voeren waardoor

de main thread niet geblokkeerd wordt.

Onderstaande methode stelt de actiemethode van de schuifbalk voor. Deze methode wordt

aangeroepen zodra de schuifbalk wordt aangepast. Deze methode roept op zijn beurt de

methode adjustWithValue op die de waarde van de schuifbalk mySlider.value als parameter

meekrijgt.

Listing 2.3: Actiemethode UISlider

1 - (IBAction)changeImage:(id)sender {

2 [self adjustWithValue:mySlider.value];

3 }

De code in Listing 2.4 zorgt ervoor dat de aanpassing van de afbeelding asynchroon wordt

uitgevoerd. De variabele m queue stelt hier een dispatch queue voor verschillend van de main

queue van de applicatie. Met de methode addOperationWithBlock wordt een nieuwe taak aan de

dispatch queue toegevoegd. De taak wordt in blokvorm meegegeven en heeft twee functies.

Vooreerst berekent de code de nieuwe afbeelding door de methode adjustBrightness aan te

roepen. Ten tweede past het de afbeelding aan op het scherm, maar dan wel asynchroon en

op de main queue.

Page 19: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 2. Onderzoek van de performantie bij mobiele technologieen 10

Listing 2.4: Asynchroon uitvoeren van de aanpassing

1 - (void)adjustWithValue:(CGFloat)value

2 {

3 [m_queue cancelAllOperations];

4 [m_queue addOperationWithBlock:^

5 {

6 UIImage *adjustedImage = [self adjustBrightness];

7 dispatch_async(dispatch_get_main_queue(),^

8 {

9 imageView.image = adjustedImage;

10 });

11 }];

12 }

De methode adjustBrightness, die hieronder wordt weergegeven, is verantwoordelijk voor het

toepassen van de filter op de afbeelding. Zoals te zien is, wordt eerst de waarde van de

brightnessFilter ingesteld met de waarde mySlider.value van de schuifbalk. Vervolgens wordt

de brightnessFilter toegepast op de afbeelding, wat een nieuwe afbeelding outputImage oplevert.

Tot slot wordt uit deze outputImage een UIImage bepaald die geretourneerd wordt om op het

scherm te tonen.

Listing 2.5: Aanpassen van de helderheid

1 -(UIImage *) adjustBrightness{

2 [brightnessFilter setValue:[NSNumber numberWithFloat:mySlider.value ]

3 forKey: @"inputBrightness"];

4 outputImage = [brightnessFilter outputImage];

5 cgiig = [context createCGImage:outputImage fromRect:[outputImage extent]];

6 newUIImage = [UIImage imageWithCGImage:cgiig];

7 CGImageRelease(cgiig);

8 return newUIImage;

9 }

2.3.2 iOS met OpenCV

OpenCV is een open source library geschreven in C++ die gebruikt wordt voor beeldverwer-

king en ontworpen is met de focus op real-time toepassingen. Omdat het ontworpen is voor

real-time toepassingen komt deze technologie zeker in aanmerking voor het onderzoek. Meer

informatie over hoe OpenCV gelinkt kan worden met iOS is te zien in bijlage A.

Uitwerking met OpenCV

Omdat er gebruik gemaakt wordt van OpenCV moet de afbeelding eerst geconverteerd worden

van een UIImage * naar een Mat. Wanneer de afbeelding bewerkt is, moet ze terug geconver-

teerd worden naar een UIImage * om op het scherm getoond te worden. Hoe dit moet, wordt

Page 20: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 2. Onderzoek van de performantie bij mobiele technologieen 11

duidelijker in de onderstaande methodes. Voor meer informatie hierover zie [6].

Listing 2.6: UIImage * naar Mat

1 - (Mat)cvMatFromUIImage:(UIImage *)inputImage{

2 CGColorSpaceRef colorSpace = CGImageGetColorSpace(inputImage.CGImage);

3 CGFloat cols = inputImage.size.width;

4 CGFloat rows = inputImage.size.height;

5 Mat cvMat(rows, cols, CV_8UC4);

6 CGContextRef contextRef =

7 CGBitmapContextCreate(cvMat.data, cols, rows, 8, cvMat.step[0], colorSpace,

8 kCGImageAlphaNoneSkipLast | kCGBitmapByteOrderDefault);

9 CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), inputImage.CGImage);

10 CGContextRelease(contextRef);

11 CGColorSpaceRelease(colorSpace);

12 return cvMat;

13 }

Om een UIImage * afbeelding om te zetten naar een Mat afbeelding wordt eerst een Mat object

aangemaakt met dezelfde grootte van de UIImage *. Vervolgens wordt de methode

CGBitmapContextCreate aangeroepen waaraan een aantal parameters worden meegegeven zoals

een pointer naar de data (cvMat.data), de breedte en de hoogte van de afbeelding, het aantal

bits per component en het aantal bytes per rij. Deze methode geeft een bitmap context

terug waarnaar de cvMat.data verwijst. De methode CGContextDrawImage zorgt ervoor dat de

afbeelding naar deze context wordt getekend. Tot slot worden de referenties vrijgegeven en

wordt de afbeelding in het nieuwe formaat geretourneerd.

Listing 2.7: Mat naar UIImage *

1 -(UIImage *)UIImageFromCVMat:(cv::Mat)cvMat

2 {

3 NSData *data = [NSData dataWithBytes:cvMat.data length:

4 cvMat.elemSize()*cvMat.total()];

5 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

6 CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);

7 CGImageRef imageRef =

8 CGImageCreate(cvMat.cols, cvMat.rows, 8, 8 * cvMat.elemSize(), cvMat.step[0],

9 colorSpace, kCGImageAlphaNone|kCGBitmapByteOrderDefault, provider, NULL,

10 false, kCGRenderingIntentDefault);

11 UIImage *finalImage = [UIImage imageWithCGImage:imageRef];

12 CGImageRelease(imageRef);

13 CGDataProviderRelease(provider);

14 CGColorSpaceRelease(colorSpace);

15 return finalImage;

16 }

In Listing 2.7 wordt er omgekeerd te werk gegaan. Bij deze methode wordt een Mat afbeelding

getransformeerd naar een UIImage * afbeelding. De methode CGImageCreate creeert een bitmap

Page 21: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 2. Onderzoek van de performantie bij mobiele technologieen 12

afbeelding op basis van de data geleverd door de data provider . Om de provider te verkrij-

gen, wordt de methode CGDataProviderCreateWithCFData aangeroepen. Deze methode krijgt als

parameter de data van de Mat afbeelding mee. Naast de data provider heeft de CGImageCreate

methode ook nog de breedte, hoogte, aantal bits per component en aantal bytes per rij nodig.

Tot slot worden opnieuw de referenties vrijgegeven en wordt een UIImage * afbeelding gere-

tourneerd.

Nu de afbeelding het juiste formaat heeft, kan deze bewerkt worden door gebruik te maken

van OpenCV. Uiteraard gebeurt dit opnieuw in de actiemethode van de schuifbalk en in een

andere dispatch queue zodat de gebruikersinterface niet blokkeert bij het aanpassen van de

afbeelding. Een afbeelding aanpassen in OpenCV kan op de volgende manier:

Listing 2.8: Actie methode UISlider OpenCV

1 - (IBAction)sliderChanged:(id)sender {

2 [m_queue cancelAllOperations];

3 [m_queue addOperationWithBlock:^

4 {

5 binaryMat = inputMat +

6 Scalar(binarySlider.value,binarySlider.value,binarySlider.value);

7 binary = [self UIImageFromCVMat:binaryMat];

8 dispatch_async(dispatch_get_main_queue(),^

9 {

10 imageView.image = binary;

11 });

12 }];

13 }

InputMat stelt de originele afbeelding voor die aangepast moet worden. Voor elke pixel van

inputMat wordt er voor de RGB waarden telkens de verschuiving van de schuifbalk bij opgeteld.

Dit levert dan de nieuwe afbeelding op genaamd binaryMat. Deze moet vervolgens worden

omgezet naar een UIImage * met de UIImageFromCVMat methode. Tot slot wordt de UIImage op

het scherm geplaatst.

2.3.3 PhoneGap

Wat is PhoneGap?

Applicaties maken voor elk soort toestel vereist kennis van verschillende frameworks en pro-

grammeertalen. PhoneGap [7] biedt hiervoor een oplossing door gebruik te maken van de

webstandaarden om webapplicaties en mobiele toestellen te overbruggen. De gebruikersinter-

face in een PhoneGap applicatie is gemaakt met HTML, CSS en JavaScript. De gebruikers-

interface is eigenlijk een webbrowser die 100% van de breedte en 100% van de hoogte van het

toestel inneemt. Dit wordt ook wel een chrome-less browser genoemd. Het laat de HTML

Page 22: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 2. Onderzoek van de performantie bij mobiele technologieen 13

inhoud zien zonder het scherm van de browser te tonen. PhoneGap biedt ook een Application

Programming Interface aan die toegang geeft tot het native besturingssysteem via JavaScript.

Tot slot wordt de applicatie gebuild naar een native platform.

Figuur 2.2: PhoneGap build

PhoneGap applicatie

Een scherm maken voor een PhoneGap applicatie kan eenvoudigweg door het aanmaken

van een HTML pagina met bijhorende CSS en JavaScript. PhoneGap beschikt echter niet

over frameworks om afbeeldingen te bewerken. Gelukkig kan dit verwezenlijkt worden met

JavaScript. De website van HTML5 rocks [8] heeft hierover een leerrijke tutorial. Een afbeel-

ding op het scherm tonen, kan met de HTML img-tag, maar voor deze specifieke applicatie

wordt de afbeelding in een HTML canvas-tag weergegeven. Met touch events kan de helder-

heid van de afbeelding aangepast worden. Op de afbeelding worden twee events geplaatst:

een touchstart en een touchmove event.

Listing 2.9: Toevoegen touch events

1 canvas.addEventListener(’touchstart’,function(evt){

2 evt.preventDefault();

3 previous = getMousePos(canvas,evt);

4 },false);

5 canvas.addEventListener(’touchmove’,getPos,false);

Bij het aanroepen van het touchstart event wordt het coordinaat van de huidige positie binnen

het canvas opgehaald. Vervolgens wordt tijdens de verplaatsing over de afbeelding telkens

het touchmove event getriggered . Deze roept de functie getPos aan, die verantwoordelijk is voor

het berekenen van de verplaatsing en het hertekenen van de afbeelding op het canvas.

Page 23: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 2. Onderzoek van de performantie bij mobiele technologieen 14

Listing 2.10: getPos functie

1 function getPos(evt){

2 evt.preventDefault();

3 var pos = getMousePos(canvas,evt);

4 var difference = pos.x-previous.x;

5 brighten(difference);

6 }

7 function getMousePos(canvas,evt){

8 evt.preventDefault();

9 return {

10 x: evt.changedTouches[0].pageX,

11 y: evt.changedTouches[0].pageY

12 }

13 }

Op het einde van de getPos functie wordt de brighten functie aangeroepen. Met deze functie

wordt een adjustement waarde meegegeven. Dit is de waarde waarmee de helderheid van de

afbeelding wordt aangepast.

Listing 2.11: Brightness filter

1 function brighten(adjustment){

2 var image = document.getElementById(’image’);

3 var canvas = document.getElementById(’canvasImage’);

4 var ctx = canvas.getContext(’2d’);

5 ctx.drawImage(image, 0, 0);

6 var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);

7 var d = imageData.data;

8 for (var i=0; i<d.length; i+=4) {

9 d[i] += adjustment;

10 d[i+1] += adjustment;

11 d[i+2] += adjustment;

12 }

13 ctx.putImageData(imageData,0,0);

14 }

Eerst wordt de afbeelding opgehaald en in het canvas getekend. Vervolgens wordt bij elke

pixel van de afbeelding de adjustement waarde opgeteld. De methode sluit af met het tekenen

van de nieuwe afbeelding in het canvas.

Page 24: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 2. Onderzoek van de performantie bij mobiele technologieen 15

2.3.4 Android

Layout

In een Android applicatie worden de schermen voorgesteld door XML bestanden. De test-

applicatie bevat twee XML bestanden:

1. activity main.xml

2. fragment main.xml

De activity main view is het hoofdscherm waarop verschillende fragmenten getoond kunnen

worden. De fragment main view bevat de afbeelding en een schuifbalk om de helderheid

van de afbeelding aan te passen. Net zoals PhoneGap beschikt Android niet over een filter

framework . Om de helderheid aan te passen, wordt dus opnieuw pixel per pixel aangepast.

Hoe dit gebeurt, is te zien in Listing 2.12.

Listing 2.12: Brightness filter android

1 public static Bitmap doBrightness(Bitmap src, int value) {

2 int width = src.getWidth();

3 int height = src.getHeight();

4 Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());

5 int A, R, G, B;

6 int pixel;

7 for (int x = 0; x < width; ++x) {

8 for (int y = 0; y < height; ++y) {

9 pixel = src.getPixel(x, y);

10 A = Color.alpha(pixel);

11 R = Color.red(pixel);

12 G = Color.green(pixel);

13 B = Color.blue(pixel);

14 R = addValue(R,value);

15 G = addValue(G,value);

16 B = addValue(B,value);

17 bmOut.setPixel(x, y, Color.argb(A, R, G, B));

18 }

19 }

20 return bmOut;

21 }

De bovenstaande methode krijgt de originele afbeelding mee in bitmap formaat en de waarde

van de schuifbalk. Voor elke pixel worden de afzonderlijke RGB waarden aangepast door er

de waarde van de schuifbalk bij op te tellen. Hiervoor wordt de methode in Listing 2.13

gebruikt. Deze methode zorgt er tevens ook voor dat men niet lager dan 0 of hoger dan 255

kan gaan. Tot slot geeft de methode de nieuwe afbeelding weer.

Listing 2.13: addValue methode

Page 25: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 2. Onderzoek van de performantie bij mobiele technologieen 16

1 int addValue(int colorValue, int value){

2 colorValue += value;

3 if(colorValue > 255){

4 colorValue = 255;

5 } else if(colorValue < 0){

6 colorValue = 0;

7 }

8 return colorValue;

9 }

Omdat de filtermethode zou worden aangeroepen bij het aanpassen van de schuifbalk, moet

er een event worden toegekend aan de schuifbalk. Een event toekennen kan op de volgende

manier:

Listing 2.14: onSeekBarChangeListener

1 SeekBar seekBarBrightness = (SeekBar) rootView.getRootView().findViewById(R.id.seekBar1);

2 seekBarBrightness.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

3 @Override

4 public void onProgressChanged(SeekBar arg0,int progress, boolean arg2) {

5 Bitmap newBitMap = doBrightness(bitMap, progress);

6 imageView.setImageBitmap(newBitMap);

7 }

8 });

De schuifbalk ophalen kan via de findViewById() methode. Aan deze methode wordt het id van

de schuifbalk meegegeven. Vervolgens wordt er een onSeekBarChangeListener event op de schuif-

balk geplaatst. Zodra er interactie is met de schuifbalk zal dit event aangeroepen worden.

Binnen dit event wordt de methode doBrightness aangeroepen die de nieuwe afbeelding zal

maken. Tot slot wordt de nieuwe afbeelding op het scherm geplaatst.

2.3.5 HTML5

Voor de mobiele webapplicatie wordt een HTML5 pagina aangemaakt net zoals bij de Phone-

Gap applicatie. Om de helderheid van de afbeelding aan te passen, kan dezelfde JavaScript

functie als bij de PhoneGap applicatie gebruikt worden. Alvorens de mobiele webapplicatie

getest kan worden, moet er een webserver geınstalleerd worden op de computer. Vervolgens

kan via het mobiele toestel naar het IP-adres van de computer genavigeerd worden waarop

de mobiele webapplicatie gehost wordt. Als webserver werd er gekozen voor Apache [9]. Om

de mobiele webapplicatie hierop te publiceren, volstaat het om de indexpagina samen met

de bijbehorende afbeelding in de volgende map te plaatsen: C:\Program Files (x86)\Apache

Group\Apache2\htdocs.

Page 26: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 2. Onderzoek van de performantie bij mobiele technologieen 17

2.4 Resultaten

De resultaten voor de iOS, iOS met OpenCV en PhoneGap kunnen bepaald worden via xcode.

Xcode beschikt over een aantal Developer Instruments. Deze instrumenten kunnen gebruikt

worden om de performantie van een applicatie te meten. Een van de mogelijkheden is bij-

voorbeeld het meten van de grafische performantie. Dit kan gedaan worden via het OpenGL

Es Driver instrument. Wanneer alles juist is ingesteld, wordt de test gestart en het aantal

frames per seconde geregistreerd terwijl er gebruikersinteractie is. De technologie die het best

presteert en dus het hoogste aantal frames per seconde geeft bij abnormaal gebruik is dan

ook de beste keuze om er de masterproefapplicatie in uit te werken. Met abnormaal gebruik

wordt bedoelt dat de schuifbalk heel snel heen en weer wordt bewogen zodat de applicatie de

gebruikersinteractie niet kan volgen.

Om het aantal frames per seconde te meten van een Android applicatie bestaat geen

developer instrument zoals bij iOS. Dit moet dus op een andere manier gebeuren. Een

mogelijkheid is het downloaden van een applicatie uit de google play store genaamd FPS

Meter [10]. Deze applicatie geeft visueel weer wat het aantal frames per seconde is tijdens

het gebruik van de applicatie. Jammer genoeg heeft deze applicatie geen historiek van de

gemeten waarden, waardoor dit dus enkel visueel kan worden gemeten. FPS Meter vereist

wel dat het Android toestel geroot is. Voor meer informatie over het rooten van een Android

toestel zie deze site [11].

De performantie van een HTML5 applicatie kan worden gemeten met behulp van remote

debugging [12]. Remote debugging laat toe dat een geopende webpagina op een mobiel toestel

kan worden onderzocht via de computer. Om aan remote debugging te doen, moeten er een

aantal instellingen gebeuren op het Android toestel.

1. Enable USB debugging

Op Android 4.2 en nieuwere versies zitten de ontwikkelaarsinstellingen verscholen. Om

deze beschikbaar te maken, gaat u naar Settings > About phone en klikt u 7 maal op het

Build number . Keer vervolgens terug naar het vorige scherm waar nu de ontwikkelaars-

instellingen tab zichtbaar is. Op Android 4.0 en 4.1 vindt u de ontwikkelaarsinstellingen

bij Settings > Developer options

2. Verbind uw toestel via USB met de computer.

3. Surf in de chrome browser vervolgens naar about:inspect en zorg ervoor dat Discover

USB Devices staat aangevinkt.

4. Accepteer vervolgens de computer op het mobiele toestel en vink Always allow from this

computer aan.

Page 27: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 2. Onderzoek van de performantie bij mobiele technologieen 18

5. Open de mobiele webapplicatie op uw mobiel toestel.

6. U zal nu de link van de mobiele webapplicatie zien verschijnen op de about:inspect

pagina op uw computer. Deze kan vervolgens geınspecteerd worden met de tools van

google chrome.

Het aantal frames per seconde kan worden teruggevonden onder de Frames tab bij de chrome

developer tools. Door op record te klikken zal het aantal frames per seconde bijgehouden

worden tot er gestopt wordt met meten.

2.4.1 Resultaat in iOS, iOS met OpenCV, PhoneGap

Figuur 2.3: Totaal

2.4.2 Resultaat in Android

Doordat de meting op het Android toestel enkel visueel kan, is er voor deze technologie geen

grafiek ter beschikking. De applicatie op het Android toestel levert maximaal 46 frames per

seconde.

Page 28: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 2. Onderzoek van de performantie bij mobiele technologieen 19

2.4.3 Resultaat in HTML5

Figuur 2.4: Cirkeldiagram

Figuur 2.5: Timeline

Het bovenstaande cirkeldiagram geeft het gemiddeld aantal frames per seconde weer over het

volledige tijdsverloop van de meting. Op de tijdslijn kan vastgesteld worden dat het aantal

frames per seconde nooit groter wordt dan 30.

2.5 Conclusie

Zoals verwacht, scoren de native applicaties zeer goed. Ook de iOS applicatie met OpenCV

scoort bijna even goed als de iOS applicatie zelf. Dit is niet abnormaal omdat OpenCV net

zoals Core Image speciaal ontwikkeld is voor real-time beeldverwerking. De mobiele webappli-

catie en de hybride PhoneGap applicatie scoren jammer genoeg bijzonder laag. Dit betekent

dat er nog veel werk aan de winkel is alvorens deze technologieen een alternatief kunnen zijn

voor de native applicaties. Er kan geconcludeerd worden dat er beter gekozen wordt voor

een native applicatie wanneer er nood is aan real-time image processing . Persoonlijk gaat

de voorkeur naar iOS, omdat deze nog net iets beter scoort dan Android. Maar beiden zijn

uiterst geschikt. De keuze voor iOS of Android is afhankelijk van het bedrijf.

Page 29: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3

Applicatie

3.1 Doel van de applicatie

Deze masterproef heeft tot doel een applicatie te maken die medische foto′s kan bewerken

en registreren via een mobiel toestel. Om de foto′s te registreren moet de applicatie de

patient kunnen identificeren. Hiervoor zal de applicatie in staat moeten zijn om de barcode

te scannen van het polsbandje van de patient. De applicatie moet onderstaande functies

kunnen uitvoeren:

1. De verpleegkundige moet zich kunnen authenticeren met zijn gebruikersnaam en pas-

woord.

2. Er moeten foto′s kunnen gemaakt worden van de aandoening.

3. De foto′s moeten aan een sessie kunnen worden toegevoegd en bewerkt of verwijderd

worden.

4. De verpleegkundige moet een identificatie kunnen toekennen aan de sessie door de bar-

code van het polsbandje te scannen of door een opnamenummer in te geven.

5. De gegevens moeten samen met de foto′s kunnen verstuurd worden naar de server,

waar ze omgezet kunnen worden naar DICOM-bestanden om in het PACS opgeslagen

te worden.

3.2 Authenticatie

Enkel een geauthenticeerd verpleegkundige mag toegang hebben tot de applicatie. Daarom

wordt de applicatie voorzien van een authenticatiemechanisme. Het is belangrijk een authen-

ticatiemechanisme te vinden dat zo weinig mogelijk aanpassingen vereist aan het bestaand

systeem. Om het authenticatiemechanisme van de iOS applicatie beter te begrijpen, wordt

eerst besproken hoe authenticatiemechanisme van het bestaande systeem werkt.

20

Page 30: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 21

3.2.1 ASP.NET authenticatie

Pacsonweb is een webapplicatie geschreven in ASP.NET die gebruik maakt van de ASP.NET

authenticatie [13]. ASP.NET implementeert authenticatie aan de hand van authenticatie

providers. De authenticatie providers bevatten de code die nodig is om de credentials van

de aanvrager te authenticeren. Bij Pacsonweb wordt authenticatie geımplementeerd aan de

hand van de Forms Authentication Provider .

Forms Authentication Provider

Om Forms authentication [14] te gebruiken, is er nood aan een loginpagina waar de gebruiker

zijn credentials kan ingeven. Indien de credentials ongeldig zijn, zal de gebruiker opnieuw op

de loginpagina terecht komen. In het andere geval, wordt er een unieke sleutel gegenereerd

die wordt opgeslagen in een cookie. Bij opeenvolgende aanvragen zal de browser deze cookie

meesturen zodat de gebruiker zich niet bij elke aanvraag opnieuw moet authenticeren.

ASPXAUTH Cookie

De cookie die door de server wordt gecreeerd bij de authenticatie wordt een ASPXAUTH

Cookie [15] genoemd. De inhoud van deze cookie is geencrypteerd. Bij elke aanvraag wordt

deze cookie meegestuurd in de HTTP payload . Deze cookie heeft een vervaldatum en wanneer

deze bereikt is, wordt de cookie verwijderd en moet de gebruiker zich opnieuw authenticeren.

Forms Authentication werking

Om een beter inzicht te krijgen in de werking van Forms authentication bekijken we het

communicatieverloop aan de hand van figuur 3.1.

1. De gebruiker vraagt een bestand Default.aspx op.

2. ASP.NET controleert of er een authentication cookie aanwezig is. Wanneer dit niet

gevonden wordt, wordt de gebruiker geredirect naar de loginpagina (Login.aspx) en

krijgt het attribuut RETURNURL de waarde Default.aspx. Het HTTP antwoord van

de server ziet er als volgt uit:

302 Found Location:

http://localhost/FormsAuthTest/login.aspx?RETURNURL=%2fFormAuthTest%2fDefault.aspx

3. De browser vraagt de Login.aspx pagina en geeft de RETURNURL parameter mee in

de query string.

4. De server geeft de loginpagina terug met een 200 OK HTTP statuscode.

5. De gebruiker vult zijn credentials in en post de pagina samen met de RETURNURL

parameter van de query string terug naar de server.

Page 31: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 22

6. De server valideert de credentials en de code in de loginpagina maakt een cookie die een

forms authenticatieticket bevat voor de huidige sessie. In ASP.NET 2.0 gebeurt de va-

lidatie van de credentials via het membership systeem aan de hand van de ValidateUser

methode:

Listing 3.1: ValidateUser

1 if (Membership.ValidateUser(userName.Text, password.Text)){

2 if (Request.QueryString["ReturnUrl"] != null){

3 FormsAuthentication.RedirectFromLoginPage(userName.Text, false);

4 } else {

5 FormsAuthentication.SetAuthCookie(userName.Text, false);

6 }

7 } else {

8 Response.Write("Invalid UserID and Password");

9 }

7. De server zal de geauthenticeerde gebruiker redirecten naar de URL van de oorspronke-

lijke aanvraag. Deze is gespecifieerd in de query string bij de RETURNURL parameter.

Het HTTP antwoord ziet er als volgt uit:

302 Found Location:

http://localhost/TestSample/default.aspx

8. De redirect wordt gevolgd en de browser vraagt opnieuw de Default.aspx pagina op.

Deze keer bevat de aanvraag ook de forms authenticatie cookie.

9. De FormsAuthenticationModule class detecteert de form authenticatie cookie en iden-

tificeert de gebruiker.

10. De server heeft de authenticatie cookie geverifieerd en stuurt de Default.aspx pagina

door.

Page 32: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 23

Figuur 3.1: Forms Authentication Control Flow

3.2.2 ASP.NET State Management

Telkens wanneer er een post gebeurt naar de server wordt een nieuwe instantie van de webpa-

gina gemaakt. In traditioneel web development zou dit betekenen dat alle informatie telkens

verloren gaat. Wanneer de gebruiker bijvoorbeeld tekst in een tekstvak invoert, zal de in-

formatie verloren gaan tijdens de heen- en terugreis van de browser/client naar de server.

ASP.NET voorziet in een aantal mogelijkheden om aan State Management [16] te doen:

View state, Control state, Hidden state, Cookies, Query strings, Application state, Session

state en Profile properties. Pacsonweb maakt zowel gebruik van View state, Cookies als van

Session state. De verschillende vormen van state management kunnen worden opgedeeld

in twee categorieen. Sommige methoden houden data bij op de client, terwijl andere data

bijhouden op de server.

Client-Based State Management

• View state

De view state biedt een dictionary object aan voor het behoud van waarden tussen

meerdere aanvragen voor dezelfde pagina. Dit is de standaardmethode die een pagina

gebruikt om de informatie te bewaren tijdens het communiceren met de server. Als de

pagina wordt verwerkt, wordt de huidige staat van de pagina gehashed in een string en

wordt deze opgeslagen in een verborgen veld of meerdere verborgen velden wanneer de

Page 33: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 24

grootte hoger is dan de opgegeven waarde in MaxPageStateFieldLength. Wanneer de

pagina gepost wordt naar de server, zal de pagina tijdens zijn initialisatie de view state

parsen en de informatie op de pagina opnieuw invullen.

• Cookies

Een cookie is een kleine hoeveelheid data die in een tekstbestand wordt opgeslagen

op de client in het besturingssysteem of in-memory van de browsersessie. Het bevat

sitespecifieke informatie die de server naar de client stuurt samen met de paginauitvoer.

Cookies kunnen tijdelijk zijn met een vervaldatum of persistent. Ze kunnen informatie

opslaan over een bepaalde client, sessie of applicatie. Cookies worden opgeslagen op het

clienttoestel en wanneer de browser een pagina aanvraagt, stuurt de client de cookie mee

met de aanvraag. De server kan de cookie lezen en er de waarde uit halen. Doorgaans

houdt men in de cookie een token bij dat aanduidt dat de gebruiker reeds geauthenticeerd

is.

Server-Based State Management

• Session state

Bij session state management zal elke gebruiker die de applicatie gebruikt een ver-

schillende session state hebben. Wanneer een gebruiker de applicatie verlaat en slechts

enkele seconden later de applicatie opnieuw opent, zal hij een session state hebben die

verschillend is van zijn oorspronkelijke session state. Session state is gestructureerd als

een key/value dictionary om sessiespecifieke informatie op te slaan die op de server moet

worden bijgehouden tussen de verschillende aanvragen. Een session state kan gebruikt

worden om de browser of het clienttoestel te identificeren bij de aanvragen. Deze kun-

nen worden gemapt naar een individuele sessie op de server. Men kan de session state

ook gebruiken om sessiespecifieke data bij te houden op de server om deze te gebruiken

over meerdere browsers.

3.2.3 Authenticatie in iOS

Zoals al eerder vermeld, is het belangrijk om de gebruikers van de nieuwe applicatie te authen-

ticeren zonder dat er grote aanpassingen aan de bestaande backend moeten gebeuren. Om

dit te verwezenlijken, loggen we programmatisch in op Pacsonweb met de iOS applicatie. Dit

kan op verschillende manieren gebeuren. We kunnen hiervoor NSURLConnection gebruiken

of NSURLSession.

NSURLConnection

Een NSURLConnection [17] object laat toe om de inhoud van een URL op te halen. Dit

kan synchroon of asynchroon gebeuren. Met een NSURLConnection object kan er enkel een

Page 34: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 25

connectie gestart of afgebroken worden. Men beschikt niet over de mogelijkheid om deze

connectie te pauzeren en later te hervatten. Een NSURLConnection object maken kan op de

volgende manier [18]:

Listing 3.2: Creatie van een NSURLConnection

1 NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:

2 @"http://www.apple.com/"]

3 cachePolicy:NSURLRequestUseProtocolCachePolicy

4 timeoutInterval:60.0];

5 receivedData = [NSMutableData dataWithCapacity: 0];

6 NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest

7 delegate:self];

8 if (!theConnection) {

9 receivedData = nil;

10 }

Zoals hierboven staat aangegeven, moet er eerst een NSURLRequest object gemaakt worden.

Dit object moet vervolgens worden meegegeven aan het NSURLConnection object. De ge-

bruikte methode - initWithRequest:delegate: toont aan dat de bovenstaande connectie asyn-

chroon is. Voor delegate staat de waarde self ingevuld, wat betekent dat de klasse die deze

methode implementeert zelf het ontvangen en versturen van data zal afhandelen. Om een syn-

chrone connectie te maken wordt de methode + sendSynchronousRequest:returningResponse:error:

gebruikt.

NSURLSession

Vanaf iOS7.0 kan er voor connecties ook NSURLSession [19] gebruikt worden. NSURLSes-

sion ondersteunt authenticatie en biedt ook de mogelijkheid om het versturen en ontvangen

van data in de achtergrond uit te voeren. In tegenstelling tot NSURLConnection kan deze

connectie wel gepauzeerd en later hervat worden. Een groot voordeel van de NSURLSession

is de mogelijkheid om de configuratie van de connectie per sessie te configureren. Dit zorgt

ervoor dat de verschillende onderdelen van de applicatie afzonderlijk kunnen werken. Een

tweede voordeel is dat NSURLSession gebruik maakt van NSURLSessionTasks. De NSURL-

SessionTask klasse is de basis voor taken van een URL sessie. Een taak is altijd een deel

van de sessie en kan worden gecreeerd door de respectievelijke methode op te roepen van het

NSURLSession object. Er zijn drie verschillende types:

• NSURLSessionDataTask

• NSURLSessionUploadTask

• NSURLSessionDownloadTask

Page 35: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 26

Een datataak vraagt een bepaalde resource op en geeft dit terug als een of meerdere NSData

objecten in het geheugen. Deze taak wordt niet ondersteund in achtergrondsessies. Upload-

taken zijn gelijkaardig aan datataken, met de uitzondering dat deze wel ondersteund zijn in

achtergrondsessies. Downloadtaken downloaden een resource onmiddellijk naar een bestand

op schijf. Deze taak is ondersteund in elk type sessie. Een NSURLSession object maken kan

op de volgende manier:

Listing 3.3: Creatie van een NSURLSessie

1 NSURLCache *myCache = [[NSURLCache alloc] initWithMemoryCapacity: 16384

2 diskCapacity: 268435456 diskPath: cachePath];

3 defaultConfigObject.URLCache = myCache;

4 defaultConfigObject.requestCachePolicy = NSURLRequestUseProtocolCachePolicy;

5 self.defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject

6 delegate: self delegateQueue: [NSOperationQueue mainQueue]];

7 self.backgroundSession = [NSURLSession sessionWithConfiguration:

8 backgroundConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];

9 self.ephemeralSession = [NSURLSession sessionWithConfiguration: ephemeralConfigObject

10 delegate: self delegateQueue: [NSOperationQueue mainQueue]];

Omdat de applicatie vereist dat uploads moeten kunnen worden gepauzeerd en dat NSURL-

Session de opvolger is van NSURLConnection is de keuze voor NSURLSession vanzelfspre-

kend.

Login procedure

De login procedure verloopt niet helemaal zoals in 3.1. Zoals reeds eerder vermeld, wordt

er programmatisch ingelogd op Pacsonweb via de iOS applicatie. De procedure wordt echter

ingekort door onmiddellijk een HTTP POST bericht te sturen naar de server in plaats van

de loginpagina eerst op te vragen aan de server. Hiervoor moeten de namen van de velden

van het inlogformulier vooraf gekend zijn. Deze zijn respectievelijk:

• UserName

• Password

• rememberMe

Aan de hand van deze namen kan het HTTP POST bericht programmatisch worden op-

gebouwd. De waarden voor deze velden worden geleverd door de iOS applicatie. Om na

te gaan of er correct is ingelogd, kan er gekeken worden naar het location veld van de res-

ponse header van het server antwoord. Indien de waarde van dit veld overeenstemt met

/v2/Members/Explore.aspx was de loginprocedure succesvol.

Page 36: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 27

Inloggen via pincode

Een van de basisvereisten die gesteld wordt aan mobiele applicaties is dat ze gemakkelijk zijn in

gebruik. De credentials van Pacsonweb bestaan uit een gebruikersnaam en een paswoord. Het

spreekt voor zich dat een gebruikersnaam en paswoord telkens opnieuw ingeven op een mobiel

toestel vervelend kan zijn. Daarom werd een alternatieve manier bedacht die eenvoudiger te

hanteren is, zoals de vaak gebruikte manier van een pincode. Tegenwoordig gebruiken bijna

alle banken dit. De iOS applicatie wordt daarom ook voorzien van de mogelijkheid om met een

pincode in te loggen. Er werd gekozen om gebruik te maken van een vijfcijferige pincode. Er

zijn hierdoor 100000 verschillende combinaties mogelijk, wat betekent dat een inbreker in het

slechtste geval alle 100000 mogelijke combinaties moet uitproberen om in zijn opzet te slagen.

In de applicatie zit echter een extra veiligheid ingebouwd die maar vijf foutieve inlogpogingen

na elkaar toelaat. Hierdoor is de kans dat de pincode achterhaald wordt 1/20000. Wanneer

een verpleegkundige zijn pincode vergeten is en deze vijfmaal foutief ingeeft, zal de account op

non-actief worden gezet. Dit zorgt ervoor dat de verpleegkundige zich niet meer kan inloggen

zonder zich opnieuw te authenticeren bij Pacsonweb. Wanneer de verpleegkundige opnieuw

geauthenticeerd is bij Pacsonweb, wordt de account terug geactiveerd en zijn de gegevens

opnieuw beschikbaar.

3.3 Beveiliging van de applicatie

3.3.1 The sandbox

Het iOS security model is gebaseerd op een sandbox . Tijdens de installatie wordt er aan

de applicatie een sandbox toegekend. Een sandbox is een container, een deel van de harde

schijf die enkel toegankelijk is voor de applicatie die aan de sandbox is toegewezen. Dit

biedt bescherming op twee manieren. Enerzijds is het besturingssysteem beschermd tegen

slecht geprogrammeerde applicaties die te veel geheugen in beslag nemen en anderzijds zijn de

bestanden van de applicatie beschermd tegen indringers. Elke sandbox heeft dezelfde indeling.

Zoals in figuur 3.2 te zien is, bevat deze een .app bestand die de applicatie voorstelt, een

Documents, Library en tmp map.

Page 37: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 28

Figuur 3.2: Sandbox indeling

Elke map heeft een eigen functie. De Documents map wordt gebruikt voor het opslaan van

documenten die door de gebruiker gegenereerd zijn en bestanden eigen aan de applicatie. De

Library map laat toe dat itunes een back-up neemt van de bestanden binnen deze map. De

tmp map wordt gebruikt voor bestanden die niet gepersisteerd moeten worden. Wanneer de

bestanden niet beschikbaar moeten zijn telkens de applicatie opstart, is het aangeraden om

deze bestanden op te slaan in de tmp map.

Een applicatie kan enkel van deze mappen gebruik maken. De applicatie heeft geen toe-

gang tot mappen van een andere applicatie en kan dus enkel bestanden wegschrijven binnen

zijn eigen sandbox .

3.3.2 Beveiliging van de bestanden

Zoals eerder vermeld, zijn de bestanden van een applicatie in principe enkel beschikbaar

binnen de container van de applicatie zelf. Een applicatie maken die 100% veilig is kan echter

niet. Er zullen altijd manieren bestaan of gevonden worden om de beveiliging te omzeilen.

Het is dus aan de ontwikkelaars van de applicaties om het zo moeilijk mogelijk te maken

voor inbrekers om toegang te krijgen. De applicatie maakt gebruik van een tweevoudige

databeveiliging namelijk op applicatieniveau en op toestelniveau.

Page 38: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 29

Databeveiliging op applicatieniveau

Omwille van de confidentialiteit is het zeer belangrijk dat de genomen foto′s niet zomaar

zichtbaar zijn voor onbevoegden. Dit is ook de reden waarom alle afbeeldingen op schijf

geencrypteerd worden. Omdat ook decryptie van de afbeeldingen mogelijk moet zijn, is er

nood aan een conventioneel encryptiealgoritme. Het huidige standaard conventioneel encryp-

tiealgoritme is AES-256, dat gebruik maakt van een encryptiesleutel van 256 bits. Het is

echter niet gebruiksvriendelijk om de gebruiker telkens om een sleutel van 256 bits te vragen

wanneer een afbeelding geencrypteerd moet worden. Daarom wordt de pincode van de ge-

bruiker als sleutel gebruikt. Omdat de pincode geen 256 bits lang is wordt deze door het

gebruikte encryptie framework aangevuld zodat deze lang genoeg is.

Databeveiliging op toestelniveau

iOS voorziet in een feature om de gemarkeerde bestanden hardwarematig te encrypteren. Deze

feature zorgt ervoor dat wanneer het toestel vergrendeld is door middel van een pincode, de

bestanden hardwarematig geencrypteerd zijn. Hierbij moet wel vermeld worden dat het om

de pincode van het toestel en niet van de applicatie gaat. Wanneer het toestel vergrendeld

is, zijn de bestanden dus ook niet beschikbaar voor de applicatie die ze gemaakt heeft. Deze

bescherming kan op twee manieren worden ingesteld. Ofwel wordt elk bestand afzonderlijk

gemarkeerd, ofwel stelt men dit in voor de volledige applicatie. Dit laatste kan voor het

project ingesteld worden door capabilities enable data protection aan te zetten.

3.3.3 Opslag van de credentials en de pincode

Er zijn twee redenen waarom de pincode lokaal bijgehouden moet worden. Een eerste reden

is omdat de applicatie offline moet kunnen worden gebruikt en het dus mogelijk moet zijn

om zich te authenticeren zonder dat er connectie gemaakt moet worden met de server. De

tweede reden is dat de backend zo weinig mogelijk moet worden aangepast.

De keychain

Om de credentials van Pacsonweb en de pincode lokaal op te slaan, wordt er gebruik gemaakt

van een keychain. Een keychain is een speciale databank die gebruikt wordt om er kleine din-

gen in op te slaan die geheim moeten blijven. Elke rij in de databank wordt voorgesteld door

een keychainitem. Een keychainitem bevat metadata en beveiligde data. De beveiligde data

zijn geencrypteerd en de metadata worden gebruikt om efficienter te zoeken in de keychain.

De keychain is specifiek voor een applicatie en wordt buiten de container van de applicatie

opgeslagen voor back-up doeleinden. Apple raadt ten sterkste aan om alles wat te maken

heeft met gebruikersaccounts en paswoorden op te slaan in de keychain. Er is reeds onder-

zoek uitgevoerd door het Fraunhofer Institute for Secure Information Technology [20] over

Page 39: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 30

de sterkte van de keychain. Het onderzoek bevestigt dat een keychain veilig is zolang aan

volgende twee vereisten wordt voldaan:

• Het is belangrijk om de keychainitems op te slaan met een goede beschermingsklasse.

Een goede beschermingsklasse is kSecAttrAccessibleWhenUnlocked . Deze zorgt ervoor

dat de keychainitems enkel beschikbaar zijn voor de applicatie wanneer het toestel

ontgrendeld is.

• Het toestel moet beschermd zijn door middel van een goede pincode. Het gaat hier

over dezelfde pincode als deze die besproken werd in subsectie databeveiliging op toe-

stelniveau van sectie 3.3.2 beveiliging van de bestanden. De pincode wordt gebruikt om

het toestel te ontgrendelen en zorgt ervoor dat keychainitems beschikbaar zijn voor de

applicatie. Standaard heeft de toestelpincode een lengte van vier karakters, maar het

onderzoek geeft aan dat deze best een lengte van zes karakters heeft. Dit wordt dus

best zo ingesteld.

Werken met een keychain is niet altijd even eenvoudig. Er zijn talrijke frameworks en key-

chainwrappers te vinden die deze omslachtige taak voor de ontwikkelaar vereenvoudigen. In

iSentToPacs wordt gebruik gemaakt van de keychainwrapper die door Apple wordt aangebo-

den. Deze keychainwrapper identificeert de keychainitems op basis van de gebruikersnaam.

Tabel 3.1 geeft een voorbeeld van hoe de keychaintable eruitziet. In het voorbeeld bevat de

keychaintable twee keychainitems van gebruiker Joachim. Zoals de tabel aangeeft, worden

paswoord en pincode in dezelfde kolom opgeslagen. Wanneer een record slechts enkel op de ge-

bruikersnaam geıdentificeerd wordt, zal deze tabel dus duplicaten bevatten. Daarom wordt de

keychainwrapper van Apple aangepast zodat een keychainwrapperitem uniek geıdentificeerd

wordt door twee velden, namelijk service en gebruikersnaam.

Service Gebruikersnaam Paswoord of pincode

pincode service Joachim xxxxx

paswoord service Joachim xxxxx

Tabel 3.1: Voorbeeld keychain

Page 40: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 31

De originele keychainwrapper is beschikbaar op de website van Apple [21] en in bijlage B is de

aangepaste keychainwrapper terug te vinden. Een keychainitem toevoegen aan de keychain

kan op de volgende manier:

Listing 3.4: Keychainitem toevoegen aan de keychain

1 wrapperPassword = [[KeychainItemWrapper alloc] initWithAccount:_user.username

2 service:@"iExaminationPassword" accessGroup:nil];

3 wrapperPincode = [[KeychainItemWrapper alloc] initWithAccount:_user.username

4 service:@"iExaminationPincode" accessGroup:nil];

5 id kSecUsername = (__bridge id)(kSecAttrAccount);

6 id kSecPassword = (__bridge id)(kSecValueData);

7 id kSecPincode = (__bridge id)(kSecValueData);

8 [wrapperPassword setObject:_user.username forKey:kSecUsername];

9 [wrapperPassword setObject:password forKey:kSecPassword];

10 [wrapperPincode setObject:_user.username forKey:kSecUsername];

11 [wrapperPincode setObject:pin forKey:kSecPincode];

Eerst worden er twee KeychainItemWrapper objecten aangemaakt die geınitialiseerd worden door

middel van de gebruikersnaam en de service. De service kan iExaminationPassword zijn wanneer

het een paswoord is dat wordt opgeslagen of iExaminationPincode wanneer het een pincode is die

wordt opgeslagen. Vervolgens kunnen de keychainwrapper objecten als dictionaries behan-

deld worden en kunnen de waarden worden ingesteld via de methode [wrapper setObject:object

forkey:sleutelattribuut]. Naast het opslaan van gegevens in de keychain moet het ook mo-

gelijk zijn om deze terug op te vragen. Telkens wanneer de applicatie achter de schermen

nood heeft aan de pincode of het paswoord van de gebruiker om bijvoorbeeld afbeeldingen te

encrypteren, kan dit gemakkelijk opgevraagd worden via de keychain. Na gebruik mag het

paswoord of de pincode gewoon worden weggegooid zodat dit niet onderschept kan worden.

De keychain wordt dus uitsluitend gebruikt wanneer de applicatie tijdelijk de pincode of het

paswoord nodig heeft. In geen enkel geval mag het paswoord of de pincode door de applicatie

in het geheugen bewaard worden. Dit is de functie van de keychain die speciaal hiervoor

ontwikkeld is. Onderstaande methode werd ook nog aan de keychainwrapper toegevoegd om

gegevens op te vragen uit de keychain.

Page 41: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 32

Listing 3.5: Paswoord of pincode ophalen uit de keychain

1 - (NSString *) passwordOrPincodeForUserName:(NSString *)serviceName

2 username:(NSString *) username found:(BOOL *)found{

3 NSMutableDictionary *query = [NSMutableDictionary dictionaryWithObjectsAndKeys:

4 (__bridge id)(kSecClassGenericPassword), kSecClass,

5 serviceName, kSecAttrService,

6 username, kSecAttrAccount,

7 kCFBooleanTrue, kSecReturnData, nil];

8 NSData * data = NULL;

9 OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)(query),

10 (CFTypeRef *)&data);

11 *found = status != errSecItemNotFound;

12 NSString *passwordOrPincode = [[NSString alloc] initWithData:

13 (__bridge NSData *)(data) encoding:NSUTF8StringEncoding];

14 return passwordOrPincode;

15 }

Op basis van de gebruikersnaam en de servicenaam kan een uniek keychainitem geıdentificeerd

worden. Met deze informatie wordt een query opgesteld die wordt uitgevoerd op de keychain.

Het resultaat van de query wordt omgezet naar een NSString * en geretourneerd indien er geen

fout is opgetreden.

3.3.4 Encryptie

Om confidentiele gegevens te beschermen worden deze geencrypteerd op schijf. Zoals reeds

eerder vermeld, werd er als encryptiealgoritme gekozen voor AES-256. Dergelijke encryptie

verzorgen met behulp van de klassen van Apple is zeer moeilijk. Daarom wordt er gebruik

gemaakt van een framework , genaamd RNCryptor, die rond deze klassen van Apple is ge-

bouwd.

AES

Advanced Encryption Standard is een symmetrisch encryptiealgoritme dat gebruikt wordt

om plain tekst om te zetten in cipher tekst. Om de cipher tekst om te zetten naar plain

tekst wordt dezelfde sleutel gebruikt als deze voor encryptie. AES kan gebruikt worden met

drie verschillende sleutellengtes: 128, 192 en 256 bits. De reden waarom er voor AES-256

werd gekozen, is omdat dit zeer veilig is. In het geval van AES-256 bedraagt de sleutellengte

256 bits wat betekent dat er 2256 mogelijke sleutels zijn. Zelf met een enorme hoeveelheid

computerkracht is het onmogelijk om de sleutel te achterhalen.

Page 42: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 33

RNCryptor

Als encryptie framework wordt er gebruik gemaakt van RNCryptor. Het framework voorziet

in AES-256 encryptie, generatie van een salt en hashen van een paswoord met SHA. Het kan

eveneens een initiele waarde geven wanneer er gebruik gemaakt wordt van de cipher block

chaining mode bij de encryptie. Data encrypteren kan met de onderstaande code.

Listing 3.6: Encryptie van data

1 NSData *encryptedData = [RNEncryptor encryptData:data

2 withSettings:kRNCryptorAES256Settings

3 password:pincode

4 error:&error];

De methode encryptData van de RNEncryptor klasse wordt aangeroepen. Aan deze methode

wordt de data meegegeven die geencrypteerd moet worden alsook de instellingen voor AES-

256, de pincode en een pointer naar een object waarin de eventuele error terecht komt wanneer

er iets fout loopt. Decrypteren van data is even eenvoudig als het encrypteren van data en

kan op de volgende manier:

Listing 3.7: Decryptie van data

1 NSData *decryptedData = [RNDecryptor decryptData:encryptedData

2 withPassword:pincode

3 error:&error];

Deze keer wordt de decryptData methode opgeroepen van de RNDecryptor klasse. Deze krijgt

de decryptiedata en de AES-256 instellingen mee alsook de pincode en een pointer naar een

object die de error zal bevatten als er iets fout loopt.

3.4 Opslag van de data

3.4.1 NSFileManager

Om de afbeeldingen naar schijf weg te schrijven, kan er gebruik gemaakt worden van de

NSFileManager . Met de NSFileManager kunnen zowel mappen als bestanden aangemaakt

worden. In de applicatie worden zowel mappen gecreeerd als bestanden om een duidelijk

onderscheid te maken waar alles is opgeslagen. Om een map te creeren moet eerst gecontro-

leerd worden of deze al dan niet reeds bestaat. Bij het wegschrijven van een afbeelding naar

een bestand zou er ook gecontroleerd kunnen worden of er niet reeds een bestand bestaat

met dezelfde naam, maar omdat de naam een uniek gegenereerde string is, is dit niet van

toepassing.

Page 43: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 34

Listing 3.8: Data wegschrijven naar een bestand

1 -(NSString *)writeDataToDisk:(NSData *)data name:(NSString *)name

2 username:(NSString *)username{

3 BOOL found;

4 NSString * pincode = ...;

5 NSString *imagePath = [NSHomeDirectory()

6 stringByAppendingPathComponent:@"Documents/iExaminationData/"];

7 NSError *error;

8 if (![[NSFileManager defaultManager] fileExistsAtPath:imagePath])

9 {

10 if (![[NSFileManager defaultManager] createDirectoryAtPath:imagePath

11 withIntermediateDirectories:NO

12 attributes:nil

13 error:&error])

14 {

15 NSLog(@"Create directory error: %@", error);

16 }

17 }

18 imagePath = [[imagePath stringByAppendingString:@"/" ] stringByAppendingString:name];

19 NSData *encryptedData = ...;

20 [encryptedData writeToFile:imagePath atomically:YES];

21 if(error){

22 NSLog(@"Fout bij wegschrijven file! Error: %@", error);

23 }

24 return imagePath;

25 }

De bovenstaande methode toont aan hoe een afbeelding wordt weggeschreven naar schijf.

Om de methode wat in te korten, werden een aantal stukken code die eerder aan bod kwa-

men weggelaten. Het betreft de stukken code om de pincode uit de keychain te halen en

om data te encrypteren. NSHomeDirectory() geeft het pad naar de homedirectory terug van de

applicatie. Het gaat hier dus niet om de homedirectory van het toestel. Het pad naar de

homedirectory wordt aangepast zodat het nu naar een al dan niet bestaande directory wijst

waarin de afbeeldingen worden opgeslagen. Aan de hand van de methode fileExistsAtPath

kan er nagegaan worden of de map reeds bestaat. Indien deze niet bestaat, kan deze via de

methode createDirectoryAtPath gecreeerd worden. Vervolgens wordt het pad opnieuw aange-

past door de naam van het bestand eraan toe te voegen. Wegschrijven van de data naar het

pad kan dan met de methode writeToFile die als parameter het pad meekrijgt. Tot slot geeft

de methode het pad terug van het opgeslagen bestand zodat dit kan worden opgeslagen in de

lokale database van de applicatie.

Page 44: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 35

Om een bestand op te halen, gebruiken we de volgende methode:

Listing 3.9: Ophalen van een bestand

1 -(NSData *) loadDataFromDisk:(NSString *)filePath username:(NSString *)username{

2 BOOL found;

3 NSString * pincode = ...;

4 NSData *encryptedData = [NSData dataWithContentsOfFile:filePath];

5 NSError *error;

6 NSData *decryptedData = ...;

7 if(error){

8 NSLog(@"Fout bij ophalen file! Error: %@", error);

9 }

10 return decryptedData;

11 }

Opnieuw zijn enkele stukken weggelaten die reeds eerder werden uitgelegd. Data ophalen

van de schijf kan met de methode dataWithContentsOfFile die als parameter het pad van het

bestand meekrijgt. Tot slot wordt de data van het bestand teruggegeven.

3.4.2 Lokale database

Wanneer de gegevens niet afgeschermd moeten zijn, kunnen deze op een normale manier

worden opgeslagen. De eenvoudigste manier die iOS biedt om gegevens op te slaan, is door

gebruik te maken van een SQLite database. Een SQLite database is een lightweight database

die dezelfde handelingen toelaat zoals elke andere database. De onderstaande figuur toont

het database model van de applicatie.

Figuur 3.3: Lokaal database model

Page 45: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 36

Users tabel

De users tabel wordt gebruikt om er de gebruikers van de applicatie in op te slaan. Voor elke

gebruiker wordt de voornaam, achternaam, PacsOnWeb gebruikersnaam, laatste loginpoging

en het aantal foutieve loginpogingen bijgehouden. De voornaam en achternaam worden in de

lijst van gebruikers die kunnen inloggen op de applicatie getoond. De PacsOnWeb gebruikers-

naam wordt gebruikt om het PacsOnWeb wachtwoord en de pincode van de gebruiker op te

halen uit de keychain wanneer deze nodig zijn. Het aantal loginpogingen wordt bijgehouden

omdat de gebruiker op non-actief geplaatst wordt na vijf foutieve loginpogingen.

Sessions tabel

Wanneer een gebruiker is ingelogd heeft, hij de mogelijkheid om een sessie aan te maken. Een

sessie bestaat uit de volgende velden: een user id , visit id , active veld, label veld, naamLabel

veld, identificated veld, uploading veld, progress veld en een uploadDate veld. Het user id

veld bevat de verwijzende sleutel naar de gebruikerstabel om een sessie aan een bepaalde

gebruiker te koppelen. Het visit id is de unieke identificatie van het visit object dat van

de server wordt afgehaald. Een visit object wordt aangemaakt wanneer een patient zich

aanmeldt aan de balie van het ziekenhuis om een onderzoek te laten uitvoeren. Zolang er

geen visit id is toegekend aan de sessie kan de sessie niet geupload worden, want zonder

een visit id is de sessie niet verbonden met een patient. Het active veld is een boolean die

aanduidt of de sessie reeds is geupload. De label en naamLabel velden geven voor de gebruiker

een grafische aanduiding of er aan de sessie reeds een patient werd toegekend. Indien er nog

geen patıent is toegekend, zal het naamLabel veld leeg zijn en enkel het label veld ingevuld

zijn. Het label veld geeft een tijdsaanduiding van wanneer de sessie werd gecreeerd. Indien

er later een patient toegekend wordt aan de sessie, zal het naamLabel veld worden ingevuld

met zijn voornaam en achternaam. Op deze manier weet de gebruiker van de applicatie dat

deze sessie geıdentificeerd is en dat deze geupload kan worden. Het identificated veld is een

boolean veld dat een aanduiding geeft of er aan de sessie een patient is toegekend. Door

deze boolean op true in te stellen, wordt de uploadknop op actief gezet voor de sessie. Dit

biedt de gebruiker de mogelijkheid om de sessie te uploaden wanneer hij klaar is met het

bewerken van de sessie. Het uploading veld is opnieuw een boolean die aanduidt of de upload

momenteel bezig is. Dit veld is nodig omdat het uploaden gepauzeerd moeten kunnen worden.

Aan de hand van dit veld zal bij de volgende opstart van de applicatie duidelijk zijn of de

sessie zijn upload vooruitgang getoond mag worden en of de uploadknop actief mag zijn. Het

progress veld is van het type double en ligt tussen 0 en 1. Dit veld geeft weer hoe ver de

upload momenteel zit. Wanneer de upload van een sessie is afgerond, wordt de datum van

het uploaden bijgehouden. Alle sessies worden een week bewaard in het intern geheugen en

daarna verwijderd om geheugen te sparen.

Page 46: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 37

Images tabel

Voor elke afbeelding wordt een extra rij in de images tabel toegevoegd. Een rij in de image

tabel heeft een session id , imagePath en een uploaded veld. Het session id is de verwijzende

sleutel naar een sessie waaraan deze afbeelding toebehoort. Het imagePath geeft weer waar

de afbeelding zich op schijf bevindt en het uploaded veld is een boolean die aanduidt of de

upload van deze afbeelding succesvol was. Op basis van het upload veld kan de vooruitgang

van de upload berekend worden wanneer deze hervat wordt.

Videos tabel

De inhoud van de videos tabel ziet er hetzelfde uit als deze van de images tabel. Momenteel

wordt deze tabel nog niet gebruikt omdat dit een van de uitbreidingen is van de applicatie.

Visits tabel

Wanneer men een sessie wil uploaden naar de server moet er aan de sessie een visit en een

patient zijn toegekend. Daarom biedt de applicatie de mogelijkheid om aan de hand van het

visitnumber een visit object van de server te halen. Dit visit object moet worden opgeslagen

omdat de gebruiker niet verplicht is om de sessie te uploaden zodra er een visit aan toegekend

is. De velden van de visit tabel zijn volledig bepaald door het reeds bestaande systeem. Deze

velden zijn visit id , patient id , patientclass, requestingphysician, requestingdepartment , atten-

dingphysician, attendingdepartment , referringphysician en referringdepartment . Het visit id

is de unieke identificatie die is toegekend aan het object bij de creatie ervan op de server.

Het patient id verwijst naar de patient van wie het onderzoek zal worden afgenomen. De

patientclass geeft meer informatie weer over het soort onderzoek.

3.4.3 Creatie lokale database

Wanneer de database nodig is, mag deze niet telkens opnieuw gecreeerd worden. Om te

vermijden dat dit gebeurt, wordt er gebruik gemaakt van het Singleton pattern. Wanneer de

database wordt opgevraagd controleert dit pattern of de database reeds bestaat. Wanneer

de database nog niet bestaat, wordt deze aangemaakt. In het andere geval wordt de reeds

bestaande database teruggegeven. Een database aanmaken kan zoals aangegeven in Listing

3.10.

Page 47: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 38

Listing 3.10: Creatie database

1 - (id)init{

2 if (self = [super init]) {

3 NSFileManager *fileManager = [NSFileManager defaultManager];

4 NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(

5 NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];

6

7 NSString *sqlitePath = [documentsDirectory stringByAppendingPathComponent:

8 databaseFileName];

9 if (![fileManager fileExistsAtPath:sqlitePath]){

10 if(![fileManager createFileAtPath:sqlitePath contents:nil attributes:nil]){

11 return nil;

12 }

13 }

14 if (sqlite3_open([sqlitePath UTF8String], &dbConnection) != SQLITE_OK) {

15 return nil;

16 }

17 }

18 return self;

19 }

Wanneer de init methode van de database wordt aangeroepen wordt het pad naar de database

file gecreeerd. De volgende stap gaat na of de database file voor het pad wel degelijk bestaat

en indien dit niet het geval is, wordt de database file aangemaakt. Indien de database file

reeds bestaat, wordt het geopend en wordt de dbConnection variabele die de connectie naar de

databank geeft ingevuld. Zoals reeds eerder vermeld zal het Singleton pattern ervoor zorgen

dat de database slechts een keer wordt aangemaakt. De implementatie van het Singleton

pattern is te zien in Listing 3.11.

Listing 3.11: Singleton

1 +(Database *)getInstance {

2 @synchronized(self)

3 {

4 if (database == nil){

5 database = [[self alloc] init];

6 }

7 }

8 return(database);

9 }

De getInstance methode is een statische methode. Wanneer er nood is aan de database zal

men van deze methode gebruik maken om de database op te vragen. Deze methode maakt de

database aan indien deze nog niet bestaat en geeft deze terug. De @synchronized(self) zorgt

ervoor dat we veilig multi-threaded kunnen werken. Zonder deze lijn zou het niet mogelijk

zijn om vanuit meerdere threads de database aan te spreken.

Page 48: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 39

Aanmaken van tabellen

Naast de creatie van de database moeten ook nog de tabellen gecreeerd worden. Om tabellen

te creeren, maken we gebruik van sql statements die worden uitgevoerd door de sqlite3 exec

methode geleverd door de sqlite3 bibliotheek. De creatie van de tabellen voor deze applicatie

ziet er als volgt uit:

Listing 3.12: Creatie tabellen

1 - (id)init {

2 Database *database = [Database getInstance];

3 db = [database getSqlite3Connection];

4 if (db == nil) {

5 database = [[Database alloc] init];

6 } else {

7 sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS users ( id INTEGER

8 PRIMARY KEY AUTOINCREMENT, name TEXT, lastName TEXT, username TEXT,

9 lastLoginOnServer TEXT, pincodeLoginTries INTEGER)", NULL, NULL, NULL);

10 ...

11 }

12 return self;

13 }

Bovenstaande methode zorgt dat alle tabellen gecreeerd worden indien deze nog niet bestaan.

In het begin van de methode wordt de getInstance methode aangeroepen. Indien de database

nog niet bestaat, zal de getInstance methode ervoor zorgen dat deze aangemaakt wordt.

Vervolgens wordt aan de hand van de getSqlite3Connection methode de database connectie

opgevraagd. Wanneer deze nog niet bestaat, wordt deze aangemaakt door de regel database

= [[Database alloc] init]. In het andere geval wordt voor elke tabel die aangemaakt moet

worden een sql statement uitgevoerd die de nodige velden bevat die in de tabel moeten

zitten. Samen met het sql statement wordt ook de database connectie meegegeven zodat de

sqlite3 exec methode weet over welke database het gaat.

3.5 UIImagePickerController

De UIImagePickerController [22] levert een interface die toelaat om afbeeldingen en video-

filmpjes te maken. Om gebruik te maken van de UIImagePickerController moet zijn delegate

geımplementeerd worden. Een delegate is een object dat de events afhandelt voor een ander

object. In dit geval zal de delegate de events afhandelen van de UIImagePickerController .

Wanneer een foto genomen wordt, zal automatisch de juiste methode van de delegate worden

aangeroepen. Alvorens gebruik te maken van de UIImagePickerController zijn er een aan-

tal zaken die ingesteld moeten worden. In Listing 3.13 staat de methode weergegeven die

verantwoordelijk is voor de initialisatie van de UIImagePickerController .

Page 49: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 40

Listing 3.13: Initialisatie van de UIImagePickerController

1 - (IBAction)addStudy:(id)sender {

2 picker = [[UIImagePickerController alloc] init];

3 picker.delegate = self;

4 picker.allowsEditing = NO;

5 picker.sourceType = UIImagePickerControllerSourceTypeCamera;

6 picker.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:

7 UIImagePickerControllerSourceTypeCamera];

8 picker.showsCameraControls = NO;

9 picker.videoQuality = UIImagePickerControllerQualityTypeHigh;

10 [[NSBundle mainBundle] loadNibNamed:@"CameraOverlayView" owner:self options:nil];

11 self.overlayView.frame = picker.cameraOverlayView.frame;

12 picker.cameraOverlayView = self.overlayView;

13 self.overlayView = nil;

14 [self presentViewController:picker animated:YES completion:NULL];

15 }

Zoals in de bovenstaande methode te zien is, wordt de picker.delegate ingesteld op self.

Dit betekent dat de klasse waarin deze methode staat de delegate is voor de UIImage-

PickerController . Een UIImagePickerController voorziet ook de mogelijkheid om een ge-

maakte foto aan te passen, maar omdat er aanpassingen moeten mogelijk zijn die niet door

de UIImagePickerController geleverd worden, zetten we picker.allowsEdeting op NO. Verder

moet ook het picker.sourceType worden ingesteld. Er kan gekozen worden tussen drie ver-

schillende types: UIImagePickerControllerSourceTypePhotoLibrary , UIImagePickerControl-

lerSourceTypeSavedPhotoAlbum en UIImagePickerControllerSourceTypeCamera. UIImage-

PickerControllerSourceTypePhotoLibrary of UIImagePickerControllerSourceTypeSavedPhotos-

Album leveren een interface die toelaat dat afbeeldingen en filmpjes kunnen worden geselec-

teerd uit de bibliotheek van het toestel. Het derde type UIImagePickerControllerSourceTypeCamera

levert een interface om foto’s te maken en daarom wordt het picker.sourceType ingesteld

met deze waarde. Als picker.mediaTypes worden alle mogelijke types ingesteld. De methode

[UIImagePickerController availableMediaTypesForSourceType:UIImagePickerSourceTypeCamera] haalt

alle beschikbare types op voor het maken van filmpjes en foto’s. Om een goede kwaliteit te

verzekeren wordt picker.videoQuality ingesteld op UIImagePickerControllerQualityTypeHigh.

3.5.1 Camera Overlay View

In Listing 3.13 is te zien dat picker.showsCameraControls is ingesteld op NO. Dit komt omdat

het standaardgedrag van de UIImagePickerController niet voldoet aan de vereisten van de

applicatie. Het moet namelijk mogelijk zijn om meer dan een foto na elkaar te maken. Met

de standaard camera controls is dit echter niet mogelijk. Om dit op te lossen, moet een

zelfgemaakte CameraOverlayView gebruikt worden. Een CameraOverlayView is een laag die

bovenop de preview van de camera wordt gelegd. Zonder een CameraOverlayView kunnen er

geen foto’s of filmpjes gemaakt worden, omdat de CameraOverlayView alle camera controls

Page 50: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 41

bevat. Door gebruik te maken van een zelfgemaakte CameraOverlayView kan de functional-

iteit van de UIImagePickerController volledig aangepast worden naar de behoeftes van de

applicatie. Onderstaande figuren geven een voorbeeld weer van een camera preview zonder

en met CameraOverlayView .

Figuur 3.4: Zonder overlay view Figuur 3.5: Met overlay view

Naast de zelfgemaakte CameraOverlayView moeten ook nog de delegate methoden geımplementeerd

worden die de events van de UIImagePickerController afhandelen.

Er zijn twee delegate methoden:

• imagePickerController:didFinishPickingMediaWithInfo:

• imagePickerControllerDidCancel:

De eerste methode wordt steeds aangeroepen wanneer er een foto wordt genomen. Het is dan

ook deze methode die ervoor zorgt dat de afbeelding geencrypteerd en opgeslagen wordt op

schijf. De UIImagePickerController ondersteunt enkel portrait mode om foto’s te nemen. Het

resultaat hiervan is dat elke foto die in landscape mode genomen is 90 graden gedraaid zal zijn.

Daarom wordt in deze methode ook de orientatie van de foto hersteld. De tweede methode

wordt aangeroepen wanneer er op de knop wordt gedrukt om de UIImagePickerController af

te sluiten. Deze methode zal de UIImagePickerController dan correct afsluiten.

Camera effect

Wanneer er een foto gemaakt wordt met een UIImagePickerController met een zelfgemaakte

CameraOverlayView zal dit niet zichtbaar voor de gebruiker van de applicatie. Dit komt

omdat er geen standaard camera effect is toegevoegd aan de CameraOverlayView . Om de

gebruiker duidelijk te maken dat zijn foto is gemaakt, zal deze onderaan rechts op het scherm

getoond worden zoals te zien is in Figuur 3.5. Vervolgens wordt er ook nog een animatie

toegevoegd aan de knop waarop de gebruiker drukt om een foto te nemen. De onderstaande

code geeft weer wat er gebeurt bij het drukken op de knop.

Page 51: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 42

Listing 3.14: Nemen van een foto

1 dispatch_async(dispatch_get_main_queue(), ^{

2 [[[picker cameraOverlayView] layer] setOpacity:1.0];

3 [[[picker cameraOverlayView] layer] setBackgroundColor:

4 [UIColor whiteColor].CGColor];

5 [UIView animateWithDuration:0.50 animations:^{

6 [[[picker cameraOverlayView] layer] setOpacity:1.0];

7 [[[picker cameraOverlayView] layer] setBackgroundColor:

8 [UIColor clearColor].CGColor];

9 }];

10 });

11 [picker takePicture];

De eerste regel code zorgt ervoor dat de actie wordt uitgevoerd op main thread van de gebrui-

kersinterface. Vervolgens wordt de achtergrond van de cameraOverlayView volledig wit gezet

en laten we de witte kleur gedurende een halve seconde wegebben tot de achtergrond van

de cameraOverlayView terug doorzichtig is. Hierdoor is het voor de gebruiker visueel zeer

duidelijk wanneer hij een foto neemt.

3.6 Editeren van afbeeldingen

Naast het nemen van foto’s moet het ook mogelijk zijn om deze aan te passen. Het moet

mogelijk zijn om de foto’s bij te snijden, in te zoomen en de helderheid aan te passen. Het

aanpassen van de helderheid van een afbeelding gebeurt op dezelfde manier als in sectie 2.3.1.

3.6.1 PEPhotoCropEditor

De PEPhotoCropEditor is een bibliotheek vrijgegeven onder de MIT license. Het ondersteunt

het bijsnijden van afbeeldingen, laat toe om in te zoomen en afbeeldingen te roteren. Er zijn

twee manieren om gebruik te maken van deze bibliotheek. De eerste manier bestaat uit het

implementeren van een PECropViewController , terwijl bij de tweede manier de PECropView

geımplementeerd wordt. Er was reeds een controller voorzien om afbeeldingen bij te snijden,

dus werd er gekozen om gebruik te maken van de PECropView . In Listing 3.15 wordt getoond

hoe de PECropView gebruikt kan worden.

Listing 3.15: PECropView

1 - (void)viewDidLoad

2 {

3 [super viewDidLoad];

4 self.cropView.image = self.image;

5 }

In de (void) viewDidLoad methode van de controller die de PECropView bevat, wordt het

nodige gedaan om de PECropView te kunnen gebruiken. Het enige wat moet gebeuren, is

Page 52: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 43

de afbeelding die bewerkt moet worden meegeven aan de cropView. Wanneer de aanpassingen

gedaan zijn, kan de nieuwe afbeelding opgevraagd worden aan de cropView op de volgende

manier: cropView.croppedImage.

3.7 Scannen van de barcode/QR-code

In het voorstel van de masterproef werd een bibliotheek aangehaald die zou gebruikt kunnen

worden om barcodes te scannen. Sinds iOS 7 is het echter mogelijk om zelf een barcodescanner

te creeren. Er werd dan ook gekozen om zelf een barcodescanner uit te werken in plaats van

gebruik te maken van een verouderde bibliotheek.

3.7.1 AVCaptureMetadataOutput

Door een AVCaptureSession toe te kennen aan een AVCaptureMetadataOutput [23] kan er

metadata uit het beeld van de AVCaptureSession worden gehaald. Om gebruik te maken van

AVCaptureMetadataOutput moet opnieuw de delegate ervan geımplementeerd worden. De

delegate bevat een methode, namelijk captureOutput:didOutputMetadataObjects:fromConnection:

, die wordt aangeroepen bij het detecteren van metadata in de beelden die worden mee-

gegeven aan fromConnection:. Naast het implementeren van de delegate moet ook nog een

AVCaptureSession worden geınitialiseerd.

Page 53: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 44

Listing 3.16: Initialisatie capture session

1 - (void)setupCaptureSession {

2 if (_captureSession) return;

3 _videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

4 if (!_videoDevice) {

5 NSLog(@"No video camera on this device!");

6 return;

7 }

8 _captureSession = [[AVCaptureSession alloc] init];

9 _videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:_videoDevice error:nil];

10

11 if ([_captureSession canAddInput:_videoInput]) {

12 [_captureSession addInput:_videoInput];

13 }

14 _previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];

15 _previewLayer.videoGravity = AVLayerVideoGravityResizeAspect;

16 AVCaptureConnection *previewLayerConnection=_previewLayer.connection;

17

18 if ([previewLayerConnection isVideoOrientationSupported])

19 [previewLayerConnection setVideoOrientation:(AVCaptureVideoOrientation)

20 [[UIApplication sharedApplication] statusBarOrientation]];

21

22 _metadataOutput = [[AVCaptureMetadataOutput alloc] init];

23 dispatch_queue_t metadataQueue =

24 dispatch_queue_create("com.dobcomed.metadata", 0);

25 [_metadataOutput setMetadataObjectsDelegate:self queue:metadataQueue];

26 if ([_captureSession canAddOutput:_metadataOutput]) {

27 [_captureSession addOutput:_metadataOutput];

28 }

29 }

In Listing 3.16 wordt de captureSession geınitialiseerd. Eerst wordt er gekeken of het toe-

stel over een camera beschikt. Indien dit niet het geval is, wordt de methode vroegtijdig

beeindigd. In het andere geval, wordt een captureSession object aangemaakt. Vervolgens

wordt videoInput toegekend aan de captureSession en wordt een previewLayer aangemaakt

zodat de input van de camera zichtbaar is voor de gebruiker. Tot slot wordt er een nieuwe

dispatch queue t aangemaakt om het ontdekken en opvangen van de metadata in de achter-

grond uit te voeren zodat de gebruikersinterface niet geblokkeerd wordt.

3.8 Uploaden van de afbeeldingen

Voor het uploaden van de afbeeldingen wordt er opnieuw gebruik gemaakt van een NSURL-

SessionDataTask . Er bestaat ook een NSURLSessionUploadTask , maar omdat niet toegela-

ten wordt dat de applicatie in de achtergrond draait, is het niet noodzakelijk om gebruik te

maken van een NSURLSessionUploadTask . Een vereiste voor het uploaden van de afbeeldin-

Page 54: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 45

gen is dat dit gepauzeerd en later hervat moet kunnen worden. De reden hiervoor is simpel:

wanneer het internet wegvalt, moet de upload hervat kunnen worden wanneer het internet

terug beschikbaar is. Om het mogelijk te maken dat een upload hervat kan worden, zullen de

afbeeldingen van een sessie een per een verstuurd worden. Op deze manier kan dit worden

aangeduid in de database telkens een afbeelding succesvol geupload. Voor het uploaden van

een afbeelding volstaat het echter niet om enkel de data van de afbeelding aan een NSURL-

SessionDataTask toe te voegen en deze te versturen. Naast de data van de afbeelding zijn er

ook nog andere gegevens nodig. Om te beginnen, moet het session id op de server gekend

zijn. De reden hiervoor is dat alle afbeeldingen van eenzelfde sessie aan eenzelfde study op de

server moeten worden toegekend. Naast het session id zijn er ook nog andere gegevens nodig

voor het aanmaken van een study op de server. Ook deze gegevens zullen bij elke afbeelding

worden meegestuurd naar de server.

3.8.1 Multipart message

Om de gegevens samen met de data van de afbeelding naar de server te uploaden, wordt er

gebruik gemaakt van een multipart bericht. In dit bericht worden de gegevens die gebruikt

worden om een study aan te maken als form data meegegeven. iOS biedt geen mogelijkheid

om een multipart bericht op te stellen dus moet het bericht volledig in code worden opgesteld.

Het eerste wat moet gebeuren, is een NSURLSession aanmaken met de juiste configuratie.

Listing 3.17: NSURLSession aanmaken met juiste configuratie

1 boundary = @"FormBoundary";

2 sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];

3 sessionConfiguration.HTTPAdditionalHeaders =

4 @{

5 @"Accept" : @"application/json",

6 @"Content-Type" : [NSString stringWithFormat:@"multipart/form-data;

7 boundary=%@", boundary],

8 @"Content-Disposition" : @"inline"

9 };

10 sessionConfiguration.HTTPMaximumConnectionsPerHost =

11 NSOperationQueueDefaultMaxConcurrentOperationCount;

12 session = [NSURLSession sessionWithConfiguration:

13 sessionConfiguration delegate:self delegateQueue:nil];

In de bovenstaande methode wordt er eerst een defaultSessionConfiguration object aange-

maakt. Op dit object worden vervolgens een aantal HTTPAdditionalHeaders ingesteld. Deze

headers bepalen dat de data verstuurd worden als json en dat het gaat om form-data die

inline wordt weergegeven. De HTTPMaximumConnectionsPerHost wordt ingesteld met

NSOperationQueueDefaultMaxConcurrentOperationCount waardoor iOS zelf zal onderzoeken hoeveel

connecties er per host worden toegelaten. Tot slot wordt er met deze configuratie een

NSURLSession object aangemaakt. Nu de header is ingesteld, moet ook de body nog worden

Page 55: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 3. Applicatie 46

toegekend aan het bericht en moet er met de sessie nog een NSURLSessionDataTask gecreeerd

worden. In Listing 3.18 is te zien hoe een multipart bericht in code wordt opgesteld.

Listing 3.18: Opbouw multipart body

1 NSMutableData *body = [NSMutableData data];

2 [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary]

3 dataUsingEncoding:NSUTF8StringEncoding]];

4 [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; id=\"id\";

5 name=\"%@\"\r\n\r\n", @"visitId"] dataUsingEncoding:NSUTF8StringEncoding]];

6 [body appendData:[[NSString stringWithFormat:@"%@\r\n", cellTask.session.visitId]

7 dataUsingEncoding:NSUTF8StringEncoding]];

8 [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary]

9 dataUsingEncoding:NSUTF8StringEncoding]];

10 if (imageData) {

11 [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data;

12 id=\"id6\"; name=\"%@\"; filename=\"%@\"\r\n", @"image",

13 [imageName stringByAppendingString:@".png"]] dataUsingEncoding:

14 NSUTF8StringEncoding]];

15 [body appendData:[@"Content-Type: image/png\r\n\r\n"

16 dataUsingEncoding:NSUTF8StringEncoding]];

17 [body appendData:imageData];

18 }

19 [body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary]

20 dataUsingEncoding:NSUTF8StringEncoding]];

Om de methode wat in te korten, zijn de meeste gegevens die nodig zijn om een study aan te

maken weggelaten. De methode toont hoe een gegeven ingesteld wordt als zijnde afkomstig

van een form. Het laatste wat de methode doet, is de data van de afbeelding toevoegen aan

de boodschap. Elk gegeven van de boodschap wordt gescheiden door een boundary om aan

te geven dat er een nieuw stuk komt. Op de server wordt stuk per stuk ingelezen en daarmee

kan een study aangemaakt worden.

Page 56: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 4

Backend

Om de informatie van het ziekenhuis beschikbaar te maken voor de iOS applicatie was er

nood aan een backend. Het reeds bestaande systeem is uitgewerkt in C# en draait op een

IIS7 server. Daarom werd er gekozen om deze backend ook in C# uit te werken.

4.1 ASP.NET Web API

Een Web API [24] is een Application Programming Interface die het mogelijk maakt om aan

de hand van gewone HTTP methoden informatie op te vragen aan de server. ASP.NET Web

API is een ideaal platform om RESTFull applicaties te maken voor het .NET framework .

Het voordeel van een web API is dat het gebruik maakt van HTTP en dat dit platform

onafhankelijk is. Dit brengt met zich mee dat dezelfde webservice gebruikt kan worden mocht

er later beslist worden om ook Android of een ander mobiel platform te ondersteunen.

47

Page 57: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 4. Backend 48

4.2 Database model

Figuur 4.1: Server database model

De visit, image en video tabel zijn identiek aan de lokale tabellen en worden hier niet meer

besproken.

Patient tabel

De patient tabel bevat alle patienten waarvan ooit al eens een onderzoek werd afgenomen in

het ziekenhuis. Van de patient wordt de voornaam, achternaam, geslacht, geboortedatum en

een interne identificatie bijgehouden. Het PatientId wordt automatisch gegenereerd wanneer

er een nieuwe patient aan de tabel wordt toegevoegd.

Studie tabel

Wanneer het uploaden van een sessie via de iOS applicatie van start gaat, zal eerst gekeken

worden of er op de server reeds een study bestaat voor de sessie. Indien dit niet het geval

is, wordt er een nieuw study object aangemaakt. Een study heeft een StudyId , PatientId ,

VisitId , SessionId , RequestingDepartment , RequestingPhysician, AccessionNumber en een

FinishedUploading veld. Het StudyId wordt automatisch gecreeerd bij het aanmaken van

Page 58: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 4. Backend 49

een nieuw study object. De PatientId verwijst naar het patient object uit de patient tabel.

Het VisitId wijst op zijn beurt naar het visit object van de visit tabel. Het uploaden van

de verschillende sessies verloopt asynchroon. Vandaar dat er bijgehouden wordt in de study

over welke sessie het gaat zodat de afbeeldingen aan de juiste study worden toegevoegd. De

volgende twee velden bevatten de aanvragende arts en het aanvragende departement. Het

AccessionNumber is een nummer dat noodzakelijk is voor de DICOM-bestanden. Het nummer

begint met de letters MF (medische fotografie), gevolgd door een oplopend getal bestaande

uit zes cijfers. Tot slot bevat deze tabel ook nog een boolean veld FinishedUploading dat

aanduidt wanneer de sessie volledig geupload is zodat de afbeeldingen die verbonden zijn met

deze study omgezet kunnen worden naar DICOM-bestanden.

4.2.1 PostFormData methode

De PostFormData methode is de methode die wordt opgeroepen wanneer een sessie geupload

moet worden. Wanneer deze methode wordt aangeroepen, wordt eerst gecontroleerd of het wel

degelijk om een multipart bericht gaat (2). Indien dit niet het geval is, zal de webservice een

gepaste HTTP code terugsturen naar de iOS applicatie (3). De methode haalt vervolgens het

pad naar de map op waar de afbeeldingen zullen worden opgeslagen (5) en maakt een provider

object aan (6). Het provider object is een CustomMultiPartFormDataStreamProvider object.

Het is een object, dat overerft van MultipartFormDataStreamProvider . Het wordt gebruikt

om streams te reserveren voor de bestanden die geupload worden en de form data van het

bericht in te lezen (14-24). Hoe dit in code gebeurt, is te zien in Listing 4.1.

Page 59: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 4. Backend 50

Listing 4.1: PostFormData methode

1 public HttpResponseMessage PostFormData(){

2 if (!Request.Content.IsMimeMultipartContent()){

3 throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);

4 }

5 string root = HttpContext.Current.Server.MapPath("~/Upload");

6 var provider = new CustomMultipartFormDataStreamProvider(root);

7 try{

8 Task.Run(async () => await Request.Content.ReadAsMultipartAsync(provider))

9 .Wait();

10 int visitId;

11 int sessionId;

12 string requestingDepartment;

13 string requestingPhysician;

14 int patientId;

15 if (!int.TryParse(provider.FormData["visitId"], out visitId)){

16 Trace.WriteLine("Error parsing visitId");

17 }

18 if (!int.TryParse(provider.FormData["sessionId"], out sessionId)){

19 Trace.WriteLine("Error parsing sessionId");

20 }

21 requestingDepartment = provider.FormData["requestingDepartment"];

22 requestingPhysician = provider.FormData["requestingPhysician"];

23 if (!int.TryParse(provider.FormData["patientId"], out patientId)){

24 Trace.WriteLine("Error parsing patientId");

25 }

26 string savePath = root + "\\" + provider.FileData.First().

27 Headers.ContentDisposition.FileName.Replace("\"", "");

28 if (StudyExistsWithSessionId(sessionId)){

29 //Afbeelding aan bestaande study toevoegen

30 }else{

31 //Nieuwe study maken en afbeelding aan toevoegen

32 }

33 }

34 catch (System.Exception e){

35 return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);

36 }

37 }

Om de methode wat overzichtelijk te houden, werden twee grote stukken weggelaten. Het

eerste stuk code zorgt ervoor dat de afbeelding aan de study wordt toegevoegd, indien deze

reeds bestaat. Het tweede stuk code dat weggelaten is, is verantwoordelijk voor het aanmaken

van een nieuwe study . Deze situatie zal zich voordoen wanneer er een afbeelding geupload

wordt met een SessionId waarvoor geen study wordt teruggevonden. In wat volgt zal er dieper

worden ingegaan op deze twee stukken code.

Page 60: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 4. Backend 51

Listing 4.2: Afbeelding aan een bestaande sessie toevoegen

1 Study study = (from s in db.Studies where s.SessionId.Equals(sessionId) select s).

2 FirstOrDefault();

3 Image image = new Image();

4 image.Imagepath = savePath;

5 study.Images.Add(image);

6 if (!ModelState.IsValid){

7 return Request.CreateResponse(HttpStatusCode.BadRequest);

8 }

9 db.Entry(study).State = EntityState.Modified;

10 try{

11 db.SaveChanges();

12 }

13 catch (DbUpdateConcurrencyException){

14 if (!StudyExistsWithSessionId(sessionId)){

15 return Request.CreateResponse(HttpStatusCode.NotFound);

16 } else {

17 throw;

18 }

19 }

20 return Request.CreateResponse(HttpStatusCode.OK);

In Listing 4.2 is te zien hoe er een nieuw Image object wordt gemaakt en aan een bestaande

study wordt toegevoegd. Alvorens de afbeelding toe te voegen aan de study moet eerst de

ImagePath eigenschap ervan ingevuld zijn. Vervolgens wordt de EntityState van het study

object op modified gezet zodat bij de aanroep van db.SaveChanges() de aanpassingen worden

opgeslagen.

De methode in Listing 4.3 maakt eerst een nieuwe study aan. Vervolgens worden alle

eigenschappen van dit object ingevuld met de informatie die afkomstig is uit de form data.

Het AccessionNumber moet een unieke code zijn. Deze code begint met MF en wordt aange-

vuld door een getal van zes cijfers. Er wordt eerst nagegaan of er al studies bestaan. Indien

dit niet het geval is, mag de suffix van de code uit zes nullen bestaan. Wanneer er wel al

studies bestaan, zal de laatste study worden opgehaald en zal het AccessionNumber in tweeen

gesplitst worden. Hierdoor kan het tweede deel als een getal geınterpreteerd en verhoogd

worden. Het laatste stuk maakt een nieuwe afbeelding en voegt deze aan de study stoe.

Page 61: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 4. Backend 52

Listing 4.3: Nieuwe sessie aanmaken en afbeelding toevoegen

1 Study study = new Study();

2 study.SessionId = sessionId;

3 study.PatientId = patientId;

4 study.VisitId = visitId;

5 study.RequestingDepartment = requestingDepartment;

6 study.RequestingPhysician = requestingPhysician;

7 if (db.Studies.Count() == 0){

8 study.AccessionNumber = "MF000000";

9 } else {

10 Study lastStudy = (from s in db.Studies select s).

11 OrderByDescending(stu => stu.StudyId).FirstOrDefault();

12 int suffix = int.Parse(lastStudy.AccessionNumber.Substring(2)) + 1;

13 int lengte = (suffix + "").Length;

14 string tekstSuffix = suffix + "";

15 for (int i = lengte; i < 6; i++){

16 tekstSuffix = "0" + tekstSuffix;

17 }

18 study.AccessionNumber = "MF" + tekstSuffix;

19 }

20 Image image = new Image();

21 image.Imagepath = savePath;

22 study.Images.Add(image);

23 if (!ModelState.IsValid){

24 return Request.CreateResponse(HttpStatusCode.BadRequest);

25 }

26 db.Studies.Add(study);

27 db.SaveChanges();

28 return Request.CreateResponse(HttpStatusCode.OK);

Page 62: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 5

Integratie van de applicaties

5.1 Huidige situatie

Parallel met iSentToPacs is er nog een andere applicatie ontwikkeld, namelijk iPacsOnWeb.

iPacsOnWeb is een applicatie ontwikkeld door mijn collega-student Pieter-Jan Van Robays en

functioneert als de alternatieve native applicatie van de website PacsOnWeb. Beide applicaties

zijn gemaakt binnen hetzelfde bedrijf en zijn bestemd voor de medische sector. Na overleg is

er besloten om het inloggedeelte van de beide applicaties samen te maken, zodat dit volledig

gelijklopend is. Desondanks het volledig gelijklopend zijn van het inloggedeelte, zijn deze

toch van elkaar gescheiden en zal een gebruiker die geregistreerd is bij de ene applicatie niet

kunnen inloggen op de andere applicatie. Omwille van deze reden wordt de mogelijkheid

onderzocht om het inloggedeelte van de applicaties gemeenschappelijk te maken.

5.2 Probleemstelling

Momenteel heeft elke applicatie zijn afzonderlijk inloggedeelte. Het zou handig zijn dat een

gebruiker die geregistreerd is bij de ene applicatie ook toegang zou hebben tot de andere

applicatie. iOS maakt echter gebruik van het sandbox principe. Dit betekent dat een appli-

catie niet is toegestaan om informatie weg te schrijven buiten de ruimte die aan de applicatie

is toegestaan. Het is dus ook niet mogelijk om van buiten een applicatie informatie weg te

schrijven binnen de sandbox van een applicatie. Enkel de applicatie zelf kan informatie weg-

schrijven binnen zijn sandbox . De applicaties zijn echter ontwikkeld voor twee verschillende

doelgroepen en dit is dan ook de reden waarom dit onderzoek niet is uitgewerkt.

5.3 Delen van logingegevens tussen applicaties

Voor het delen van logingegevens is de oplossing niet zo moeilijk. Doordat het inloggen op de

beide applicaties volledig gelijklopend is, maken beide applicaties gebruik van een keychain.

53

Page 63: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 5. Integratie van de applicaties 54

Wanneer er nood is om keychain gegevens te delen over verschillende applicaties kan er gebruik

gemaakt worden van een gedeelde keychain. Indien dit zou worden toegepast, zouden beide

applicaties toegang hebben tot de logingegevens. Hierdoor is de gebruiker in staat om op

beide applicaties in te loggen terwijl hij zich slechts op een applicatie heeft geregistreerd.

5.4 Delen van andere data tussen applicaties

In beide applicaties wordt er gebruik gemaakt van een user object die een aantal gegevens

van de ingelogde gebruiker bijhoudt. Deze gegevens zijn niet geschikt om bij te houden in een

keychain en zijn dan ook opgeslagen in een lokale database die zich binnen de sandbox van

de applicatie bevindt. Het spreekt voor zich dat de gebruiker niet van de applicatie gebruik

zal kunnen maken wanneer hij kan inloggen, maar er voor deze gebruiker geen user object

aanwezig is. Er moet dus gezocht worden naar een manier om het user object tussen de

applicaties uit te wisselen. iOS ondersteunt verschillende mogelijkheden om data te delen

tussen applicaties, maar er zijn er slechts enkele die in aanmerking komen om ons probleem

op te lossen.

5.4.1 Webservice

Een eerste mogelijkheid zou een webservice kunnen zijn die het user object online op de server

bijhoudt. Zo zouden beide applicaties bij het inloggen kunnen nagaan of ze lokaal over het

gebruikersobject beschikken. Indien dit niet het geval is, kan het object opgehaald worden

van de server. Het probleem met deze mogelijke oplossing is dat er internet beschikbaar moet

zijn. Wanneer er geen internet is, kan er niet nagegaan worden of dit gebruikersobject op de

server reeds bestaat en zal de gebruiker niet kunnen inloggen op de applicatie die nog niet

over het gebruikersobject beschikt.

5.4.2 Custom URL Schemes

Wanneer een applicatie custom URL schemes [25] ondersteunt kunnen andere applicaties die

over deze URL beschikken boodschappen naar deze applicatie sturen. Het voordeel van deze

manier is dat er geen internet beschikbaar hoeft te zijn. Het nadeel ervan is dat de data

base64 geencodeerd moet zijn en dat deze geencodeerde data karakters kan bevatten die niet

in een URL mogen voorkomen.

5.4.3 UIPasteBoard

Een pasteboard laat toe om data te delen tussen applicaties. De meeste gebruikers komen in

aanraking met het pasteboard wanneer ze gegevens van de ene applicatie kopieren naar een

andere applicatie. Er zijn drie verschillende soorten pasteboards:

Page 64: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Hoofdstuk 5. Integratie van de applicaties 55

• General pasteboard

• Find pasteboard

• Custom pasteboard

Wanneer men data wil delen die eigen is aan een applicatie, wordt er het best gebruik gemaakt

van een custom pastboard . De reden hiervoor is omdat het general pasteboard reeds andere

data kan bevatten en dat de gebruiker niet expliciet kopieer- en plakacties zal uitvoeren, maar

dat dit achter de schermen gebeurt. Pasteboards zijn in staat om data bij te houden zelfs

wanneer de applicatie die de data er heeft opgezet wordt afgesloten. Ook wanneer het toestel

wordt afgesloten, zal het pasteboard de data niet verliezen.

5.5 Conclusie

Het delen van de inloggegevens brengt geen enkel probleem met zich mee. Met behulp van een

gemeenschappelijke keychain kunnen de inloggegevens eenvoudig gedeeld worden. Voor het

delen van het user object zijn er een aantal verschillende mogelijkheden: webservice, custom

URL schemes en UIPasteBoard . Om gebruik te maken van een webservice moet er altijd

internet beschikbaar zijn. Aangezien de applicatie ook offline moet kunnen werken is deze

optie niet geschikt. Alle data toevoegen aan een URL en dit base64 encoderen is wel een

mogelijkheid, maar als de data karakters bevat die niet in de URL mogen voorkomen zal dit

problemen opleveren. Mocht er dus beslist worden om de inloggedeeltes te integreren gaat

de voorkeur uit naar eencustom pasteboard omdat dit offline beschikbaar is, gelijk welke data

kan bevatten en de data bewaard zelf na het afsluiten van het toestel.

Page 65: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Conclusie

De performantie van vier verschillende mobiele technologieen (iOS, PhoneGap, Android,

HTML5) werd vergeleken door te kijken naar het verschil in het aantal frames per seconde

die de technologie weergeeft bij het aanpassen van de helderheid van de afbeelding. Bij iOS

werden 55 frames per seconde behaald en bij iOS met OpenCV werd een gelijkaardig resultaat

vastgesteld. Android gaf maximaal 46 frames per seconde weer, terwijl HTML5 en Phone-

Gap slechts 30 en 22 frames per seconde respectievelijk behaalden. Aan de hand van deze

resultaten werd uiteindelijk gekozen voor iOS.

De eerste stap, namelijk de authenticatie ten opzichte van de server, werd uitgewerkt in

samenwerking met Pieter-Jan Van Robays. Om de beveiliging van de applicatie te garande-

ren werden de bestanden geencrypteerd en de credentials (gebruikersnaam en wachtwoord)

opgeslagen in een keychain. Het bewerken van foto′s werd gerealiseerd met een bestaande

bibliotheek, die in verschillende bewerkingsmogelijkheden zoals inzoomen, bijsnijden en ro-

teren voorziet. De barcodescanner werd uitgewerkt met de iOS 7 technologie omdat de

voorgestelde bibliotheek reeds verouderd is. Ten slotte maaktte de backend het mogelijk dat

aan de hand van de barcode een patient met zijn onderzoek kon worden opgehaald en dat de

foto′s geupload konden worden.

Ter afsluiting van deze masterproef werd besproken hoe zowel logingegevens als andere data

tussen applicaties gedeeld kunnen worden. Om logingegevens te delen, kan gebruik gemaakt

worden van een gemeenschappelijke keychain. Bij het delen van andere data werden drie

mogelijkheden toegelicht: Webservice, Custom URL Schemes, UIPasteBoard. Tot slot moet

nog worden vermeld dat de backend tijdens de ontwikkeling van de applicatie slechts lokaal

gebruikt werd en uiteindelijk op de server van het bedrijf actief zal worden.

56

Page 66: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Bijlage A

OpenCV linken met iOS

Om OpenCV met iOS te linken moeten er een aantal stappen ondernomen worden. Eerst

moet OpenCV gedownload worden van GitHub [26]. Vervolgens moet het OpenCV framework

gebuild worden. Dit kan door in het terminal venster de volgende commando’s in te geven:

Listing A.1: Build OpenCV framework

1 cd home/myWorkingDirectory

2 python opencv/platforms/ios/build_framework.py ios

Als alles goed verloopt staat het framework in de volgende map:

home/myWorkingDirectory/ios/opencv2.framework. De volgende stap is het framework toe-

voegen aan het iOS project. Dit kan door het OpenCV framework te slepen naar de Fra-

meworks map van het project. Als laatste stap moet het volgende stukje code toegevoegd

worden aan de projectnaam-Prefix.pch header file.

Listing A.2: Import OpenCV

1 #ifdef __cplusplus

2 #import <opencv2/opencv.hpp>

3 #endif

Verder mag men in de code niet vergeten aan te duiden dat C++ wordt gebruikt zodat de

compiler weet wanneer hij een andere taal dan Objective-C moet interpreteren. Dit wordt

aangeduid zoals in listing A.2 te zien is.

57

Page 67: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Bijlage B

Aangepaste keychain wrapper

Listing B.1: Aangepaste keychain wrapper

1 #import "KeychainItemWrapper.h"

2 #import <Security/Security.h>

3 @interface KeychainItemWrapper (PrivateMethods)

4 - (NSMutableDictionary *)secItemFormatToDictionary:(NSDictionary *)dictionaryToConvert;

5 - (NSMutableDictionary *)dictionaryToSecItemFormat:(NSDictionary *)dictionaryToConvert;

6 - (void)writeToKeychain;

7 @end

8 @implementation KeychainItemWrapper

9 @synthesize keychainItemData, genericPasswordQuery;

10 - (id)initWithAccount:(NSString *)account

11 service:(NSString *)service accessGroup:(NSString *) accessGroup;

12 {

13 if (self = [super init])

14 {

15 NSAssert(account != nil || service != nil,

16 [genericPasswordQuery setObject:(id)kSecClassGenericPassword forKey:

17 (id)kSecClass];

18 [genericPasswordQuery setObject:account forKey:(id)kSecAttrAccount];

19 [genericPasswordQuery setObject:service forKey:(id)kSecAttrService];

20 if (accessGroup != nil)

21 {

22 [genericPasswordQuery setObject:accessGroup forKey:(id)kSecAttrAccessGroup];

23 }

24 [genericPasswordQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];

25 [genericPasswordQuery setObject:

26 (id)kCFBooleanTrue forKey:(id)kSecReturnAttributes];

27 NSDictionary *tempQuery =

28 [NSDictionary dictionaryWithDictionary:genericPasswordQuery];

29 NSMutableDictionary *outDictionary = nil;

30 if (! SecItemCopyMatching((CFDictionaryRef)tempQuery,

31 (CFTypeRef *)&outDictionary) == noErr)

32 {

58

Page 68: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Bijlage B. Aangepaste keychain wrapper 59

33 [self resetKeychainItem];

34 [keychainItemData setObject:account forKey:(id)kSecAttrAccount];

35 [keychainItemData setObject:service forKey:(id)kSecAttrService];

36 if (accessGroup != nil)

37 {

38 [keychainItemData setObject:accessGroup forKey:(id)kSecAttrAcces sGroup];

39 }

40 }

41 else

42 {

43 self.keychainItemData = [self secItemFormatToDictionary:outDictionary];

44 }

45 [outDictionary release];

46 }

47 return self;

48 }

49

50 - (void)dealloc

51 {

52 [keychainItemData release];

53 [genericPasswordQuery release];

54 [super dealloc];

55 }

56

57 - (void)setObject:(id)inObject forKey:(id)key

58 {

59 if (inObject == nil) return;

60 id currentObject = [keychainItemData objectForKey:key];

61 if (![currentObject isEqual:inObject])

62 {

63 [keychainItemData setObject:inObject forKey:key];

64 [self writeToKeychain];

65 }

66 }

67

68 - (id)objectForKey:(id)key

69 {

70 return [keychainItemData objectForKey:key];

71 }

72

73 - (NSString *) passwordForUserName:(NSString *)serviceName

74 username:(NSString *) username found:(BOOL *)found{

75 NSMutableDictionary *query = [NSMutableDictionary dictionaryWithObjectsAndKeys:

76 (__bridge id)(kSecClassGenericPassword), kSecClass,

77 serviceName, kSecAttrService,

78 username, kSecAttrAccount,

79 kCFBooleanTrue, kSecReturnData, nil];

80 NSData * data = NULL;

Page 69: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Bijlage B. Aangepaste keychain wrapper 60

81 OSStatus status =

82 SecItemCopyMatching((__bridge CFDictionaryRef)(query), (CFTypeRef *)&data);

83 *found = status != errSecItemNotFound;

84 NSString *password = [[NSString alloc] initWithData:

85 (__bridge NSData *)(data) encoding:NSUTF8StringEncoding];

86 return password;

87 }

88

89 - (NSString *) pincodeForUserName:(NSString *)serviceName

90 username:(NSString *) username found:(BOOL *)found{

91 NSMutableDictionary *query = [NSMutableDictionary dictionaryWithObjectsAndKeys:

92 (__bridge id)(kSecClassGenericPassword), kSecClass,

93 serviceName, kSecAttrService,

94 username, kSecAttrAccount,

95 kCFBooleanTrue, kSecReturnData, nil];

96 NSData * data = NULL;

97 OSStatus status =

98 SecItemCopyMatching((__bridge CFDictionaryRef)(query), (CFTypeRef *)&data);

99 *found = status != errSecItemNotFound;

100 NSString *pincode = [[NSString alloc]

101 initWithData:(__bridge NSData *)(data) encoding:NSUTF8StringEncoding];

102 return pincode;

103 }

104

105 - (void)resetKeychainItem

106 {

107 OSStatus junk = noErr;

108 if (!keychainItemData)

109 {

110 self.keychainItemData = [[NSMutableDictionary alloc] init];

111 }

112 else if (keychainItemData)

113 {

114 NSMutableDictionary *tempDictionary =

115 [self dictionaryToSecItemFormat:keychainItemData];

116 junk = SecItemDelete((CFDictionaryRef)tempDictionary);

117 NSAssert( junk == noErr || junk == errSecItemNotFound,

118 @"Problem deleting current dictionary." );

119 }

120 [keychainItemData setObject:@"" forKey:(id)kSecAttrAccount];

121 [keychainItemData setObject:@"" forKey:(id)kSecAttrLabel];

122 [keychainItemData setObject:@"" forKey:(id)kSecAttrDescription];

123

124 [keychainItemData setObject:@"" forKey:(id)kSecValueData];

125 }

126

127 - (NSMutableDictionary *)dictionaryToSecItemFormat:(NSDictionary *)dictionaryToConvert

128 {

Page 70: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Bijlage B. Aangepaste keychain wrapper 61

129 NSMutableDictionary *returnDictionary =

130 [NSMutableDictionary dictionaryWithDictionary:dictionaryToConvert];

131

132 [returnDictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];

133

134 NSString *passwordString = [dictionaryToConvert objectForKey:(id)kSecValueData];

135 [returnDictionary setObject:

136 [passwordString dataUsingEncoding:NSUTF8StringEncoding] forKey:(id)kSecValueData];

137

138 return returnDictionary;

139 }

140

141 - (NSMutableDictionary *)secItemFormatToDictionary:(NSDictionary *)dictionaryToConvert

142 {

143 NSMutableDictionary *returnDictionary =

144 [NSMutableDictionary dictionaryWithDictionary:dictionaryToConvert];

145

146 [returnDictionary setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];

147 [returnDictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];

148

149 NSData *passwordData = NULL;

150 if (SecItemCopyMatching((CFDictionaryRef)returnDictionary,

151 (CFTypeRef *)&passwordData) == noErr) {

152 [returnDictionary removeObjectForKey:(id)kSecReturnData];

153 NSString *password = [[[NSString alloc] initWithBytes:

154 [passwordData bytes] length:[passwordData length]

155 encoding:NSUTF8StringEncoding] autorelease];

156 [returnDictionary setObject:password forKey:(id)kSecValueData];

157 }

158 else {

159 NSAssert(NO, @"Serious error, no matching item found in the keychain.\n");

160 }

161

162 [passwordData release];

163

164 return returnDictionary;

165 }

166

167 - (void)writeToKeychain

168 {

169 NSDictionary *attributes = NULL;

170 NSMutableDictionary *updateItem = NULL;

171 OSStatus result;

172

173 if (SecItemCopyMatching((CFDictionaryRef)genericPasswordQuery,

174 (CFTypeRef *)&attributes) == noErr){

175 updateItem = [NSMutableDictionary dictionaryWithDictionary:attributes];

176 [updateItem setObject:

Page 71: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Bijlage B. Aangepaste keychain wrapper 62

177 [genericPasswordQuery objectForKey:(id)kSecClass] forKey:(id)kSecClass];

178 NSMutableDictionary *tempCheck = [self dictionaryToSecItemFormat:

179 keychainItemData];

180 [tempCheck removeObjectForKey:(id)kSecClass];

181 [tempCheck removeObjectForKey:(id)kSecAttrAccessGroup];

182 result = SecItemUpdate((CFDictionaryRef)updateItem, (CFDictionaryRef)tempCheck);

183 NSAssert( result == noErr, @"Couldn’t update the Keychain Item." );

184 }

185 else

186 {

187 result = SecItemAdd((CFDictionaryRef)

188 [self dictionaryToSecItemFormat:keychainItemData], NULL);

189 NSAssert( result == noErr, @"Couldn’t add the Keychain Item." );

190 }

191 }

192 @end

Page 72: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Bijlage C

Herstellen van de orientatie van een

afbeelding

Listing C.1: Herstellen orientatie afbeelding

1 - (UIImage *)fixOrientation:(UIImage *)image {

2

3 if (image.imageOrientation == UIImageOrientationUp) return image;

4 CGAffineTransform transform = CGAffineTransformIdentity;

5 switch (image.imageOrientation) {

6 case UIImageOrientationDown:

7 case UIImageOrientationDownMirrored:

8 transform = CGAffineTransformTranslate(transform, image.size.width,

9 image.size.height);

10 transform = CGAffineTransformRotate(transform, M_PI);

11 break;

12

13 case UIImageOrientationLeft:

14 case UIImageOrientationLeftMirrored:

15 transform = CGAffineTransformTranslate(transform, image.size.width, 0);

16 transform = CGAffineTransformRotate(transform, M_PI_2);

17 break;

18

19 case UIImageOrientationRight:

20 case UIImageOrientationRightMirrored:

21 transform = CGAffineTransformTranslate(transform, 0, image.size.height);

22 transform = CGAffineTransformRotate(transform, -M_PI_2);

23 break;

24 case UIImageOrientationUp:

25 case UIImageOrientationUpMirrored:

26 break;

27 }

28 switch (image.imageOrientation) {

29 case UIImageOrientationUpMirrored:

63

Page 73: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Bijlage C. Herstellen van de orientatie van een afbeelding 64

30 case UIImageOrientationDownMirrored:

31 transform = CGAffineTransformTranslate(transform, image.size.width, 0);

32 transform = CGAffineTransformScale(transform, -1, 1);

33 break;

34

35 case UIImageOrientationLeftMirrored:

36 case UIImageOrientationRightMirrored:

37 transform = CGAffineTransformTranslate(transform, image.size.height, 0);

38 transform = CGAffineTransformScale(transform, -1, 1);

39 break;

40 case UIImageOrientationUp:

41 case UIImageOrientationDown:

42 case UIImageOrientationLeft:

43 case UIImageOrientationRight:

44 break;

45 }

46 CGContextRef ctx = CGBitmapContextCreate(NULL, image.size.width, image.size.height,

47 CGImageGetBitsPerComponent(image.CGImage), 0,

48 CGImageGetColorSpace(image.CGImage),

49 CGImageGetBitmapInfo(image.CGImage));

50 CGContextConcatCTM(ctx, transform);

51 switch (image.imageOrientation) {

52 case UIImageOrientationLeft:

53 case UIImageOrientationLeftMirrored:

54 case UIImageOrientationRight:

55 case UIImageOrientationRightMirrored:

56 CGContextDrawImage(ctx, CGRectMake(0,0,image.size.height,

57 image.size.width), image.CGImage);

58 break;

59

60 default:

61 CGContextDrawImage(ctx, CGRectMake(0,0,image.size.width,

62 image.size.height), image.CGImage);

63 break;

64 }

65 CGImageRef cgimg = CGBitmapContextCreateImage(ctx);

66 UIImage *img = [UIImage imageWithCGImage:cgimg];

67 CGContextRelease(ctx);

68 CGImageRelease(cgimg);

69 return img;

70 }

Page 74: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Bibliografie

[1] Dobcomed. PacsOnWeb. url: http://www.dobcomed.com/pacsonweb/nl/home.php.

[2] Henning Heitkotter, Sebastian Hanschke en Tim A. Majchrzak. “Evaluating Cross-

Platform Development Approaches for Mobile Applications”. In: Web Information Sys-

tems and Technologies. Red. door Jose Cordeiro en Karl-Heinz Krempels. Deel 140.

Lecture Notes in Business Information Processing. Springer Berlin Heidelberg, 2013,

p. 120–138. isbn: 978-3-642-36607-9. doi: 10.1007/978- 3- 642- 36608- 6_8. url:

http://dx.doi.org/10.1007/978-3-642-36608-6_8.

[3] Apple. Core Image Programming Guide. url: https : / / developer . apple . com /

library / ios / documentation / graphicsimaging / Conceptual / CoreImaging / ci _

tasks/ci_tasks.html#//apple_ref/doc/uid/TP30001185-CH3-SW19.

[4] Apple. Core Image Filter Reference. url: https://developer.apple.com/library/

ios / documentation / graphicsimaging / Reference / CoreImageFilterReference /

Reference/reference.html#//apple_ref/doc/uid/TP40004346.

[5] Apple. Dispatch Queue. url: https://developer.apple.com/library/ios/documentation/

General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.

html#//apple_ref/doc/uid/TP40008091-CH102-SW2.

[6] OpenCV. UIImage naar Mat. url: http://docs.opencv.org/doc/tutorials/ios/

image_manipulation/image_manipulation.html.

[7] Phonegap. Phonegap. url: http://phonegap.com/.

[8] HTML5 rocks. Image Filter with canvas. url: http://www.html5rocks.com/en/

tutorials/canvas/imagefilters/.

[9] Apache. Apache installatie. url: http : / / apache . belnet . be / httpd / binaries /

win32/.

[10] Google Play. FPS Meter. url: https://play.google.com/store/apps/details?id=

com.aatt.fpsm&hl=nl.

[11] howtogeek. Root Android. url: http://www.howtogeek.com/115297/how-to-root-

your-android-why-you-might-want-to/.

65

Page 75: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Bibliografie 66

[12] Google Chrome. Remote Debugging. url: https://developers.google.com/chrome-

developer-tools/docs/remote-debugging#remote-debugging.

[13] Microsoft. ASP.NET Authentication. url: http://msdn.microsoft.com/en- us/

library/eeyk640h(v=vs.100).aspx.

[14] Microsoft. ASP.NET Forms Authentication. url: http://msdn.microsoft.com/en-

us/library/7t6b43z4.ASPX.

[15] Microsoft. ASPXAUTH Cookie. url: http://msdn.microsoft.com/en-us/library/

ee920427.aspx.

[16] Microsoft. ASP.NET State Management Overview. url: http://msdn.microsoft.

com/en-us/library/75x4ha6s(v=vs.100).aspx.

[17] Apple. NSURLConnection. url: https://developer.apple.com/library/mac/

documentation/cocoa/reference/foundation/classes/NSURLConnection_Class/

Reference/Reference.html#//apple_ref/doc/uid/20001697-387826.

[18] Apple. URL Loading System Programming Guide. url: https://developer.apple.

com/library/mac/documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/

UsingNSURLConnection.html.

[19] Apple. NSURLSession. url: https://developer.apple.com/library/ios/documentation/

Foundation/Reference/NSURLSession_class/Introduction/Introduction.html.

[20] Rachid El Khayari Jens Heider. iOS Keychain Weakness FAQ. url: https://www.

sit.fraunhofer.de/fileadmin/dokumente/sonstiges/iPhone_keychain_faq.pdf.

[21] Apple. iOS Keychain Wrapper. url: https : / / developer . apple . com / library /

ios/samplecode/GenericKeychain/Listings/Classes_KeychainItemWrapper_m.

html#//apple_ref/doc/uid/DTS40007797- Classes_KeychainItemWrapper_m-

DontLinkElementID_10.

[22] Apple. iOS UIImagePickerController. url: https://developer.apple.com/library/

ios/documentation/uikit/reference/UIImagePickerController_Class/UIImagePickerController/

UIImagePickerController.html.

[23] Apple. iOS AVCaptureMetadataOutput. url: https://developer.apple.com/library/

ios/documentation/AVFoundation/Reference/AVCaptureMetadataOutput/Reference/

Reference.html.

[24] Microsoft. ASP.NET Web API. url: http://msdn.microsoft.com/en-us/library/

hh833994(v=vs.108).aspx.

[25] Apple. Custom URL Schemes. url: https://developer.apple.com/library/ios/

documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/AdvancedAppTricks/

AdvancedAppTricks.html#//apple_ref/doc/uid/TP40007072-CH7-SW50.

Page 76: Opnemen en registreren van medische foto´s via een mobile applib.ugent.be/fulltxt/RUG01/002/154/022/RUG01... · 1.3 Mobiele webapplicaties Mobiele webapplicaties (Web apps) ge mplementeerd

Bibliografie 67

[26] OpenCV. OpenCV linken met iOS. url: http://docs.opencv.org/doc/tutorials/

ios/hello/hello.html#opencvioshelloworld.