├── .gitignore ├── IDEAS.txt ├── LICENSE.txt ├── PixlView.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── sveinbjorn.xcuserdatad │ │ └── WorkspaceSettings.xcsettings └── xcuserdata │ └── sveinbjorn.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── PixlView ├── AppDelegate.h ├── AppDelegate.m ├── Base.lproj │ ├── MainMenu.xib │ └── PixlDoc.xib ├── Constants.h ├── GLPixelView.h ├── GLPixelView.m ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── PixelBuffer.h ├── PixelBuffer.m ├── PixlDoc.h ├── PixlDoc.m ├── PixlDocWindowController.h ├── PixlDocWindowController.m ├── TB_zoomIn.pdf ├── TB_zoomOut.pdf ├── ZoomableClipView.h ├── ZoomableClipView.m ├── assets │ ├── zoom-cursor.psd │ └── zoom-out-cursor.png ├── en.lproj │ └── PixlDoc.strings ├── icon │ ├── PixlViewIcon.ai │ ├── PixlViewIcon.icns │ ├── PixlViewIcon.psd │ └── PixlViewerIcon.iconset │ │ ├── icon_128x128.png │ │ ├── icon_128x128@2x.png │ │ ├── icon_16x16.png │ │ ├── icon_16x16@2x.png │ │ ├── icon_256x256.png │ │ ├── icon_256x256@2x.png │ │ ├── icon_32x32.png │ │ ├── icon_32x32@2x.png │ │ ├── icon_512x512.png │ │ └── icon_512x512@2x.png ├── images │ ├── small-zoom-cursor.png │ └── small-zoom-in-cursor.png ├── main.m ├── resolutions.plist └── resolutions.txt ├── README.md ├── binaries └── PixlView.zip └── screenshots ├── appicon.jpg ├── screenshot1.png └── screenshot2.png /.gitignore: -------------------------------------------------------------------------------- 1 | *.xcuserstate 2 | UserInterfaceState.xcuserstate 3 | *dsa_priv.pem 4 | Platypus.build 5 | BuildData 6 | .DS_Store 7 | *.swp 8 | *~.nib 9 | *.pbxuser 10 | *.perspective 11 | *.perspectivev3 12 | *.mode1v3 13 | *.mode2v3 14 | *.xcodeproj/xcuserdata/*.xcuserdatad 15 | *.xcodeproj/project.xcworkspace/xcuserdata/*.xcuserdatad 16 | xcuserdata/ 17 | platypus.man.html 18 | *UserInterfaceState.xcuserstate 19 | .DS_Store 20 | build/ 21 | *.pbxuser 22 | !default.pbxuser 23 | *.mode1v3 24 | !default.mode1v3 25 | *.mode2v3 26 | !default.mode2v3 27 | *.perspectivev3 28 | !default.perspectivev3 29 | *.xcworkspace 30 | !default.xcworkspace 31 | xcuserdata 32 | profile 33 | *.moved-aside 34 | DerivedData 35 | .idea/ 36 | Pods 37 | 38 | -------------------------------------------------------------------------------- /IDEAS.txt: -------------------------------------------------------------------------------- 1 | 2 | Ideas for further development: 3 | 4 | * Safe GL usage 5 | * CLI parameters for interpreting data file. Integrate into debug process. Pretty cool, eh? 6 | * Alternate drawing implementations 7 | * Support for more pixel formats (more planar formats etc.) 8 | * Preset popup should show when current res fits no preset 9 | * Cursors to zoom in/out, option-click to zoom out 10 | * Exponential zoom using cursor 11 | * Support export to multiple formats -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | License 2 | 3 | PixlView - Copyright (c) Sveinbjorn Thordarson All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | 9 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | 11 | Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 | -------------------------------------------------------------------------------- /PixlView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | F40068681B3A0AAA00961B42 /* small-zoom-cursor.png in Resources */ = {isa = PBXBuildFile; fileRef = F40068661B3A0AAA00961B42 /* small-zoom-cursor.png */; }; 11 | F40068691B3A0AAA00961B42 /* small-zoom-in-cursor.png in Resources */ = {isa = PBXBuildFile; fileRef = F40068671B3A0AAA00961B42 /* small-zoom-in-cursor.png */; }; 12 | F400686D1B3A0CB900961B42 /* ZoomableClipView.m in Sources */ = {isa = PBXBuildFile; fileRef = F400686C1B3A0CB900961B42 /* ZoomableClipView.m */; }; 13 | F46AB9361B3738AB00CEB288 /* resolutions.plist in Resources */ = {isa = PBXBuildFile; fileRef = F46AB9351B3738AB00CEB288 /* resolutions.plist */; }; 14 | F46AB9681B375BD800CEB288 /* PixlDoc.m in Sources */ = {isa = PBXBuildFile; fileRef = F46AB9671B375BD800CEB288 /* PixlDoc.m */; }; 15 | F46AB96B1B375BED00CEB288 /* PixlDoc.xib in Resources */ = {isa = PBXBuildFile; fileRef = F46AB9691B375BED00CEB288 /* PixlDoc.xib */; }; 16 | F46AB96E1B375DB300CEB288 /* PixlDocWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = F46AB96D1B375DB300CEB288 /* PixlDocWindowController.m */; }; 17 | F4B87C4D1B3EE62300F4B8BE /* PixlViewIcon.icns in Resources */ = {isa = PBXBuildFile; fileRef = F4B87C4B1B3EE61800F4B8BE /* PixlViewIcon.icns */; }; 18 | F4BECE381B348E4F005FAD6C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F4BECE371B348E4F005FAD6C /* main.m */; }; 19 | F4BECE3B1B348E4F005FAD6C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F4BECE3A1B348E4F005FAD6C /* AppDelegate.m */; }; 20 | F4BECE3D1B348E4F005FAD6C /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F4BECE3C1B348E4F005FAD6C /* Images.xcassets */; }; 21 | F4BECE401B348E4F005FAD6C /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4BECE3E1B348E4F005FAD6C /* MainMenu.xib */; }; 22 | F4BECE5D1B35B541005FAD6C /* GLPixelView.m in Sources */ = {isa = PBXBuildFile; fileRef = F4BECE5C1B35B541005FAD6C /* GLPixelView.m */; }; 23 | F4BECE671B35D878005FAD6C /* PixelBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = F4BECE661B35D878005FAD6C /* PixelBuffer.m */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | F40068601B38CE6500961B42 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/PixlDoc.strings; sourceTree = ""; }; 28 | F40068651B3A049800961B42 /* IDEAS.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = IDEAS.txt; path = ../pixlview/IDEAS.txt; sourceTree = ""; }; 29 | F40068661B3A0AAA00961B42 /* small-zoom-cursor.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "small-zoom-cursor.png"; path = "../../pixlview/PixlView/images/small-zoom-cursor.png"; sourceTree = ""; }; 30 | F40068671B3A0AAA00961B42 /* small-zoom-in-cursor.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "small-zoom-in-cursor.png"; path = "../../pixlview/PixlView/images/small-zoom-in-cursor.png"; sourceTree = ""; }; 31 | F400686B1B3A0CB900961B42 /* ZoomableClipView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ZoomableClipView.h; path = ../../pixlview/PixlView/ZoomableClipView.h; sourceTree = ""; }; 32 | F400686C1B3A0CB900961B42 /* ZoomableClipView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ZoomableClipView.m; path = ../../pixlview/PixlView/ZoomableClipView.m; sourceTree = ""; }; 33 | F417D6AB1B8380A100742263 /* Constants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Constants.h; sourceTree = ""; }; 34 | F41E40721B5AA76A006D6160 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 35 | F46AB9351B3738AB00CEB288 /* resolutions.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = resolutions.plist; sourceTree = ""; }; 36 | F46AB9661B375BD800CEB288 /* PixlDoc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PixlDoc.h; sourceTree = ""; }; 37 | F46AB9671B375BD800CEB288 /* PixlDoc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PixlDoc.m; sourceTree = ""; }; 38 | F46AB96A1B375BED00CEB288 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/PixlDoc.xib; sourceTree = ""; }; 39 | F46AB96C1B375DB300CEB288 /* PixlDocWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PixlDocWindowController.h; sourceTree = ""; }; 40 | F46AB96D1B375DB300CEB288 /* PixlDocWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PixlDocWindowController.m; sourceTree = ""; }; 41 | F4B87C491B3EE61800F4B8BE /* PixlViewerIcon.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = PixlViewerIcon.iconset; path = icon/PixlViewerIcon.iconset; sourceTree = ""; }; 42 | F4B87C4A1B3EE61800F4B8BE /* PixlViewIcon.ai */ = {isa = PBXFileReference; lastKnownFileType = text; name = PixlViewIcon.ai; path = icon/PixlViewIcon.ai; sourceTree = ""; }; 43 | F4B87C4B1B3EE61800F4B8BE /* PixlViewIcon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = PixlViewIcon.icns; path = icon/PixlViewIcon.icns; sourceTree = ""; }; 44 | F4B87C4C1B3EE61800F4B8BE /* PixlViewIcon.psd */ = {isa = PBXFileReference; lastKnownFileType = file; name = PixlViewIcon.psd; path = icon/PixlViewIcon.psd; sourceTree = ""; }; 45 | F4BECE321B348E4F005FAD6C /* PixlView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PixlView.app; sourceTree = BUILT_PRODUCTS_DIR; }; 46 | F4BECE361B348E4F005FAD6C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 47 | F4BECE371B348E4F005FAD6C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 48 | F4BECE391B348E4F005FAD6C /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 49 | F4BECE3A1B348E4F005FAD6C /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 50 | F4BECE3C1B348E4F005FAD6C /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 51 | F4BECE3F1B348E4F005FAD6C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 52 | F4BECE5B1B35B541005FAD6C /* GLPixelView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLPixelView.h; sourceTree = ""; }; 53 | F4BECE5C1B35B541005FAD6C /* GLPixelView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLPixelView.m; sourceTree = ""; }; 54 | F4BECE651B35D878005FAD6C /* PixelBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PixelBuffer.h; sourceTree = ""; }; 55 | F4BECE661B35D878005FAD6C /* PixelBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PixelBuffer.m; sourceTree = ""; }; 56 | /* End PBXFileReference section */ 57 | 58 | /* Begin PBXFrameworksBuildPhase section */ 59 | F4BECE2F1B348E4F005FAD6C /* Frameworks */ = { 60 | isa = PBXFrameworksBuildPhase; 61 | buildActionMask = 2147483647; 62 | files = ( 63 | ); 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | /* End PBXFrameworksBuildPhase section */ 67 | 68 | /* Begin PBXGroup section */ 69 | F400686A1B3A0AB600961B42 /* Images */ = { 70 | isa = PBXGroup; 71 | children = ( 72 | F40068661B3A0AAA00961B42 /* small-zoom-cursor.png */, 73 | F40068671B3A0AAA00961B42 /* small-zoom-in-cursor.png */, 74 | F4B87C481B3EE60D00F4B8BE /* Icon */, 75 | F4BECE3C1B348E4F005FAD6C /* Images.xcassets */, 76 | ); 77 | name = Images; 78 | sourceTree = ""; 79 | }; 80 | F4B87C481B3EE60D00F4B8BE /* Icon */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | F4B87C491B3EE61800F4B8BE /* PixlViewerIcon.iconset */, 84 | F4B87C4A1B3EE61800F4B8BE /* PixlViewIcon.ai */, 85 | F4B87C4B1B3EE61800F4B8BE /* PixlViewIcon.icns */, 86 | F4B87C4C1B3EE61800F4B8BE /* PixlViewIcon.psd */, 87 | ); 88 | name = Icon; 89 | sourceTree = ""; 90 | }; 91 | F4BECE291B348E4F005FAD6C = { 92 | isa = PBXGroup; 93 | children = ( 94 | F41E40721B5AA76A006D6160 /* README.md */, 95 | F40068651B3A049800961B42 /* IDEAS.txt */, 96 | F4BECE341B348E4F005FAD6C /* PixlView */, 97 | F4BECE331B348E4F005FAD6C /* Products */, 98 | ); 99 | sourceTree = ""; 100 | }; 101 | F4BECE331B348E4F005FAD6C /* Products */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | F4BECE321B348E4F005FAD6C /* PixlView.app */, 105 | ); 106 | name = Products; 107 | sourceTree = ""; 108 | }; 109 | F4BECE341B348E4F005FAD6C /* PixlView */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | F417D6AB1B8380A100742263 /* Constants.h */, 113 | F4BECE391B348E4F005FAD6C /* AppDelegate.h */, 114 | F4BECE3A1B348E4F005FAD6C /* AppDelegate.m */, 115 | F46AB9661B375BD800CEB288 /* PixlDoc.h */, 116 | F46AB9671B375BD800CEB288 /* PixlDoc.m */, 117 | F46AB96C1B375DB300CEB288 /* PixlDocWindowController.h */, 118 | F46AB96D1B375DB300CEB288 /* PixlDocWindowController.m */, 119 | F4BECE651B35D878005FAD6C /* PixelBuffer.h */, 120 | F4BECE661B35D878005FAD6C /* PixelBuffer.m */, 121 | F4BECE5B1B35B541005FAD6C /* GLPixelView.h */, 122 | F4BECE5C1B35B541005FAD6C /* GLPixelView.m */, 123 | F400686B1B3A0CB900961B42 /* ZoomableClipView.h */, 124 | F400686C1B3A0CB900961B42 /* ZoomableClipView.m */, 125 | F4BECE351B348E4F005FAD6C /* Resources */, 126 | ); 127 | path = PixlView; 128 | sourceTree = ""; 129 | }; 130 | F4BECE351B348E4F005FAD6C /* Resources */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | F400686A1B3A0AB600961B42 /* Images */, 134 | F46AB9691B375BED00CEB288 /* PixlDoc.xib */, 135 | F4BECE3E1B348E4F005FAD6C /* MainMenu.xib */, 136 | F46AB9351B3738AB00CEB288 /* resolutions.plist */, 137 | F4BECE361B348E4F005FAD6C /* Info.plist */, 138 | F4BECE371B348E4F005FAD6C /* main.m */, 139 | ); 140 | name = Resources; 141 | sourceTree = ""; 142 | }; 143 | /* End PBXGroup section */ 144 | 145 | /* Begin PBXNativeTarget section */ 146 | F4BECE311B348E4F005FAD6C /* PixlView */ = { 147 | isa = PBXNativeTarget; 148 | buildConfigurationList = F4BECE4F1B348E50005FAD6C /* Build configuration list for PBXNativeTarget "PixlView" */; 149 | buildPhases = ( 150 | F4BECE2E1B348E4F005FAD6C /* Sources */, 151 | F4BECE2F1B348E4F005FAD6C /* Frameworks */, 152 | F4BECE301B348E4F005FAD6C /* Resources */, 153 | ); 154 | buildRules = ( 155 | ); 156 | dependencies = ( 157 | ); 158 | name = PixlView; 159 | productName = PixlView; 160 | productReference = F4BECE321B348E4F005FAD6C /* PixlView.app */; 161 | productType = "com.apple.product-type.application"; 162 | }; 163 | /* End PBXNativeTarget section */ 164 | 165 | /* Begin PBXProject section */ 166 | F4BECE2A1B348E4F005FAD6C /* Project object */ = { 167 | isa = PBXProject; 168 | attributes = { 169 | LastUpgradeCheck = 0640; 170 | ORGANIZATIONNAME = "Sveinbjorn Thordarson"; 171 | TargetAttributes = { 172 | F4BECE311B348E4F005FAD6C = { 173 | CreatedOnToolsVersion = 6.0.1; 174 | }; 175 | }; 176 | }; 177 | buildConfigurationList = F4BECE2D1B348E4F005FAD6C /* Build configuration list for PBXProject "PixlView" */; 178 | compatibilityVersion = "Xcode 3.2"; 179 | developmentRegion = English; 180 | hasScannedForEncodings = 0; 181 | knownRegions = ( 182 | en, 183 | Base, 184 | ); 185 | mainGroup = F4BECE291B348E4F005FAD6C; 186 | productRefGroup = F4BECE331B348E4F005FAD6C /* Products */; 187 | projectDirPath = ""; 188 | projectRoot = ""; 189 | targets = ( 190 | F4BECE311B348E4F005FAD6C /* PixlView */, 191 | ); 192 | }; 193 | /* End PBXProject section */ 194 | 195 | /* Begin PBXResourcesBuildPhase section */ 196 | F4BECE301B348E4F005FAD6C /* Resources */ = { 197 | isa = PBXResourcesBuildPhase; 198 | buildActionMask = 2147483647; 199 | files = ( 200 | F46AB96B1B375BED00CEB288 /* PixlDoc.xib in Resources */, 201 | F4BECE3D1B348E4F005FAD6C /* Images.xcassets in Resources */, 202 | F4BECE401B348E4F005FAD6C /* MainMenu.xib in Resources */, 203 | F40068681B3A0AAA00961B42 /* small-zoom-cursor.png in Resources */, 204 | F46AB9361B3738AB00CEB288 /* resolutions.plist in Resources */, 205 | F4B87C4D1B3EE62300F4B8BE /* PixlViewIcon.icns in Resources */, 206 | F40068691B3A0AAA00961B42 /* small-zoom-in-cursor.png in Resources */, 207 | ); 208 | runOnlyForDeploymentPostprocessing = 0; 209 | }; 210 | /* End PBXResourcesBuildPhase section */ 211 | 212 | /* Begin PBXSourcesBuildPhase section */ 213 | F4BECE2E1B348E4F005FAD6C /* Sources */ = { 214 | isa = PBXSourcesBuildPhase; 215 | buildActionMask = 2147483647; 216 | files = ( 217 | F46AB9681B375BD800CEB288 /* PixlDoc.m in Sources */, 218 | F4BECE5D1B35B541005FAD6C /* GLPixelView.m in Sources */, 219 | F4BECE671B35D878005FAD6C /* PixelBuffer.m in Sources */, 220 | F4BECE3B1B348E4F005FAD6C /* AppDelegate.m in Sources */, 221 | F46AB96E1B375DB300CEB288 /* PixlDocWindowController.m in Sources */, 222 | F400686D1B3A0CB900961B42 /* ZoomableClipView.m in Sources */, 223 | F4BECE381B348E4F005FAD6C /* main.m in Sources */, 224 | ); 225 | runOnlyForDeploymentPostprocessing = 0; 226 | }; 227 | /* End PBXSourcesBuildPhase section */ 228 | 229 | /* Begin PBXVariantGroup section */ 230 | F46AB9691B375BED00CEB288 /* PixlDoc.xib */ = { 231 | isa = PBXVariantGroup; 232 | children = ( 233 | F46AB96A1B375BED00CEB288 /* Base */, 234 | F40068601B38CE6500961B42 /* en */, 235 | ); 236 | name = PixlDoc.xib; 237 | sourceTree = ""; 238 | }; 239 | F4BECE3E1B348E4F005FAD6C /* MainMenu.xib */ = { 240 | isa = PBXVariantGroup; 241 | children = ( 242 | F4BECE3F1B348E4F005FAD6C /* Base */, 243 | ); 244 | name = MainMenu.xib; 245 | sourceTree = ""; 246 | }; 247 | /* End PBXVariantGroup section */ 248 | 249 | /* Begin XCBuildConfiguration section */ 250 | F4BECE4D1B348E50005FAD6C /* Debug */ = { 251 | isa = XCBuildConfiguration; 252 | buildSettings = { 253 | ALWAYS_SEARCH_USER_PATHS = NO; 254 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 255 | CLANG_CXX_LIBRARY = "libc++"; 256 | CLANG_ENABLE_MODULES = YES; 257 | CLANG_ENABLE_OBJC_ARC = YES; 258 | CLANG_WARN_BOOL_CONVERSION = YES; 259 | CLANG_WARN_CONSTANT_CONVERSION = YES; 260 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 261 | CLANG_WARN_EMPTY_BODY = YES; 262 | CLANG_WARN_ENUM_CONVERSION = YES; 263 | CLANG_WARN_INT_CONVERSION = YES; 264 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 265 | CLANG_WARN_UNREACHABLE_CODE = YES; 266 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 267 | CODE_SIGN_IDENTITY = ""; 268 | COPY_PHASE_STRIP = NO; 269 | ENABLE_STRICT_OBJC_MSGSEND = YES; 270 | GCC_C_LANGUAGE_STANDARD = gnu99; 271 | GCC_DYNAMIC_NO_PIC = NO; 272 | GCC_OPTIMIZATION_LEVEL = 0; 273 | GCC_PREPROCESSOR_DEFINITIONS = ( 274 | "DEBUG=1", 275 | "$(inherited)", 276 | ); 277 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 278 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 279 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 280 | GCC_WARN_UNDECLARED_SELECTOR = YES; 281 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 282 | GCC_WARN_UNUSED_FUNCTION = YES; 283 | GCC_WARN_UNUSED_VARIABLE = YES; 284 | MACOSX_DEPLOYMENT_TARGET = 10.10; 285 | MTL_ENABLE_DEBUG_INFO = YES; 286 | ONLY_ACTIVE_ARCH = YES; 287 | SDKROOT = macosx; 288 | }; 289 | name = Debug; 290 | }; 291 | F4BECE4E1B348E50005FAD6C /* Release */ = { 292 | isa = XCBuildConfiguration; 293 | buildSettings = { 294 | ALWAYS_SEARCH_USER_PATHS = NO; 295 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 296 | CLANG_CXX_LIBRARY = "libc++"; 297 | CLANG_ENABLE_MODULES = YES; 298 | CLANG_ENABLE_OBJC_ARC = YES; 299 | CLANG_WARN_BOOL_CONVERSION = YES; 300 | CLANG_WARN_CONSTANT_CONVERSION = YES; 301 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 302 | CLANG_WARN_EMPTY_BODY = YES; 303 | CLANG_WARN_ENUM_CONVERSION = YES; 304 | CLANG_WARN_INT_CONVERSION = YES; 305 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 306 | CLANG_WARN_UNREACHABLE_CODE = YES; 307 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 308 | CODE_SIGN_IDENTITY = ""; 309 | COPY_PHASE_STRIP = YES; 310 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 311 | ENABLE_NS_ASSERTIONS = NO; 312 | ENABLE_STRICT_OBJC_MSGSEND = YES; 313 | GCC_C_LANGUAGE_STANDARD = gnu99; 314 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 315 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 316 | GCC_WARN_UNDECLARED_SELECTOR = YES; 317 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 318 | GCC_WARN_UNUSED_FUNCTION = YES; 319 | GCC_WARN_UNUSED_VARIABLE = YES; 320 | MACOSX_DEPLOYMENT_TARGET = 10.10; 321 | MTL_ENABLE_DEBUG_INFO = NO; 322 | SDKROOT = macosx; 323 | }; 324 | name = Release; 325 | }; 326 | F4BECE501B348E50005FAD6C /* Debug */ = { 327 | isa = XCBuildConfiguration; 328 | buildSettings = { 329 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 330 | COMBINE_HIDPI_IMAGES = YES; 331 | INFOPLIST_FILE = PixlView/Info.plist; 332 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 333 | MACOSX_DEPLOYMENT_TARGET = 10.8; 334 | PRODUCT_NAME = PixlView; 335 | }; 336 | name = Debug; 337 | }; 338 | F4BECE511B348E50005FAD6C /* Release */ = { 339 | isa = XCBuildConfiguration; 340 | buildSettings = { 341 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 342 | COMBINE_HIDPI_IMAGES = YES; 343 | INFOPLIST_FILE = PixlView/Info.plist; 344 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 345 | MACOSX_DEPLOYMENT_TARGET = 10.8; 346 | PRODUCT_NAME = PixlView; 347 | }; 348 | name = Release; 349 | }; 350 | /* End XCBuildConfiguration section */ 351 | 352 | /* Begin XCConfigurationList section */ 353 | F4BECE2D1B348E4F005FAD6C /* Build configuration list for PBXProject "PixlView" */ = { 354 | isa = XCConfigurationList; 355 | buildConfigurations = ( 356 | F4BECE4D1B348E50005FAD6C /* Debug */, 357 | F4BECE4E1B348E50005FAD6C /* Release */, 358 | ); 359 | defaultConfigurationIsVisible = 0; 360 | defaultConfigurationName = Release; 361 | }; 362 | F4BECE4F1B348E50005FAD6C /* Build configuration list for PBXNativeTarget "PixlView" */ = { 363 | isa = XCConfigurationList; 364 | buildConfigurations = ( 365 | F4BECE501B348E50005FAD6C /* Debug */, 366 | F4BECE511B348E50005FAD6C /* Release */, 367 | ); 368 | defaultConfigurationIsVisible = 0; 369 | defaultConfigurationName = Release; 370 | }; 371 | /* End XCConfigurationList section */ 372 | }; 373 | rootObject = F4BECE2A1B348E4F005FAD6C /* Project object */; 374 | } 375 | -------------------------------------------------------------------------------- /PixlView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PixlView.xcodeproj/project.xcworkspace/xcuserdata/sveinbjorn.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /PixlView.xcodeproj/xcuserdata/sveinbjorn.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | PixlView.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | F4BECE311B348E4F005FAD6C 16 | 17 | primary 18 | 19 | 20 | F4BECE441B348E50005FAD6C 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /PixlView/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // PixelViewer 4 | // 5 | // Created by Sveinbjorn Thordarson on 19/06/15. 6 | // Copyright (c) 2015 Sveinbjorn Thordarson. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "GLPixelView.h" 11 | #import "PixelBuffer.h" 12 | 13 | #define PIXEL_FORMATS [NSArray arrayWithObjects: @"RGBPixelFormat", nil] 14 | 15 | @interface AppDelegate : NSObject 16 | { 17 | 18 | } 19 | 20 | @end 21 | 22 | -------------------------------------------------------------------------------- /PixlView/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // PixelViewer 4 | // 5 | // Created by Sveinbjorn Thordarson on 19/06/15. 6 | // Copyright (c) 2015 Sveinbjorn Thordarson. All rights reserved. 7 | // 8 | 9 | #import "Constants.h" 10 | #import "AppDelegate.h" 11 | #import "GLPixelView.h" 12 | #import "PixelBuffer.h" 13 | 14 | @implementation AppDelegate 15 | 16 | - (void)awakeFromNib { 17 | 18 | } 19 | 20 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 21 | 22 | } 23 | 24 | - (void)applicationWillTerminate:(NSNotification *)aNotification { 25 | 26 | } 27 | 28 | - (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication 29 | hasVisibleWindows:(BOOL)flag { 30 | 31 | //[[NSDocumentController sharedDocumentController] openDocument:self]; 32 | return NO; 33 | } 34 | 35 | //- (BOOL)application:(NSApplication *)theApplication 36 | // openFile:(NSString *)filename { 37 | // return YES; 38 | //} 39 | 40 | - (IBAction)newRandomBuffer:(id)sender { 41 | // prepare filename 42 | NSString *appPath = [[[NSBundle mainBundle] bundleURL] path]; 43 | NSString *filename = @"/tmp/random.data"; 44 | while ([[NSFileManager defaultManager] fileExistsAtPath:filename]) { 45 | filename = [NSString stringWithFormat:@"/tmp/random%d.data", arc4random()]; 46 | } 47 | 48 | // write 49 | int length = RANDOM_PIXEL_BUFFER_WIDTH * RANDOM_PIXEL_BUFFER_HEIGHT * 3; 50 | void *d = malloc(length); 51 | arc4random_buf(d, length); 52 | [[NSData dataWithBytes:d length:length] writeToFile:filename atomically:NO]; 53 | free(d); 54 | 55 | // open 56 | [[NSWorkspace sharedWorkspace] openFile:filename withApplication:appPath]; 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /PixlView/Base.lproj/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | DQ 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 273 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | NSUnarchiveFromData 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 324 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | NSUnarchiveFromData 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | -------------------------------------------------------------------------------- /PixlView/Base.lproj/PixlDoc.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 57 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | -------------------------------------------------------------------------------- /PixlView/Constants.h: -------------------------------------------------------------------------------- 1 | // 2 | // Constants.h 3 | // PixlView 4 | // 5 | // Created by Sveinbjorn Thordarson on 18/08/15. 6 | // Copyright (c) 2015 Sveinbjorn Thordarson. All rights reserved. 7 | // 8 | 9 | 10 | #define DEFAULT_PIXEL_BUFFER_WIDTH 640 11 | #define DEFAULT_PIXEL_BUFFER_HEIGHT 480 12 | 13 | #define RANDOM_PIXEL_BUFFER_WIDTH 640 14 | #define RANDOM_PIXEL_BUFFER_HEIGHT 480 -------------------------------------------------------------------------------- /PixlView/GLPixelView.h: -------------------------------------------------------------------------------- 1 | // 2 | // PixelGLView.h 3 | // PixelViewer 4 | // 5 | // Created by Sveinbjorn Thordarson on 20/06/15. 6 | // Copyright (c) 2015 Sveinbjorn Thordarson. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol GLPixelViewDelegate 12 | - (void)glPixelViewDoubleClicked:(NSEvent *)event; 13 | - (void)glPixelViewClicked:(NSEvent *)event; 14 | @end 15 | 16 | @interface GLPixelView : NSOpenGLView 17 | { 18 | GLuint framebuffer; 19 | GLuint texture; 20 | } 21 | @property (retain, nonatomic) NSData *pixelData; 22 | @property CGFloat scale; 23 | @property id delegate; 24 | 25 | - (instancetype)initWithFrame:(NSRect)frameRect pixelFormat:(NSOpenGLPixelFormat *)format scale:(CGFloat)scale; 26 | - (void)refresh; 27 | - (void)createTexture; 28 | - (void *)readGLBuffer; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /PixlView/GLPixelView.m: -------------------------------------------------------------------------------- 1 | // 2 | // PixelGLView.m 3 | // PixelViewer 4 | // 5 | // Created by Sveinbjorn Thordarson on 20/06/15. 6 | // Copyright (c) 2015 Sveinbjorn Thordarson. All rights reserved. 7 | // 8 | 9 | #import "GLPixelView.h" 10 | #import 11 | #import 12 | #import 13 | 14 | @implementation GLPixelView 15 | 16 | - (instancetype)initWithFrame:(NSRect)frameRect pixelFormat:(NSOpenGLPixelFormat *)format scale:(CGFloat)scale { 17 | 18 | frameRect.size.width = frameRect.size.width * scale ; 19 | frameRect.size.height = frameRect.size.height * scale; 20 | if ((self = [super initWithFrame:frameRect pixelFormat:format])) { 21 | self.scale = scale; 22 | } 23 | return self; 24 | } 25 | 26 | - (void)prepareOpenGL { 27 | glClearColor(0, 0, 0, 0); 28 | glDisable(GL_POINT_SMOOTH); 29 | glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST); 30 | glEnable(GL_BLEND); 31 | } 32 | 33 | #pragma mark - 34 | 35 | - (void *)readGLBuffer { 36 | [[self openGLContext] makeCurrentContext]; 37 | 38 | void *buf = malloc(self.frame.size.width * self.frame.size.height * 4); 39 | glReadPixels(0, 0, self.frame.size.width, self.frame.size.height, GL_RGBA, GL_UNSIGNED_BYTE, buf); 40 | 41 | return buf; 42 | } 43 | 44 | - (void)setPixelData:(NSData *)pixelData { 45 | _pixelData = pixelData; 46 | [self createTexture]; 47 | } 48 | 49 | - (void)setFrame:(NSRect)frameRect { 50 | frameRect.size.width = frameRect.size.width * self.scale; 51 | frameRect.size.height = frameRect.size.height * self.scale; 52 | [super setFrame:frameRect]; 53 | } 54 | 55 | #pragma mark - 56 | 57 | - (void)reshape { 58 | 59 | } 60 | 61 | - (void)refresh { 62 | [self drawRect:[self bounds]]; 63 | } 64 | 65 | - (void)drawRect:(NSRect)dirtyRect { 66 | 67 | [[self openGLContext] makeCurrentContext]; 68 | [super drawRect:dirtyRect]; 69 | 70 | NSRect backingFrameRect = [self bounds]; 71 | if (self.wantsBestResolutionOpenGLSurface) { 72 | backingFrameRect = [self convertRectToBacking:[self bounds]]; 73 | } 74 | 75 | int maxSize; 76 | glGetIntegerv(GL_MAX_VIEWPORT_DIMS, &maxSize); 77 | 78 | int vpw = backingFrameRect.size.width > maxSize ? maxSize : backingFrameRect.size.width; 79 | int vph = backingFrameRect.size.height > maxSize ? maxSize : backingFrameRect.size.height; 80 | 81 | glViewport(0, 0, vpw, vph); 82 | 83 | glMatrixMode(GL_PROJECTION); 84 | glLoadIdentity(); 85 | 86 | // x=0,y=0 is top left 87 | glOrtho(0, self.frame.size.width, self.frame.size.height, 0 , 0, 1); 88 | 89 | glMatrixMode(GL_MODELVIEW); 90 | glLoadIdentity(); 91 | 92 | NSColor *color = [NSColor redColor]; 93 | id colorData = [[NSUserDefaults standardUserDefaults] objectForKey:@"BufferOverflowColor"]; 94 | if (colorData) { 95 | color = [NSUnarchiver unarchiveObjectWithData:colorData]; 96 | } 97 | glClearColor(color.redComponent, color.greenComponent, color.blueComponent, color.alphaComponent); 98 | glClear(GL_COLOR_BUFFER_BIT); 99 | 100 | // Draw texture 101 | if (texture) { 102 | glEnable(GL_TEXTURE_2D); 103 | glBindTexture(GL_TEXTURE_2D, texture); 104 | 105 | int x1 = 0; 106 | int y1 = 0; 107 | 108 | int x2 = self.frame.size.width; 109 | int y2 = self.frame.size.height; 110 | 111 | glBegin(GL_QUADS); 112 | 113 | glTexCoord2f(0.0f,1.0f); 114 | glVertex2f(x1,y2); 115 | 116 | glTexCoord2f(0.0f,0.0f); 117 | glVertex2f(x1,y1); 118 | 119 | glTexCoord2f(1.0f,0.0f); 120 | glVertex2f(x2,y1); 121 | 122 | glTexCoord2f(1.0f,1.0f); 123 | glVertex2f(x2,y2); 124 | 125 | glEnd(); 126 | } 127 | 128 | [[self openGLContext] flushBuffer]; 129 | } 130 | 131 | - (void)createTexture { 132 | [[self openGLContext] makeCurrentContext]; 133 | 134 | // delete previous texture 135 | if (texture) { 136 | glDeleteTextures(1, &texture); 137 | } 138 | 139 | // Create the texture we're going to render to 140 | glGenTextures(1, &texture); 141 | if (!texture) { 142 | NSLog(@"Failed to create texture"); 143 | return; 144 | } 145 | glBindTexture(GL_TEXTURE_2D, texture); 146 | 147 | int w = self.frame.size.width/self.scale; 148 | int h = self.frame.size.height/self.scale; 149 | 150 | int bufLength = w * h * 4; 151 | unsigned char *buf = malloc(bufLength); 152 | if (self.pixelData.length >= bufLength) { 153 | memcpy(buf, self.pixelData.bytes, bufLength); 154 | } else { 155 | 156 | NSColor *color = [NSColor blackColor]; 157 | id archivedColor = [[NSUserDefaults standardUserDefaults] objectForKey:@"BackgroundColor"]; 158 | if (archivedColor) { 159 | color = [NSUnarchiver unarchiveObjectWithData:archivedColor]; 160 | } 161 | unsigned char val[4]; 162 | val[0] = color.redComponent * 255; 163 | val[1] = color.greenComponent * 255; 164 | val[2] = color.blueComponent * 255; 165 | val[3] = color.alphaComponent * 255; 166 | 167 | memset_pattern4(buf, &val, bufLength); 168 | memcpy(buf, self.pixelData.bytes, self.pixelData.length); 169 | } 170 | 171 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0,GL_RGBA, GL_UNSIGNED_BYTE, buf); 172 | if ([[NSUserDefaults standardUserDefaults] boolForKey:@"UseAntialiasing"]) { 173 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 174 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 175 | } else { 176 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 177 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 178 | } 179 | 180 | free(buf); 181 | 182 | NSLog(@"Created texture %.1f x %.1f", self.frame.size.width, self.frame.size.height); 183 | } 184 | 185 | #pragma mark - Event handling 186 | 187 | - (void)mouseUp:(NSEvent*)event 188 | { 189 | if (!self.delegate) { 190 | return; 191 | } 192 | 193 | NSInteger clickCount = [event clickCount]; 194 | if (2 == clickCount) { 195 | [self.delegate glPixelViewDoubleClicked:event]; 196 | } else { 197 | [self.delegate glPixelViewClicked:event]; 198 | } 199 | } 200 | 201 | 202 | #pragma mark - 203 | 204 | -(BOOL)isFlipped 205 | { 206 | return YES; 207 | } 208 | 209 | 210 | @end 211 | -------------------------------------------------------------------------------- /PixlView/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /PixlView/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDocumentTypes 8 | 9 | 10 | CFBundleTypeExtensions 11 | 12 | data 13 | rgb 14 | yuv 15 | rgba 16 | rgb8 17 | rgb24 18 | yuv420 19 | yuv420p 20 | yuv422p 21 | 22 | CFBundleTypeIconFile 23 | 24 | CFBundleTypeName 25 | DocumentType 26 | CFBundleTypeOSTypes 27 | 28 | ???? 29 | 30 | CFBundleTypeRole 31 | Viewer 32 | NSDocumentClass 33 | PixlDoc 34 | 35 | 36 | CFBundleExecutable 37 | $(EXECUTABLE_NAME) 38 | CFBundleIconFile 39 | PixlViewIcon.icns 40 | CFBundleIdentifier 41 | org.sveinbjornt.$(PRODUCT_NAME:rfc1034identifier) 42 | CFBundleInfoDictionaryVersion 43 | 6.0 44 | CFBundleName 45 | $(PRODUCT_NAME) 46 | CFBundlePackageType 47 | APPL 48 | CFBundleShortVersionString 49 | 1.0 50 | CFBundleSignature 51 | ???? 52 | CFBundleVersion 53 | 1 54 | LSApplicationCategoryType 55 | public.app-category.developer-tools 56 | LSMinimumSystemVersion 57 | $(MACOSX_DEPLOYMENT_TARGET) 58 | NSHumanReadableCopyright 59 | Copyright © 2015 Sveinbjorn Thordarson. All rights reserved. 60 | NSMainNibFile 61 | MainMenu 62 | NSPrincipalClass 63 | NSApplication 64 | 65 | 66 | -------------------------------------------------------------------------------- /PixlView/PixelBuffer.h: -------------------------------------------------------------------------------- 1 | // 2 | // PixelBuffer.h 3 | // PixelViewer 4 | // 5 | // Created by Sveinbjorn Thordarson on 20/06/15. 6 | // Copyright (c) 2015 Sveinbjorn Thordarson. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef enum : NSInteger { 12 | PIXEL_FORMAT_RGBA, 13 | PIXEL_FORMAT_RGB24, 14 | PIXEL_FORMAT_RGB8, 15 | PIXEL_FORMAT_YUV420P 16 | } PixelFormat; 17 | 18 | @interface PixelBuffer : NSObject 19 | { 20 | 21 | } 22 | @property (retain, nonatomic) NSData *data; 23 | @property PixelFormat pixelFormat; 24 | @property int offset; 25 | 26 | - (instancetype)initWithContentsOfFile:(NSString *)path; 27 | - (instancetype)initWithData:(NSData *)d; 28 | 29 | - (unsigned char *)bytes; 30 | - (int)length; 31 | 32 | + (PixelFormat)pixelFormatForSuffix:(NSString *)suffix; 33 | + (NSArray *)supportedFormats; 34 | 35 | - (NSData *)toRGBA; 36 | - (int)expectedBitLengthForImageSize:(NSSize)size; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /PixlView/PixelBuffer.m: -------------------------------------------------------------------------------- 1 | // 2 | // PixelBuffer.m 3 | // PixelViewer 4 | // 5 | // Created by Sveinbjorn Thordarson on 20/06/15. 6 | // Copyright (c) 2015 Sveinbjorn Thordarson. All rights reserved. 7 | // 8 | 9 | #import "PixelBuffer.h" 10 | 11 | @implementation PixelBuffer 12 | 13 | - (instancetype)initWithContentsOfFile:(NSString *)path { 14 | 15 | NSData *d = [NSData dataWithContentsOfFile:path]; 16 | return [self initWithData:d]; 17 | } 18 | 19 | - (instancetype)initWithData:(NSData *)d { 20 | if ((self = [super init])) { 21 | self.data = d; 22 | NSLog(@"Pixel buffer inited with data length %lu", self.data.length); 23 | } 24 | return self; 25 | } 26 | 27 | #pragma mark - Info 28 | 29 | - (unsigned char *)bytes { 30 | return (unsigned char *)([self.data bytes] + self.offset); 31 | } 32 | 33 | - (int)length { 34 | return (int)self.data.length - self.offset; 35 | } 36 | 37 | + (NSArray *)supportedFormats { 38 | return [NSArray arrayWithObjects:@"RGBA (32bpp)", 39 | @"RGB (24bpp)", 40 | @"RGB8 (8bpp)", 41 | //@"YUV420p", 42 | nil]; 43 | } 44 | 45 | + (PixelFormat)pixelFormatForSuffix:(NSString *)suffix { 46 | if ([suffix isEqualToString:@"rgba"]) { 47 | return PIXEL_FORMAT_RGBA; 48 | } else if ([suffix isEqualToString:@"rgb"]) { 49 | return PIXEL_FORMAT_RGB24; 50 | } else if ([suffix isEqualToString:@"rgb8"]) { 51 | return PIXEL_FORMAT_RGB8; 52 | } else if ([suffix isEqualToString:@"yuv"] || [suffix isEqualToString:@"yuv420p"]) { 53 | return PIXEL_FORMAT_YUV420P; 54 | } 55 | return -1; 56 | } 57 | 58 | #pragma mark - Pixel format conversion routines 59 | 60 | - (NSData *)rgb24_2_rgba { 61 | 62 | unsigned char *rgbBuffer = (unsigned char *)[self bytes]; 63 | int rgbBufferLength = (int)[self length]; 64 | int pixelCount = rgbBufferLength/3; 65 | 66 | if (pixelCount == 0 || rgbBufferLength < 3) { 67 | NSLog(@"Aborted conversion of rgb24 buffer length %d", rgbBufferLength); 68 | return nil; 69 | } 70 | 71 | int rgbaBufferLength = pixelCount * 4; 72 | unsigned char *rgbaBuffer = malloc(rgbaBufferLength); 73 | 74 | int rgbaIndex = 0; 75 | int rgbIndex = 0; 76 | for (int i = 0; i < pixelCount; i++) { 77 | rgbaBuffer[rgbaIndex] = rgbBuffer[rgbIndex]; 78 | rgbaBuffer[rgbaIndex+1] = rgbBuffer[rgbIndex+1]; 79 | rgbaBuffer[rgbaIndex+2] = rgbBuffer[rgbIndex+2]; 80 | rgbaBuffer[rgbaIndex+3] = 1; 81 | 82 | rgbaIndex += 4; 83 | rgbIndex += 3; 84 | } 85 | 86 | NSData *d = [NSData dataWithBytes:rgbaBuffer length:rgbaBufferLength]; 87 | free(rgbaBuffer); 88 | 89 | return d; 90 | } 91 | 92 | - (NSData *)rgb8_2_rgba { 93 | 94 | unsigned char *rgb8Buffer = (unsigned char *)[self bytes]; 95 | int rgb8BufferLength = (int)[self length]; 96 | int pixelCount = rgb8BufferLength; 97 | 98 | int rgbaBufferLength = pixelCount * 4; 99 | unsigned char *rgbaBuffer = malloc(rgbaBufferLength); 100 | 101 | int rgbaIndex = 0; 102 | int rgb8Index = 0; 103 | for (int i = 0; i < pixelCount; i++) { 104 | rgbaBuffer[rgbaIndex] = rgb8Buffer[rgb8Index]; 105 | rgbaBuffer[rgbaIndex+1] = rgb8Buffer[rgb8Index]; 106 | rgbaBuffer[rgbaIndex+2] = rgb8Buffer[rgb8Index]; 107 | rgbaBuffer[rgbaIndex+3] = 1; 108 | 109 | rgbaIndex += 4; 110 | rgb8Index += 1; 111 | } 112 | 113 | 114 | NSData *d = [NSData dataWithBytes:rgbaBuffer length:rgbaBufferLength]; 115 | free(rgbaBuffer); 116 | 117 | return d; 118 | } 119 | 120 | 121 | - (unsigned char *)yuv420p_2_rgba { 122 | 123 | // void *src = (void *)[self.data bytes]; 124 | // 125 | // void *dst = 126 | // , void *dst, int width, int height 127 | // 128 | // unsigned char y, u,v; 129 | // char *rgb = dst; 130 | // 131 | // int pixelcount = width * height; 132 | // unsigned char *yptr = src; 133 | // unsigned char *uptr = src + pixelcount; 134 | // unsigned char *vptr = src + pixelcount + (pixelcount/4); 135 | // 136 | // int linesize[3]; 137 | // linesize[0] = width; 138 | // linesize[1] = width / 2; 139 | // linesize[2] = width / 2; 140 | // 141 | // int i =0; 142 | // 143 | // for (int py = 0; py < height; py++) 144 | // { 145 | // for (int px = 0; px < width; px++, i+= 3) 146 | // { 147 | // y = yptr[py * linesize[0] + px]; 148 | // u = uptr[py/2 * linesize[1] + px/2]; 149 | // v = vptr[py/2 * linesize[2] + px/2]; 150 | // 151 | // rgb[ i ] = y + 1.402 * (v-128); 152 | // rgb[ i + 1 ] = y - 0.34414 * (u-128) - 0.71414 * (v-128); 153 | // rgb[ i + 2] = y + 1.772 * (u-128); 154 | // } 155 | // } 156 | 157 | return 0; 158 | 159 | } 160 | 161 | - (NSData *)toRGBA 162 | { 163 | NSString *fmtName = [[PixelBuffer supportedFormats] objectAtIndex:(int)self.pixelFormat]; 164 | NSLog(@"Converting format %@ to RGBA", fmtName); 165 | 166 | switch (self.pixelFormat) { 167 | 168 | case PIXEL_FORMAT_RGBA: 169 | NSLog(@"Data length %d", [self length]); 170 | return [NSData dataWithBytes:[self bytes] length:[self length]]; 171 | break; 172 | case PIXEL_FORMAT_RGB24: 173 | return [self rgb24_2_rgba]; 174 | break; 175 | case PIXEL_FORMAT_RGB8: 176 | return [self rgb8_2_rgba]; 177 | break; 178 | case PIXEL_FORMAT_YUV420P: 179 | break; 180 | } 181 | 182 | return nil; 183 | } 184 | 185 | - (int)expectedBitLengthForImageSize:(NSSize)size 186 | { 187 | int bpp = 32; 188 | 189 | switch (self.pixelFormat) { 190 | 191 | case PIXEL_FORMAT_RGBA: 192 | bpp = 32; 193 | break; 194 | case PIXEL_FORMAT_RGB24: 195 | bpp = 24; 196 | break; 197 | case PIXEL_FORMAT_RGB8: 198 | bpp = 8; 199 | break; 200 | case PIXEL_FORMAT_YUV420P: 201 | bpp = 12; 202 | break; 203 | } 204 | return size.width * size.height * bpp; 205 | } 206 | 207 | 208 | @end 209 | -------------------------------------------------------------------------------- /PixlView/PixlDoc.h: -------------------------------------------------------------------------------- 1 | // 2 | // Document.h 3 | // documentsTest 4 | // 5 | // Created by Sveinbjorn Thordarson on 21/06/15. 6 | // Copyright (c) 2015 Sveinbjorn Thordarson. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "PixlDocWindowController.h" 11 | #import "PixelBuffer.h" 12 | 13 | @class PixlDocWindowController; 14 | @interface PixlDoc : NSDocument 15 | { 16 | 17 | } 18 | @property (retain, nonatomic) PixlDocWindowController *controller; 19 | @property (retain, nonatomic) PixelBuffer *pixelBuffer; 20 | @property (retain, nonatomic) NSString *filePath; 21 | @end 22 | 23 | -------------------------------------------------------------------------------- /PixlView/PixlDoc.m: -------------------------------------------------------------------------------- 1 | // 2 | // Document.m 3 | // documentsTest 4 | // 5 | // Created by Sveinbjorn Thordarson on 21/06/15. 6 | // Copyright (c) 2015 Sveinbjorn Thordarson. All rights reserved. 7 | // 8 | 9 | #import "PixlDoc.h" 10 | 11 | @implementation PixlDoc 12 | 13 | - (instancetype)init { 14 | self = [super init]; 15 | if (self) { 16 | 17 | } 18 | return self; 19 | } 20 | 21 | //Lazy instantiation of window controller 22 | - (PixlDocWindowController *)controller { 23 | if (!_controller) { 24 | _controller = [[PixlDocWindowController alloc] initWithWindowNibName:@"PixlDoc"]; 25 | } 26 | return _controller; 27 | } 28 | 29 | - (void)makeWindowControllers { 30 | [self addWindowController:self.controller]; 31 | } 32 | 33 | - (BOOL)readFromURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError **)outError { 34 | 35 | self.filePath = [url path]; 36 | self.pixelBuffer = [[PixelBuffer alloc] initWithContentsOfFile:self.filePath]; 37 | 38 | return self.pixelBuffer != nil; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /PixlView/PixlDocWindowController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DocumentWindowController.h 3 | // PixelViewer 4 | // 5 | // Created by Sveinbjorn Thordarson on 21/06/15. 6 | // Copyright (c) 2015 Sveinbjorn Thordarson. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "GLPixelView.h" 11 | #import "PixelBuffer.h" 12 | #import "PixlDoc.h" 13 | 14 | @class PixlDoc; 15 | 16 | @interface PixlDocWindowController : NSWindowController 17 | { 18 | IBOutlet id fileMD5TextField; 19 | 20 | IBOutlet id presetPopupButton; 21 | IBOutlet id formatPopupButton; 22 | IBOutlet id widthTextField; 23 | IBOutlet id heightTextField; 24 | IBOutlet id offsetTextField; 25 | IBOutlet id scaleTextField; 26 | IBOutlet id bufferInfoTextField; 27 | 28 | IBOutlet id scaleSlider; 29 | IBOutlet id widthSlider; 30 | IBOutlet id heightSlider; 31 | IBOutlet id offsetSlider; 32 | 33 | IBOutlet id pixelScrollView; 34 | IBOutlet id exportFileTypePopupButton; 35 | 36 | GLPixelView *glView; 37 | 38 | NSArray *resolutions; 39 | int presetIndex; 40 | } 41 | @property (retain, nonatomic) PixlDoc *doc; 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /PixlView/PixlDocWindowController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DocumentWindowController.m 3 | // PixelViewer 4 | // 5 | // Created by Sveinbjorn Thordarson on 21/06/15. 6 | // Copyright (c) 2015 Sveinbjorn Thordarson. All rights reserved. 7 | // 8 | 9 | #import "PixlDocWindowController.h" 10 | #import "ZoomableClipView.h" 11 | 12 | @implementation PixlDocWindowController 13 | 14 | - (void)windowDidLoad { 15 | [super windowDidLoad]; 16 | 17 | self.doc = self.document; 18 | presetIndex = -1; 19 | 20 | [self createGLPixelView]; 21 | 22 | // Offset can never be greater than file length 23 | [offsetSlider setMaxValue:[self.doc.pixelBuffer length]]; 24 | 25 | // Populate pixel format popup 26 | [formatPopupButton removeAllItems]; 27 | for (NSString *format in [PixelBuffer supportedFormats]) { 28 | [formatPopupButton addItemWithTitle:format]; 29 | } 30 | 31 | // Populate presets menu 32 | [self loadResolutionsArray]; 33 | [self populatePresetPopupMenu]; 34 | 35 | [fileMD5TextField setStringValue:[self md5hashForFileAtPath:self.doc.filePath]]; 36 | 37 | // Guess pixel format from suffix 38 | PixelFormat pixFmt = [PixelBuffer pixelFormatForSuffix:[self.doc.filePath pathExtension]]; 39 | if ((NSInteger)pixFmt != -1) { 40 | self.doc.pixelBuffer.pixelFormat = pixFmt; 41 | [formatPopupButton selectItemAtIndex:pixFmt]; 42 | } else { 43 | self.doc.pixelBuffer.pixelFormat = [formatPopupButton indexOfSelectedItem]; 44 | [self loadBestPreset]; 45 | } 46 | 47 | // Attach rgba representation of pixel data to gl view 48 | glView.pixelData = [self.doc.pixelBuffer toRGBA]; 49 | [glView setNeedsDisplay:YES]; 50 | 51 | [self updateBufferInfoTextField]; 52 | 53 | } 54 | 55 | - (void)createGLPixelView { 56 | int width = [[widthTextField stringValue] intValue]; 57 | int height = [[heightTextField stringValue] intValue]; 58 | CGFloat scale = 1.0f; 59 | 60 | NSOpenGLPixelFormatAttribute attrs[] = 61 | { 62 | NSOpenGLPFADoubleBuffer, 63 | NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute)24, 64 | NSOpenGLPFAAlphaSize, (NSOpenGLPixelFormatAttribute)0,//8 65 | NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)0,//16 66 | NSOpenGLPFAClosestPolicy, 67 | NSOpenGLPFAAllowOfflineRenderers, 68 | NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy, 69 | // NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, // !!! 70 | 0 71 | }; 72 | 73 | NSRect glFrame = NSMakeRect(0, 0, width, height); 74 | glView = [[GLPixelView alloc] initWithFrame:glFrame 75 | pixelFormat:[[NSOpenGLPixelFormat alloc] initWithAttributes:attrs] 76 | scale:scale]; 77 | // glView.autoresizingMask = NSViewNotSizable; 78 | glView.delegate = self; 79 | glView.wantsLayer = YES; 80 | // BOOL useRetinaBacking = [[NSUserDefaults standardUserDefaults] boolForKey:@"UseRetinaBacking"]; 81 | // [glView setWantsBestResolutionOpenGLSurface:useRetinaBacking]; 82 | 83 | [pixelScrollView setDocumentView:glView]; 84 | } 85 | 86 | #pragma mark - Control delegate 87 | 88 | - (IBAction)pixelFormatChanged:(id)sender { 89 | self.doc.pixelBuffer.pixelFormat = [formatPopupButton indexOfSelectedItem]; 90 | glView.pixelData = [self.doc.pixelBuffer toRGBA]; 91 | [glView setNeedsDisplay:YES]; 92 | [self updateBufferInfoTextField]; 93 | } 94 | 95 | - (void)controlTextDidChange:(NSNotification *)notification { 96 | 97 | if ([notification object] == scaleTextField) { 98 | return; 99 | } 100 | 101 | int width = [[widthTextField stringValue] intValue]; 102 | int height = [[heightTextField stringValue] intValue]; 103 | int offset = [[offsetTextField stringValue] intValue]; 104 | 105 | [widthSlider setIntValue:width]; 106 | [heightSlider setIntValue:height]; 107 | [offsetSlider setIntValue:offset]; 108 | 109 | if ([notification object] == offsetTextField) { 110 | PixlDoc *doc = self.document; 111 | doc.pixelBuffer.offset = offset; 112 | glView.pixelData = [doc.pixelBuffer toRGBA]; 113 | } 114 | 115 | glView.frame = NSMakeRect(0, 0, width, height); 116 | [glView createTexture]; 117 | [glView setNeedsDisplay:YES]; 118 | [self updateBufferInfoTextField]; 119 | } 120 | 121 | - (void)updateBufferInfoTextField { 122 | int width = [[widthTextField stringValue] intValue]; 123 | int height = [[heightTextField stringValue] intValue]; 124 | 125 | PixlDoc *doc = self.document; 126 | int fileDataLength = [doc.pixelBuffer length]; 127 | int bufferSize = [doc.pixelBuffer expectedBitLengthForImageSize:NSMakeSize(width, height)] / 8; 128 | 129 | NSString *bufferInfoString = [NSString stringWithFormat: 130 | @"Data in: %d Buffer out: %d Diff: %@%d ", 131 | fileDataLength, 132 | bufferSize, 133 | fileDataLength-bufferSize > 0 ? @"+" : @"", 134 | fileDataLength-bufferSize 135 | ]; 136 | 137 | NSString *msg = fileDataLength-bufferSize > 0 ? @"Buffer smaller than source data" : @"Buffer larger than source data"; 138 | NSColor *color = fileDataLength-bufferSize > 0 ? [NSColor orangeColor] : [NSColor redColor]; 139 | if (fileDataLength-bufferSize == 0) { 140 | msg = @"Buffer size == source data size"; 141 | color = [NSColor greenColor]; 142 | } 143 | 144 | NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:msg]; 145 | [string addAttribute:NSForegroundColorAttributeName value:color range:NSMakeRange(0,string.length)]; 146 | 147 | NSMutableAttributedString *finalStr = [[NSMutableAttributedString alloc] initWithString:bufferInfoString attributes:nil]; 148 | [finalStr appendAttributedString:string]; 149 | 150 | [bufferInfoTextField setAttributedStringValue:finalStr]; 151 | } 152 | 153 | - (IBAction)scaleToActualSize:(id)sender { 154 | [scaleSlider setIntValue:100/5]; 155 | [self scaleSliderValueChanged:nil]; 156 | } 157 | 158 | #pragma mark - Slider actions 159 | 160 | - (IBAction)scaleSliderValueChanged:(id)sender { 161 | int perc = ([scaleSlider intValue] * 5); 162 | float scale = (float)perc / 100; 163 | if (glView.scale == scale) { 164 | return; 165 | } 166 | glView.scale = scale; 167 | [scaleTextField setStringValue:[NSString stringWithFormat:@"%d%%", perc]]; 168 | 169 | int width = [[widthTextField stringValue] intValue]; 170 | int height = [[heightTextField stringValue] intValue]; 171 | 172 | glView.frame = NSMakeRect(0, 0, width, height); 173 | 174 | [glView setNeedsDisplay:YES]; 175 | } 176 | 177 | - (IBAction)widthSliderValueChanged:(id)sender { 178 | [widthTextField setStringValue:[NSString stringWithFormat:@"%d", [sender intValue]]]; 179 | [self controlTextDidChange:nil]; 180 | } 181 | 182 | - (IBAction)heightSliderValueChanged:(id)sender { 183 | [heightTextField setStringValue:[NSString stringWithFormat:@"%d", [sender intValue]]]; 184 | [self controlTextDidChange:nil]; 185 | } 186 | 187 | - (IBAction)offsetSliderValueChanged:(id)sender { 188 | [offsetTextField setStringValue:[NSString stringWithFormat:@"%d", [sender intValue]]]; 189 | PixlDoc *doc = self.document; 190 | doc.pixelBuffer.offset = [sender intValue]; 191 | glView.pixelData = [doc.pixelBuffer toRGBA]; 192 | [glView createTexture]; 193 | [glView setNeedsDisplay:YES]; 194 | [self updateBufferInfoTextField]; 195 | } 196 | 197 | #pragma mark - Menu-based slider control 198 | 199 | - (IBAction)decreaseScale:(id)sender { 200 | [scaleSlider setIntValue:[scaleSlider intValue]-1 < 1 ? 1 : [scaleSlider intValue]-1]; 201 | [self scaleSliderValueChanged:nil]; 202 | } 203 | 204 | - (IBAction)increaseScale:(id)sender { 205 | [scaleSlider setIntValue:[scaleSlider intValue]+1]; 206 | [self scaleSliderValueChanged:nil]; 207 | } 208 | 209 | - (IBAction)decreaseWidth:(id)sender { 210 | int newWidth = [[widthTextField stringValue] intValue]-1 < 0 ? 0 : [[widthTextField stringValue] intValue]-1; 211 | [widthTextField setStringValue:[NSString stringWithFormat:@"%d", newWidth]]; 212 | [self controlTextDidChange:nil]; 213 | } 214 | 215 | - (IBAction)increaseWidth:(id)sender { 216 | [widthTextField setStringValue:[NSString stringWithFormat:@"%d", [[widthTextField stringValue] intValue]+1]]; 217 | [self controlTextDidChange:nil]; 218 | } 219 | 220 | - (IBAction)decreaseHeight:(id)sender { 221 | int newHeight = [[heightTextField stringValue] intValue]-1 < 0 ? 0 : [[heightTextField stringValue] intValue]-1; 222 | [heightTextField setStringValue:[NSString stringWithFormat:@"%d", newHeight]]; 223 | [self controlTextDidChange:nil]; 224 | } 225 | 226 | - (IBAction)increaseHeight:(id)sender { 227 | [heightTextField setStringValue:[NSString stringWithFormat:@"%d", [[heightTextField stringValue] intValue]+1]]; 228 | [self controlTextDidChange:nil]; 229 | } 230 | 231 | #pragma mark - Presets 232 | 233 | - (IBAction)bestFitButtonPressed:(id)sender { 234 | 235 | 236 | if (presetIndex == -1) { 237 | if ([self loadBestPreset] == NO) { 238 | NSBeep(); 239 | return; 240 | } 241 | } 242 | NSArray *matches = [self matchingResolutionPresets]; 243 | if (presetIndex >= [matches count]-1 || presetIndex == -1) { 244 | presetIndex = 0; 245 | } else { 246 | presetIndex++; 247 | } 248 | [self loadPreset:[matches objectAtIndex:presetIndex]]; 249 | 250 | } 251 | 252 | - (BOOL)loadBestPreset { 253 | NSDictionary *res = [self bestPreset]; 254 | if (res != nil) { 255 | int index = (int)[resolutions indexOfObject:res]; 256 | [self loadPreset:[resolutions objectAtIndex:index]]; 257 | return YES; 258 | } 259 | return NO; 260 | } 261 | 262 | - (IBAction)presetSelected:(id)sender { 263 | int index = (int)[presetPopupButton indexOfSelectedItem]; 264 | [self loadPreset:[resolutions objectAtIndex:index]]; 265 | } 266 | 267 | - (NSDictionary *)bestPreset { 268 | NSArray *matches = [self matchingResolutionPresets]; 269 | //PixelFormat fmt = [PixelBuffer pixelFormatForSuffix:[self.doc.filePath pathExtension]]; 270 | 271 | if ([matches count]) { 272 | return [matches objectAtIndex:0]; 273 | } 274 | return nil; 275 | } 276 | 277 | - (void)loadPreset:(NSDictionary *)res { 278 | int w = [[res objectForKey:@"width"] intValue]; 279 | int h = [[res objectForKey:@"height"] intValue]; 280 | PixelFormat pixFmt = [self pixelFormatMatchingResolution:res]; 281 | 282 | [widthTextField setStringValue:[NSString stringWithFormat:@"%d", w]]; 283 | [heightTextField setStringValue:[NSString stringWithFormat:@"%d", h]]; 284 | 285 | if ((NSUInteger)pixFmt != -1) { 286 | [formatPopupButton selectItemAtIndex:pixFmt]; 287 | [self pixelFormatChanged:nil]; 288 | } 289 | 290 | [self controlTextDidChange:nil]; 291 | 292 | [presetPopupButton selectItemAtIndex:[resolutions indexOfObject:res]]; 293 | } 294 | 295 | #pragma mark - GLPixelViewDelegate 296 | 297 | - (void)glPixelViewDoubleClicked:(NSEvent *)event { 298 | [self increaseScale:self]; 299 | } 300 | 301 | - (void)glPixelViewClicked:(NSEvent *)event { 302 | [self increaseScale:self]; 303 | } 304 | 305 | #pragma mark - File 306 | 307 | - (IBAction)export:(id)sender { 308 | 309 | // Create save panel and add our custom accessory view 310 | NSSavePanel *sPanel = [NSSavePanel savePanel]; 311 | [sPanel setPrompt:@"Create"]; 312 | [sPanel setAccessoryView:exportFileTypePopupButton]; 313 | [sPanel setNameFieldStringValue:@"file.png"]; 314 | 315 | NSDictionary *itemName2fileTypeMap = @{ 316 | @"TIFF": @(NSTIFFFileType), 317 | @"BMP": @(NSBMPFileType), 318 | @"GIF": @(NSGIFFileType), 319 | @"JPEG": @(NSJPEGFileType), 320 | @"PNG": @(NSPNGFileType), 321 | @"JPEG2000": @(NSJPEG2000FileType) 322 | }; 323 | 324 | //run save panel 325 | [sPanel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) { 326 | if (result != NSOKButton) { 327 | return; 328 | } 329 | NSString *path = [[sPanel URL] path]; 330 | NSBitmapImageFileType type = [itemName2fileTypeMap[[exportFileTypePopupButton titleOfSelectedItem]] intValue]; 331 | [self writeGLImageToPath:path asFileType:type]; 332 | }]; 333 | } 334 | 335 | - (IBAction)dropMenuChange:(NSPopUpButton *)sender { 336 | 337 | NSDictionary *itemName2fsuffixMap = @{ 338 | @"TIFF": @"tiff", 339 | @"BMP": @"bmp", 340 | @"GIF": @"gif", 341 | @"JPEG": @"jpg", 342 | @"PNG": @"png", 343 | @"JPEG2000": @"jp2", 344 | @"RGB24": @"rgb", 345 | @"RGBA": @"rgba", 346 | @"YUV420P": @"yuv420p" 347 | }; 348 | 349 | 350 | NSSavePanel *savePanel = (NSSavePanel *)[sender window]; 351 | NSString *nameFieldString = [savePanel nameFieldStringValue]; 352 | NSString *selectedTitle = [exportFileTypePopupButton titleOfSelectedItem]; 353 | NSString *nameFieldStringWithExt = [NSString stringWithFormat:@"%@.%@", 354 | [nameFieldString stringByDeletingPathExtension], 355 | itemName2fsuffixMap[selectedTitle]]; 356 | [savePanel setNameFieldStringValue:nameFieldStringWithExt]; 357 | } 358 | 359 | - (void)writeGLImageToPath:(NSString *)path asFileType:(NSBitmapImageFileType)fileType { 360 | unsigned char *buf = [glView readGLBuffer]; 361 | NSBitmapImageRep *imageRep; 362 | imageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&buf 363 | pixelsWide:glView.frame.size.width 364 | pixelsHigh:glView.frame.size.height 365 | bitsPerSample:8 366 | samplesPerPixel:4 367 | hasAlpha:YES 368 | isPlanar:NO 369 | colorSpaceName:NSDeviceRGBColorSpace 370 | bytesPerRow:glView.frame.size.width*4 371 | bitsPerPixel:32]; 372 | NSData *data = [imageRep representationUsingType:fileType properties:nil]; 373 | [data writeToFile:path atomically: NO]; 374 | 375 | free(buf); 376 | } 377 | 378 | - (NSString *)md5hashForFileAtPath:(NSString *)path { 379 | BOOL isDir; 380 | 381 | //make sure it exists and isn't folder 382 | if (![[NSFileManager defaultManager] fileExistsAtPath:path isDirectory: &isDir] || isDir) { 383 | return nil; 384 | } 385 | 386 | NSPipe *pipe = [NSPipe pipe]; 387 | NSTask *task = [[NSTask alloc] init]; 388 | [task setLaunchPath:@"/sbin/md5"]; 389 | [task setArguments:[NSArray arrayWithObject:path]]; 390 | [task setStandardOutput:pipe]; 391 | [task launch]; 392 | 393 | //read the output from the command 394 | NSData *data = [[pipe fileHandleForReading] readDataToEndOfFile]; 395 | 396 | NSString *outputStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 397 | NSString *md5string = [[outputStr componentsSeparatedByString:@" = "] objectAtIndex:1]; 398 | return [NSString stringWithFormat:@"MD5: %@", md5string]; 399 | } 400 | 401 | #pragma mark - Resolution presets 402 | 403 | - (void)populatePresetPopupMenu { 404 | 405 | [presetPopupButton removeAllItems]; 406 | 407 | for (NSDictionary *res in resolutions) { 408 | int w = [[res objectForKey:@"width"] intValue]; 409 | int h = [[res objectForKey:@"height"] intValue]; 410 | 411 | NSString *presetName = [NSString stringWithFormat:@"%d x %d", w, h]; 412 | [presetPopupButton addItemWithTitle:presetName]; 413 | } 414 | 415 | NSArray *menuItems = [presetPopupButton itemArray]; 416 | for (NSMenuItem *menuItem in menuItems) { 417 | 418 | int index = (int)[presetPopupButton indexOfItem:menuItem]; 419 | NSDictionary *resInfoDict = [resolutions objectAtIndex:index]; 420 | 421 | // NSColor *resColor = [NSColor clearColor]; 422 | NSString *title = menuItem.title; 423 | NSFont *font = [NSFont systemFontOfSize:[NSFont systemFontSize]]; 424 | 425 | 426 | // Check if match 427 | PixelFormat pixFmt = [self pixelFormatMatchingResolution:resInfoDict]; 428 | if ((NSUInteger)pixFmt != -1) { 429 | // resColor = [NSColor greenColor]; 430 | NSString *pixFmtStr = [[PixelBuffer supportedFormats] objectAtIndex:pixFmt]; 431 | title = [NSString stringWithFormat:@"%@ (%@)", menuItem.title, pixFmtStr]; 432 | font = [NSFont boldSystemFontOfSize: [NSFont systemFontSize]]; 433 | } 434 | 435 | NSDictionary *textAttr = [NSDictionary dictionaryWithObjectsAndKeys: 436 | // resColor, NSBackgroundColorAttributeName, 437 | font, NSFontAttributeName, nil]; 438 | 439 | 440 | NSMutableAttributedString *attrTitle = [[NSMutableAttributedString alloc] initWithString:title attributes:textAttr]; 441 | 442 | [menuItem setAttributedTitle:attrTitle]; 443 | } 444 | } 445 | 446 | - (PixelFormat)pixelFormatMatchingResolution:(NSDictionary *)resInfoDict { 447 | int pixelCount = [[resInfoDict objectForKey:@"pixels"] intValue]; 448 | 449 | if (pixelCount * 4 == self.doc.pixelBuffer.length) { 450 | return PIXEL_FORMAT_RGBA; 451 | } else if (pixelCount * 3 == self.doc.pixelBuffer.length) { 452 | return PIXEL_FORMAT_RGB24; 453 | } else if (pixelCount * 1 == self.doc.pixelBuffer.length) { 454 | return PIXEL_FORMAT_RGB8; 455 | } 456 | return -1; 457 | } 458 | 459 | - (NSArray *)matchingResolutionPresets { 460 | NSMutableArray *matches = [NSMutableArray array]; 461 | if (self.doc.pixelBuffer.data == nil || [self.doc.pixelBuffer.data length] == 0) { 462 | return matches; 463 | } 464 | 465 | for (NSDictionary *res in resolutions) { 466 | // int w = [[res objectForKey:@"width"] intValue]; 467 | // int h = [[res objectForKey:@"height"] intValue]; 468 | int pixCount = [[res objectForKey:@"pixels"] intValue]; 469 | int docDataLength = (int)[self.doc.pixelBuffer.data length]; 470 | BOOL match = NO; 471 | if (pixCount * 4 == docDataLength) { 472 | match = YES; 473 | } else if (pixCount * 3 == docDataLength) { 474 | match = YES; 475 | } else if (pixCount * 1 == docDataLength) { 476 | match = YES; 477 | } 478 | if (match) { 479 | [matches addObject:res]; 480 | } 481 | } 482 | return matches; 483 | } 484 | 485 | //- (BOOL)guessResolution:(NSSize *)outSize pixelFormat:(PixelFormat *)format { 486 | // NSString *resFilePath = [[NSBundle mainBundle] pathForResource:@"resolutions" ofType:@"plist"]; 487 | // NSArray *resolutions = [NSArray arrayWithContentsOfFile:resFilePath]; 488 | // 489 | // for (NSDictionary *res in resolutions) { 490 | // int w = [[res objectForKey:@"width"] intValue]; 491 | // int h = [[res objectForKey:@"height"] intValue]; 492 | // int pixCount = [[res objectForKey:@"pixels"] intValue]; 493 | // 494 | // if (pixCount * 4 == self.data.length) { 495 | // *format = PIXEL_FORMAT_RGBA; 496 | // } else if (pixCount * 3 == self.data.length) { 497 | // *format = PIXEL_FORMAT_RGB24; 498 | // } else if (pixCount * 1 == self.data.length) { 499 | // *format = PIXEL_FORMAT_RGB8; 500 | // } else { 501 | // continue; 502 | // } 503 | // 504 | // // NSString *fmtName = [[PixelBuffer supportedFormats] objectAtIndex:*format]; 505 | // // NSLog(@"Data length %d matches %d x %d format: %@", self.data.length, w, h, fmtName); 506 | // 507 | // } 508 | // 509 | // return TRUE; 510 | //} 511 | 512 | - (void)loadResolutionsArray { 513 | NSString *resFilePath = [[NSBundle mainBundle] pathForResource:@"resolutions" ofType:@"plist"]; 514 | resolutions = [NSArray arrayWithContentsOfFile:resFilePath]; 515 | } 516 | 517 | @end 518 | -------------------------------------------------------------------------------- /PixlView/TB_zoomIn.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveinbjornt/PixlView/3e52e6ac371fe71adecd9d7016fe9641f07ea6a8/PixlView/TB_zoomIn.pdf -------------------------------------------------------------------------------- /PixlView/TB_zoomOut.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveinbjornt/PixlView/3e52e6ac371fe71adecd9d7016fe9641f07ea6a8/PixlView/TB_zoomOut.pdf -------------------------------------------------------------------------------- /PixlView/ZoomableClipView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZoomableScrollView.h 3 | // PixlView 4 | // 5 | // Created by Sveinbjorn Thordarson on 23/06/15. 6 | // Copyright (c) 2015 Sveinbjorn Thordarson. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ZoomableClipView : NSClipView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PixlView/ZoomableClipView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZoomableScrollView.m 3 | // PixlView 4 | // 5 | // Created by Sveinbjorn Thordarson on 23/06/15. 6 | // Copyright (c) 2015 Sveinbjorn Thordarson. All rights reserved. 7 | // 8 | 9 | #import "ZoomableClipView.h" 10 | 11 | @implementation ZoomableClipView 12 | 13 | // 14 | //-(void)resetCursorRects 15 | //{ 16 | // NSImage *image = [NSImage imageNamed:@"small-zoom-in-cursor.png"]; 17 | // 18 | // NSUInteger currentFlags = [[[NSApplication sharedApplication] currentEvent] modifierFlags]; 19 | // 20 | // if (currentFlags & NSShiftKeyMask) { 21 | // image = [NSImage imageNamed:@"small-zoom-cursor.png"]; 22 | // } 23 | // 24 | // NSCursor *cursor = [[NSCursor alloc] initWithImage:image hotSpot:NSZeroPoint]; 25 | // 26 | // [self addCursorRect:[self bounds] cursor:cursor]; 27 | //} 28 | // 29 | //- (void)flagsChanged:(NSEvent *)theEvent { 30 | // if (([theEvent modifierFlags] & NSShiftKeyMask) == NSAlternateKeyMask) { 31 | // [self.window resetCursorRects]; 32 | // } 33 | //} 34 | // 35 | //- (BOOL)acceptsFirstResponder { 36 | // return TRUE; 37 | //} 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /PixlView/assets/zoom-cursor.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveinbjornt/PixlView/3e52e6ac371fe71adecd9d7016fe9641f07ea6a8/PixlView/assets/zoom-cursor.psd -------------------------------------------------------------------------------- /PixlView/assets/zoom-out-cursor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveinbjornt/PixlView/3e52e6ac371fe71adecd9d7016fe9641f07ea6a8/PixlView/assets/zoom-out-cursor.png -------------------------------------------------------------------------------- /PixlView/en.lproj/PixlDoc.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "NSTextFieldCell"; title = "Scale:"; ObjectID = "07f-cl-Vl2"; */ 3 | "07f-cl-Vl2.title" = "Scale:"; 4 | 5 | /* Class = "NSMenuItem"; title = "RGBA 32"; ObjectID = "8VS-zb-HJi"; */ 6 | "8VS-zb-HJi.title" = "RGBA 32"; 7 | 8 | /* Class = "NSTextFieldCell"; title = "Placeholder text that is very long so I can see this bloody control"; ObjectID = "Ajv-6B-RAJ"; */ 9 | "Ajv-6B-RAJ.title" = "Placeholder text that is very long so I can see this bloody control"; 10 | 11 | /* Class = "NSTextFieldCell"; title = "Width:"; ObjectID = "RPf-DE-JFx"; */ 12 | "RPf-DE-JFx.title" = "Width:"; 13 | 14 | /* Class = "NSMenuItem"; title = "RGB8"; ObjectID = "T6L-qU-R4T"; */ 15 | "T6L-qU-R4T.title" = "RGB8"; 16 | 17 | /* Class = "NSTextFieldCell"; title = "Offset:"; ObjectID = "Tur-vl-BFy"; */ 18 | "Tur-vl-BFy.title" = "Offset:"; 19 | 20 | /* Class = "NSTextFieldCell"; title = "480"; ObjectID = "Yzw-pz-Bpj"; */ 21 | "Yzw-pz-Bpj.title" = "480"; 22 | 23 | /* Class = "NSTextFieldCell"; title = "0"; ObjectID = "Zmn-kN-msJ"; */ 24 | "Zmn-kN-msJ.title" = "0"; 25 | 26 | /* Class = "NSTextFieldCell"; title = "100%"; ObjectID = "bVt-0g-mAv"; */ 27 | "bVt-0g-mAv.title" = "100%"; 28 | 29 | /* Class = "NSButtonCell"; title = "Best fit"; ObjectID = "dah-Db-dah"; */ 30 | "dah-Db-dah.title" = "Best fit"; 31 | 32 | /* Class = "NSTextFieldCell"; title = "Format:"; ObjectID = "g1C-Ey-Tdp"; */ 33 | "g1C-Ey-Tdp.title" = "Format:"; 34 | 35 | /* Class = "NSWindow"; title = "PixlView"; ObjectID = "hJW-mj-eiW"; */ 36 | "hJW-mj-eiW.title" = "PixlView"; 37 | 38 | /* Class = "NSMenuItem"; title = "YUV 420p"; ObjectID = "jtt-IX-vK1"; */ 39 | "jtt-IX-vK1.title" = "YUV 420p"; 40 | 41 | /* Class = "NSTextFieldCell"; title = "Height:"; ObjectID = "kM2-rU-46l"; */ 42 | "kM2-rU-46l.title" = "Height:"; 43 | 44 | /* Class = "NSMenuItem"; title = "RGB 24"; ObjectID = "lAj-XV-t2v"; */ 45 | "lAj-XV-t2v.title" = "RGB 24"; 46 | 47 | /* Class = "NSTextFieldCell"; title = "640"; ObjectID = "sxh-Jc-kbS"; */ 48 | "sxh-Jc-kbS.title" = "640"; 49 | 50 | /* Class = "NSTextFieldCell"; title = "3eac1f3c2ef5215eb9bd13e28ae0975a"; ObjectID = "w5N-Sp-xCD"; */ 51 | "w5N-Sp-xCD.title" = "3eac1f3c2ef5215eb9bd13e28ae0975a"; 52 | -------------------------------------------------------------------------------- /PixlView/icon/PixlViewIcon.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveinbjornt/PixlView/3e52e6ac371fe71adecd9d7016fe9641f07ea6a8/PixlView/icon/PixlViewIcon.ai -------------------------------------------------------------------------------- /PixlView/icon/PixlViewIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveinbjornt/PixlView/3e52e6ac371fe71adecd9d7016fe9641f07ea6a8/PixlView/icon/PixlViewIcon.icns -------------------------------------------------------------------------------- /PixlView/icon/PixlViewIcon.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveinbjornt/PixlView/3e52e6ac371fe71adecd9d7016fe9641f07ea6a8/PixlView/icon/PixlViewIcon.psd -------------------------------------------------------------------------------- /PixlView/icon/PixlViewerIcon.iconset/icon_128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveinbjornt/PixlView/3e52e6ac371fe71adecd9d7016fe9641f07ea6a8/PixlView/icon/PixlViewerIcon.iconset/icon_128x128.png -------------------------------------------------------------------------------- /PixlView/icon/PixlViewerIcon.iconset/icon_128x128@2x.png: -------------------------------------------------------------------------------- 1 | icon_256x256.png -------------------------------------------------------------------------------- /PixlView/icon/PixlViewerIcon.iconset/icon_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveinbjornt/PixlView/3e52e6ac371fe71adecd9d7016fe9641f07ea6a8/PixlView/icon/PixlViewerIcon.iconset/icon_16x16.png -------------------------------------------------------------------------------- /PixlView/icon/PixlViewerIcon.iconset/icon_16x16@2x.png: -------------------------------------------------------------------------------- 1 | icon_32x32.png -------------------------------------------------------------------------------- /PixlView/icon/PixlViewerIcon.iconset/icon_256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveinbjornt/PixlView/3e52e6ac371fe71adecd9d7016fe9641f07ea6a8/PixlView/icon/PixlViewerIcon.iconset/icon_256x256.png -------------------------------------------------------------------------------- /PixlView/icon/PixlViewerIcon.iconset/icon_256x256@2x.png: -------------------------------------------------------------------------------- 1 | icon_512x512.png -------------------------------------------------------------------------------- /PixlView/icon/PixlViewerIcon.iconset/icon_32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveinbjornt/PixlView/3e52e6ac371fe71adecd9d7016fe9641f07ea6a8/PixlView/icon/PixlViewerIcon.iconset/icon_32x32.png -------------------------------------------------------------------------------- /PixlView/icon/PixlViewerIcon.iconset/icon_32x32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveinbjornt/PixlView/3e52e6ac371fe71adecd9d7016fe9641f07ea6a8/PixlView/icon/PixlViewerIcon.iconset/icon_32x32@2x.png -------------------------------------------------------------------------------- /PixlView/icon/PixlViewerIcon.iconset/icon_512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveinbjornt/PixlView/3e52e6ac371fe71adecd9d7016fe9641f07ea6a8/PixlView/icon/PixlViewerIcon.iconset/icon_512x512.png -------------------------------------------------------------------------------- /PixlView/icon/PixlViewerIcon.iconset/icon_512x512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveinbjornt/PixlView/3e52e6ac371fe71adecd9d7016fe9641f07ea6a8/PixlView/icon/PixlViewerIcon.iconset/icon_512x512@2x.png -------------------------------------------------------------------------------- /PixlView/images/small-zoom-cursor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveinbjornt/PixlView/3e52e6ac371fe71adecd9d7016fe9641f07ea6a8/PixlView/images/small-zoom-cursor.png -------------------------------------------------------------------------------- /PixlView/images/small-zoom-in-cursor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveinbjornt/PixlView/3e52e6ac371fe71adecd9d7016fe9641f07ea6a8/PixlView/images/small-zoom-in-cursor.png -------------------------------------------------------------------------------- /PixlView/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // PixelViewer 4 | // 5 | // Created by Sveinbjorn Thordarson on 19/06/15. 6 | // Copyright (c) 2015 Sveinbjorn Thordarson. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | void exceptionHandler(NSException *exception) { 12 | NSLog(@"%@", [exception reason]); 13 | NSLog(@"%@", [exception userInfo]); 14 | NSLog(@"%@", [exception callStackReturnAddresses]); 15 | NSLog(@"%@", [exception callStackSymbols]); 16 | } 17 | 18 | int main(int argc, const char * argv[]) { 19 | 20 | NSSetUncaughtExceptionHandler(&exceptionHandler); 21 | return NSApplicationMain(argc, argv); 22 | } 23 | -------------------------------------------------------------------------------- /PixlView/resolutions.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | height 7 | 16 8 | pixels 9 | 256 10 | width 11 | 16 12 | 13 | 14 | height 15 | 11 16 | pixels 17 | 462 18 | width 19 | 42 20 | 21 | 22 | height 23 | 32 24 | pixels 25 | 1024 26 | width 27 | 32 28 | 29 | 30 | height 31 | 30 32 | pixels 33 | 1200 34 | width 35 | 40 36 | 37 | 38 | height 39 | 32 40 | pixels 41 | 1344 42 | width 43 | 42 44 | 45 | 46 | height 47 | 32 48 | pixels 49 | 1536 50 | width 51 | 48 52 | 53 | 54 | height 55 | 40 56 | pixels 57 | 2400 58 | width 59 | 60 60 | 61 | 62 | height 63 | 64 64 | pixels 65 | 4096 66 | width 67 | 64 68 | 69 | 70 | height 71 | 64 72 | pixels 73 | 4608 74 | width 75 | 72 76 | 77 | 78 | height 79 | 36 80 | pixels 81 | 4608 82 | width 83 | 128 84 | 85 | 86 | height 87 | 64 88 | pixels 89 | 4800 90 | width 91 | 75 92 | 93 | 94 | height 95 | 48 96 | pixels 97 | 4032 98 | width 99 | 84 100 | 101 | 102 | height 103 | 40 104 | pixels 105 | 6000 106 | width 107 | 150 108 | 109 | 110 | height 111 | 64 112 | pixels 113 | 6144 114 | width 115 | 96 116 | 117 | 118 | height 119 | 64 120 | pixels 121 | 6144 122 | width 123 | 96 124 | 125 | 126 | height 127 | 48 128 | pixels 129 | 6144 130 | width 131 | 128 132 | 133 | 134 | height 135 | 65 136 | pixels 137 | 6240 138 | width 139 | 96 140 | 141 | 142 | height 143 | 96 144 | pixels 145 | 9216 146 | width 147 | 96 148 | 149 | 150 | height 151 | 64 152 | pixels 153 | 6528 154 | width 155 | 102 156 | 157 | 158 | height 159 | 64 160 | pixels 161 | 15360 162 | width 163 | 240 164 | 165 | 166 | height 167 | 102 168 | pixels 169 | 16320 170 | width 171 | 160 172 | 173 | 174 | height 175 | 128 176 | pixels 177 | 16384 178 | width 179 | 128 180 | 181 | 182 | height 183 | 120 184 | pixels 185 | 19200 186 | width 187 | 160 188 | 189 | 190 | height 191 | 144 192 | pixels 193 | 23040 194 | width 195 | 160 196 | 197 | 198 | height 199 | 168 200 | pixels 201 | 24192 202 | width 203 | 144 204 | 205 | 206 | height 207 | 152 208 | pixels 209 | 24320 210 | width 211 | 160 212 | 213 | 214 | height 215 | 160 216 | pixels 217 | 25600 218 | width 219 | 160 220 | 221 | 222 | height 223 | 192 224 | pixels 225 | 26880 226 | width 227 | 140 228 | 229 | 230 | height 231 | 200 232 | pixels 233 | 32000 234 | width 235 | 160 236 | 237 | 238 | height 239 | 144 240 | pixels 241 | 32256 242 | width 243 | 224 244 | 245 | 246 | height 247 | 176 248 | pixels 249 | 36608 250 | width 251 | 208 252 | 253 | 254 | height 255 | 160 256 | pixels 257 | 38400 258 | width 259 | 240 260 | 261 | 262 | height 263 | 176 264 | pixels 265 | 38720 266 | width 267 | 220 268 | 269 | 270 | height 271 | 256 272 | pixels 273 | 40960 274 | width 275 | 160 276 | 277 | 278 | height 279 | 208 280 | pixels 281 | 43264 282 | width 283 | 208 284 | 285 | 286 | height 287 | 192 288 | pixels 289 | 49152 290 | width 291 | 256 292 | 293 | 294 | height 295 | 192 296 | pixels 297 | 53760 298 | width 299 | 280 300 | 301 | 302 | height 303 | 128 304 | pixels 305 | 55296 306 | width 307 | 432 308 | 309 | 310 | height 311 | 240 312 | pixels 313 | 57600 314 | width 315 | 240 316 | 317 | 318 | height 319 | 192 320 | pixels 321 | 61440 322 | width 323 | 320 324 | 325 | 326 | height 327 | 200 328 | pixels 329 | 64000 330 | width 331 | 320 332 | 333 | 334 | height 335 | 256 336 | pixels 337 | 65536 338 | width 339 | 256 340 | 341 | 342 | height 343 | 208 344 | pixels 345 | 66560 346 | width 347 | 320 348 | 349 | 350 | height 351 | 224 352 | pixels 353 | 71680 354 | width 355 | 320 356 | 357 | 358 | height 359 | 240 360 | pixels 361 | 76800 362 | width 363 | 320 364 | 365 | 366 | height 367 | 256 368 | pixels 369 | 81920 370 | width 371 | 320 372 | 373 | 374 | height 375 | 340 376 | pixels 377 | 92480 378 | width 379 | 272 380 | 381 | 382 | height 383 | 240 384 | pixels 385 | 96000 386 | width 387 | 400 388 | 389 | 390 | height 391 | 320 392 | pixels 393 | 102400 394 | width 395 | 320 396 | 397 | 398 | height 399 | 240 400 | pixels 401 | 103680 402 | width 403 | 432 404 | 405 | 406 | height 407 | 192 408 | pixels 409 | 107520 410 | width 411 | 560 412 | 413 | 414 | height 415 | 270 416 | pixels 417 | 108000 418 | width 419 | 400 420 | 421 | 422 | height 423 | 288 424 | pixels 425 | 110592 426 | width 427 | 384 428 | 429 | 430 | height 431 | 234 432 | pixels 433 | 112320 434 | width 435 | 480 436 | 437 | 438 | height 439 | 250 440 | pixels 441 | 120000 442 | width 443 | 480 444 | 445 | 446 | height 447 | 300 448 | pixels 449 | 120000 450 | width 451 | 400 452 | 453 | 454 | height 455 | 240 456 | pixels 457 | 90240 458 | width 459 | 376 460 | 461 | 462 | height 463 | 390 464 | pixels 465 | 121680 466 | width 467 | 312 468 | 469 | 470 | height 471 | 200 472 | pixels 473 | 128000 474 | width 475 | 640 476 | 477 | 478 | height 479 | 272 480 | pixels 481 | 130560 482 | width 483 | 480 484 | 485 | 486 | height 487 | 256 488 | pixels 489 | 131072 490 | width 491 | 512 492 | 493 | 494 | height 495 | 352 496 | pixels 497 | 146432 498 | width 499 | 416 500 | 501 | 502 | height 503 | 240 504 | pixels 505 | 153600 506 | width 507 | 640 508 | 509 | 510 | height 511 | 320 512 | pixels 513 | 153600 514 | width 515 | 480 516 | 517 | 518 | height 519 | 256 520 | pixels 521 | 163840 522 | width 523 | 640 524 | 525 | 526 | height 527 | 342 528 | pixels 529 | 175104 530 | width 531 | 512 532 | 533 | 534 | height 535 | 240 536 | pixels 537 | 192000 538 | width 539 | 800 540 | 541 | 542 | height 543 | 384 544 | pixels 545 | 196608 546 | width 547 | 512 548 | 549 | 550 | height 551 | 320 552 | pixels 553 | 204800 554 | width 555 | 640 556 | 557 | 558 | height 559 | 350 560 | pixels 561 | 224000 562 | width 563 | 640 564 | 565 | 566 | height 567 | 360 568 | pixels 569 | 230400 570 | width 571 | 640 572 | 573 | 574 | height 575 | 500 576 | pixels 577 | 240000 578 | width 579 | 480 580 | 581 | 582 | height 583 | 348 584 | pixels 585 | 250560 586 | width 587 | 720 588 | 589 | 590 | height 591 | 350 592 | pixels 593 | 252000 594 | width 595 | 720 596 | 597 | 598 | height 599 | 400 600 | pixels 601 | 256000 602 | width 603 | 640 604 | 605 | 606 | height 607 | 364 608 | pixels 609 | 262080 610 | width 611 | 720 612 | 613 | 614 | height 615 | 352 616 | pixels 617 | 281600 618 | width 619 | 800 620 | 621 | 622 | height 623 | 480 624 | pixels 625 | 288000 626 | width 627 | 600 628 | 629 | 630 | height 631 | 480 632 | pixels 633 | 307200 634 | width 635 | 640 636 | 637 | 638 | height 639 | 512 640 | pixels 641 | 327680 642 | width 643 | 640 644 | 645 | 646 | height 647 | 480 648 | pixels 649 | 368640 650 | width 651 | 768 652 | 653 | 654 | height 655 | 480 656 | pixels 657 | 384000 658 | width 659 | 800 660 | 661 | 662 | height 663 | 480 664 | pixels 665 | 407040 666 | width 667 | 848 668 | 669 | 670 | height 671 | 480 672 | pixels 673 | 409920 674 | width 675 | 854 676 | 677 | 678 | height 679 | 600 680 | pixels 681 | 480000 682 | width 683 | 800 684 | 685 | 686 | height 687 | 540 688 | pixels 689 | 518400 690 | width 691 | 960 692 | 693 | 694 | height 695 | 624 696 | pixels 697 | 519168 698 | width 699 | 832 700 | 701 | 702 | height 703 | 544 704 | pixels 705 | 522240 706 | width 707 | 960 708 | 709 | 710 | height 711 | 576 712 | pixels 713 | 589824 714 | width 715 | 1024 716 | 717 | 718 | height 719 | 600 720 | pixels 721 | 614400 722 | width 723 | 1024 724 | 725 | 726 | height 727 | 640 728 | pixels 729 | 614400 730 | width 731 | 960 732 | 733 | 734 | height 735 | 640 736 | pixels 737 | 655360 738 | width 739 | 1024 740 | 741 | 742 | height 743 | 720 744 | pixels 745 | 691200 746 | width 747 | 960 748 | 749 | 750 | height 751 | 640 752 | pixels 753 | 727040 754 | width 755 | 1136 756 | 757 | 758 | height 759 | 768 760 | pixels 761 | 786432 762 | width 763 | 1024 764 | 765 | 766 | height 767 | 800 768 | pixels 769 | 819200 770 | width 771 | 1024 772 | 773 | 774 | height 775 | 720 776 | pixels 777 | 829440 778 | width 779 | 1152 780 | 781 | 782 | height 783 | 768 784 | pixels 785 | 884736 786 | width 787 | 1152 788 | 789 | 790 | height 791 | 720 792 | pixels 793 | 921600 794 | width 795 | 1280 796 | 797 | 798 | height 799 | 832 800 | pixels 801 | 931840 802 | width 803 | 1120 804 | 805 | 806 | height 807 | 768 808 | pixels 809 | 983040 810 | width 811 | 1280 812 | 813 | 814 | height 815 | 864 816 | pixels 817 | 995328 818 | width 819 | 1152 820 | 821 | 822 | height 823 | 750 824 | pixels 825 | 1000500 826 | width 827 | 1334 828 | 829 | 830 | height 831 | 800 832 | pixels 833 | 1024000 834 | width 835 | 1280 836 | 837 | 838 | height 839 | 900 840 | pixels 841 | 1036800 842 | width 843 | 1152 844 | 845 | 846 | height 847 | 1024 848 | pixels 849 | 1048576 850 | width 851 | 1024 852 | 853 | 854 | height 855 | 768 856 | pixels 857 | 1049088 858 | width 859 | 1366 860 | 861 | 862 | height 863 | 854 864 | pixels 865 | 1093120 866 | width 867 | 1280 868 | 869 | 870 | height 871 | 768 872 | pixels 873 | 1228800 874 | width 875 | 1600 876 | 877 | 878 | height 879 | 960 880 | pixels 881 | 1228800 882 | width 883 | 1280 884 | 885 | 886 | height 887 | 900 888 | pixels 889 | 1296000 890 | width 891 | 1440 892 | 893 | 894 | height 895 | 1024 896 | pixels 897 | 1310720 898 | width 899 | 1280 900 | 901 | 902 | height 903 | 960 904 | pixels 905 | 1382400 906 | width 907 | 1440 908 | 909 | 910 | height 911 | 900 912 | pixels 913 | 1440000 914 | width 915 | 1600 916 | 917 | 918 | height 919 | 1050 920 | pixels 921 | 1470000 922 | width 923 | 1400 924 | 925 | 926 | height 927 | 1024 928 | pixels 929 | 1474560 930 | width 931 | 1440 932 | 933 | 934 | height 935 | 1080 936 | pixels 937 | 1555200 938 | width 939 | 1440 940 | 941 | 942 | height 943 | 1024 944 | pixels 945 | 1638400 946 | width 947 | 1600 948 | 949 | 950 | height 951 | 1050 952 | pixels 953 | 1764000 954 | width 955 | 1680 956 | 957 | 958 | height 959 | 1200 960 | pixels 961 | 1920000 962 | width 963 | 1600 964 | 965 | 966 | height 967 | 1080 968 | pixels 969 | 2073600 970 | width 971 | 1920 972 | 973 | 974 | height 975 | 1200 976 | pixels 977 | 2304000 978 | width 979 | 1920 980 | 981 | 982 | height 983 | 1280 984 | pixels 985 | 2457600 986 | width 987 | 1920 988 | 989 | 990 | height 991 | 1152 992 | pixels 993 | 2359296 994 | width 995 | 2048 996 | 997 | 998 | height 999 | 1344 1000 | pixels 1001 | 2408448 1002 | width 1003 | 1792 1004 | 1005 | 1006 | height 1007 | 1392 1008 | pixels 1009 | 2583552 1010 | width 1011 | 1856 1012 | 1013 | 1014 | height 1015 | 900 1016 | pixels 1017 | 2592000 1018 | width 1019 | 2880 1020 | 1021 | 1022 | height 1023 | 1440 1024 | pixels 1025 | 2592000 1026 | width 1027 | 1800 1028 | 1029 | 1030 | height 1031 | 1280 1032 | pixels 1033 | 2621440 1034 | width 1035 | 2048 1036 | 1037 | 1038 | height 1039 | 1400 1040 | pixels 1041 | 2688000 1042 | width 1043 | 1920 1044 | 1045 | 1046 | height 1047 | 1080 1048 | pixels 1049 | 2741040 1050 | width 1051 | 2538 1052 | 1053 | 1054 | height 1055 | 1080 1056 | pixels 1057 | 2764800 1058 | width 1059 | 2560 1060 | 1061 | 1062 | height 1063 | 1440 1064 | pixels 1065 | 2764800 1066 | width 1067 | 1920 1068 | 1069 | 1070 | height 1071 | 1440 1072 | pixels 1073 | 3110400 1074 | width 1075 | 2160 1076 | 1077 | 1078 | height 1079 | 1536 1080 | pixels 1081 | 3145728 1082 | width 1083 | 2048 1084 | 1085 | 1086 | height 1087 | 1440 1088 | pixels 1089 | 3317760 1090 | width 1091 | 2304 1092 | 1093 | 1094 | height 1095 | 1440 1096 | pixels 1097 | 3686400 1098 | width 1099 | 2560 1100 | 1101 | 1102 | height 1103 | 1728 1104 | pixels 1105 | 3981312 1106 | width 1107 | 2304 1108 | 1109 | 1110 | height 1111 | 1600 1112 | pixels 1113 | 4096000 1114 | width 1115 | 2560 1116 | 1117 | 1118 | height 1119 | 1700 1120 | pixels 1121 | 4352000 1122 | width 1123 | 2560 1124 | 1125 | 1126 | height 1127 | 1920 1128 | pixels 1129 | 4915200 1130 | width 1131 | 2560 1132 | 1133 | 1134 | height 1135 | 1440 1136 | pixels 1137 | 4953600 1138 | width 1139 | 3440 1140 | 1141 | 1142 | height 1143 | 1800 1144 | pixels 1145 | 5184000 1146 | width 1147 | 2880 1148 | 1149 | 1150 | height 1151 | 2048 1152 | pixels 1153 | 5242880 1154 | width 1155 | 2560 1156 | 1157 | 1158 | height 1159 | 2100 1160 | pixels 1161 | 5880000 1162 | width 1163 | 2800 1164 | 1165 | 1166 | height 1167 | 1800 1168 | pixels 1169 | 5760000 1170 | width 1171 | 3200 1172 | 1173 | 1174 | height 1175 | 2048 1176 | pixels 1177 | 6553600 1178 | width 1179 | 3200 1180 | 1181 | 1182 | height 1183 | 2400 1184 | pixels 1185 | 7680000 1186 | width 1187 | 3200 1188 | 1189 | 1190 | height 1191 | 2160 1192 | pixels 1193 | 8294400 1194 | width 1195 | 3840 1196 | 1197 | 1198 | height 1199 | 2400 1200 | pixels 1201 | 9216000 1202 | width 1203 | 3840 1204 | 1205 | 1206 | height 1207 | 2304 1208 | pixels 1209 | 9437184 1210 | width 1211 | 4096 1212 | 1213 | 1214 | height 1215 | 2160 1216 | pixels 1217 | 11059200 1218 | width 1219 | 5120 1220 | 1221 | 1222 | height 1223 | 3072 1224 | pixels 1225 | 12582912 1226 | width 1227 | 4096 1228 | 1229 | 1230 | height 1231 | 2880 1232 | pixels 1233 | 14745600 1234 | width 1235 | 5120 1236 | 1237 | 1238 | height 1239 | 3200 1240 | pixels 1241 | 16384000 1242 | width 1243 | 5120 1244 | 1245 | 1246 | height 1247 | 4096 1248 | pixels 1249 | 20971520 1250 | width 1251 | 5120 1252 | 1253 | 1254 | height 1255 | 4096 1256 | pixels 1257 | 26214400 1258 | width 1259 | 6400 1260 | 1261 | 1262 | height 1263 | 4800 1264 | pixels 1265 | 30720000 1266 | width 1267 | 6400 1268 | 1269 | 1270 | height 1271 | 4320 1272 | pixels 1273 | 33177600 1274 | width 1275 | 7680 1276 | 1277 | 1278 | height 1279 | 4800 1280 | pixels 1281 | 36864000 1282 | width 1283 | 7680 1284 | 1285 | 1286 | height 1287 | 4608 1288 | pixels 1289 | 37748736 1290 | width 1291 | 8192 1292 | 1293 | 1294 | height 1295 | 8192 1296 | pixels 1297 | 67108864 1298 | width 1299 | 8192 1300 | 1301 | 1302 | 1303 | -------------------------------------------------------------------------------- /PixlView/resolutions.txt: -------------------------------------------------------------------------------- 1 | 16,16 2 | 42,11 3 | 32,32 4 | 40,30 5 | 42,32 6 | 48,32 7 | 60,40 8 | 64,64 9 | 72,64 10 | 128,36 11 | 75,64 12 | 84,48 13 | 150,40 14 | 96,64 15 | 96,64 16 | 128,48 17 | 96,65 18 | 96,96 19 | 102,64 20 | 240,64 21 | 160,102 22 | 128,128 23 | 160,120 24 | 160,144 25 | 144,168 26 | 160,152 27 | 160,160 28 | 140,192 29 | 160,200 30 | 224,144 31 | 208,176 32 | 240,160 33 | 220,176 34 | 160,256 35 | 208,208 36 | 256,192 37 | 280,192 38 | 432,128 39 | 240,240 40 | 320,192 41 | 320,200 42 | 256,256 43 | 320,208 44 | 320,224 45 | 320,240 46 | 320,256 47 | 272,340 48 | 400,240 49 | 320,320 50 | 432,240 51 | 560,192 52 | 400,270 53 | 384,288 54 | 480,234 55 | 480,250 56 | 400,300 57 | 376,240 58 | 312,390 59 | 640,200 60 | 480,272 61 | 512,256 62 | 416,352 63 | 640,240 64 | 480,320 65 | 640,256 66 | 512,342 67 | 800,240 68 | 512,384 69 | 640,320 70 | 640,350 71 | 640,360 72 | 480,500 73 | 720,348 74 | 720,350 75 | 640,400 76 | 720,364 77 | 800,352 78 | 600,480 79 | 640,480 80 | 640,512 81 | 768,480 82 | 800,480 83 | 848,480 84 | 854,480 85 | 800,600 86 | 960,540 87 | 832,624 88 | 960,544 89 | 1024,576 90 | 1024,600 91 | 960,640 92 | 1024,640 93 | 960,720 94 | 1136,640 95 | 1024,768 96 | 1024,800 97 | 1152,720 98 | 1152,768 99 | 1280,720 100 | 1120,832 101 | 1280,768 102 | 1152,864 103 | 1334,750 104 | 1280,800 105 | 1152,900 106 | 1024,1024 107 | 1366,768 108 | 1280,854 109 | 1600,768 110 | 1280,960 111 | 1440,900 112 | 1280,1024 113 | 1440,960 114 | 1600,900 115 | 1400,1050 116 | 1440,1024 117 | 1440,1080 118 | 1600,1024 119 | 1680,1050 120 | 1600,1200 121 | 1920,1080 122 | 1920,1200 123 | 1920,1280 124 | 2048,1152 125 | 1792,1344 126 | 1856,1392 127 | 2880,900 128 | 1800,1440 129 | 2048,1280 130 | 1920,1400 131 | 2538,1080 132 | 2560,1080 133 | 1920,1440 134 | 2160,1440 135 | 2048,1536 136 | 2304,1440 137 | 2560,1440 138 | 2304,1728 139 | 2560,1600 140 | 2560,1700 141 | 2560,1920 142 | 3440,1440 143 | 2880,1800 144 | 2560,2048 145 | 2800,2100 146 | 3200,1800 147 | 3200,2048 148 | 3200,2400 149 | 3840,2160 150 | 3840,2400 151 | 4096,2304 152 | 5120,2160 153 | 4096,3072 154 | 5120,2880 155 | 5120,3200 156 | 5120,4096 157 | 6400,4096 158 | 6400,4800 159 | 7680,4320 160 | 7680,4800 161 | 8192,4608 162 | 8192,8192 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PixlView 2 | 3 | 4 | PixlView is a native, open-source raw pixel data viewer for Mac OS X. Raw pixel data can be interpreted and displayed in pixel formats such as RGBA, RGB24, RGB8 and YUV420p. Pixel buffers can also be exported to various formats. Uses OpenGL for rendering. Runs on Mac OS X 10.8 or later. Source is distributed under the BSD license. 5 | 6 | PixlView is a work in progress. Stuff may be broken. 7 | 8 | 9 | 10 | 11 | 12 | ## Screenshots 13 | 14 | ![PixlView Screenshot 1](https://raw.githubusercontent.com/sveinbjornt/PixlView/master/screenshots/screenshot1.png) 15 | 16 | ![PixlView Screenshot 2](https://raw.githubusercontent.com/sveinbjornt/PixlView/master/screenshots/screenshot2.png) 17 | 18 | 19 | ## License 20 | 21 | Copyright (c) Sveinbjorn Thordarson 22 | All rights reserved. 23 | 24 | Redistribution and use in source and binary forms, with or without modification, 25 | are permitted provided that the following conditions are met: 26 | 27 | 1. Redistributions of source code must retain the above copyright notice, this 28 | list of conditions and the following disclaimer. 29 | 30 | 2. Redistributions in binary form must reproduce the above copyright notice, this 31 | list of conditions and the following disclaimer in the documentation and/or other 32 | materials provided with the distribution. 33 | 34 | 3. Neither the name of the copyright holder nor the names of its contributors may 35 | be used to endorse or promote products derived from this software without specific 36 | prior written permission. 37 | 38 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 39 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 40 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 41 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 42 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 43 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 44 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 45 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 47 | POSSIBILITY OF SUCH DAMAGE. 48 | -------------------------------------------------------------------------------- /binaries/PixlView.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveinbjornt/PixlView/3e52e6ac371fe71adecd9d7016fe9641f07ea6a8/binaries/PixlView.zip -------------------------------------------------------------------------------- /screenshots/appicon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveinbjornt/PixlView/3e52e6ac371fe71adecd9d7016fe9641f07ea6a8/screenshots/appicon.jpg -------------------------------------------------------------------------------- /screenshots/screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveinbjornt/PixlView/3e52e6ac371fe71adecd9d7016fe9641f07ea6a8/screenshots/screenshot1.png -------------------------------------------------------------------------------- /screenshots/screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveinbjornt/PixlView/3e52e6ac371fe71adecd9d7016fe9641f07ea6a8/screenshots/screenshot2.png --------------------------------------------------------------------------------