Sample

Schnappinger/aoi/artofillusion.translators.TextureImageExporter

Human rating uses the original dataset scale.

Human2.89
Lines195

Scores

MethodScoreScaleDataset rank
(0–100)
Posnett00–1; higher is more readable
19.4Δ 1.1
Scalabrino0.5850–1; higher is more readable
19.9Δ 0.6
Dorn0.0690–1; higher is more readable
29.7Δ 9.2
Mi0.0630–1; higher is more readable
7.6Δ 12.9
LLOC99Logical lines; fewer is more readable
25.2Δ 4.8
DeepSeek V4 Pro14.670–20; mean of three runs
34.8Δ 14.4
GPT-6.1 Sol14.330–20; mean of three runs
19.8Δ 0.7
BTTF0.1170–1; higher is more readable
4.0Δ 16.5
Human2.891–4; original rating
20.5

Views

Source code

/* Copyright (C) 2003 by Peter Eastman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ package artofillusion.translators; import artofillusion.image.*; import artofillusion.math.*; import artofillusion.object.*; import artofillusion.procedural.*; import artofillusion.texture.*; import java.awt.Image; import java.io.*; import java.util.*; /** This class can be used by various other exporters. It collects information about the textures used by a set of objects, and writes out image files for the 2D textures. */ public class TextureImageExporter { private Hashtable textureTable; private File dir; private String baseFilename; private int quality, components, width, height; private int nextID; public static final int DIFFUSE = 1; public static final int SPECULAR = 2; public static final int HILIGHT = 4; public static final int TRANSPARENT = 8; public static final int EMISSIVE = 16; public static final int BUMP = 32; /** Create a new TextureImageExporter. @param dir the directory in which to save images @param baseFilename the base filename to use for image files @param quality the JPEG image quality (from 0 to 100) @param components specifies which components to write images for (a sum of the flags given above) @param width the width to use for images @param height the height to use for images */ public TextureImageExporter(File dir, String baseFilename, int quality, int components, int width, int height) { textureTable = new Hashtable(); this.dir = dir; this.baseFilename = baseFilename; this.quality = quality; this.components = components; this.width = width; this.height = height; nextID = 1; } /** Check the texture of an object, and record what information needs to be exported. */ public void addObject(ObjectInfo obj) { Texture tex = obj.getObject().getTexture(); if (tex == null) return; TextureImageInfo info = (TextureImageInfo) textureTable.get(tex); if (info == null) { // We haven't encountered this texture before, so create a new TextureImageInfo for it. info = new TextureImageInfo(tex, obj.getObject().getAverageParameterValues()); textureTable.put(tex, info); if (tex instanceof ImageMapTexture) { // Go through the image maps, and see which ones are being used. ImageMapTexture imt = (ImageMapTexture) tex; info.diffuseFilename = (imt.diffuseColor.getImage() != null ? newName() : null); info.specularFilename = (imt.specularColor.getImage() != null || imt.specularity.getImage() != null ? newName() : null); info.hilightFilename = (imt.specularColor.getImage() != null || imt.shininess.getImage() != null ? newName() : null); info.transparentFilename = (imt.transparentColor.getImage() != null || imt.transparency.getImage() != null ? newName() : null); info.emissiveFilename = (imt.emissiveColor.getImage() != null ? newName() : null); } else if (tex instanceof ProceduralTexture2D) { Module output[] = ((ProceduralTexture2D) tex).getProcedure().getOutputModules(); info.diffuseFilename = (output[0].inputConnected(0) ? newName() : null); info.specularFilename = (output[1].inputConnected(0) || output[5].inputConnected(0) ? newName() : null); info.hilightFilename = (output[1].inputConnected(0) || output[6].inputConnected(0) ? newName() : null); info.transparentFilename = (output[2].inputConnected(0) || output[4].inputConnected(0) ? newName() : null); info.emissiveFilename = (output[3].inputConnected(0) ? newName() : null); } } // Determine the range of UV coordinates for this object. if (tex instanceof ImageMapTexture) { info.minu = info.minv = 0.0; info.maxu = info.maxv = 1.0; } else if (tex instanceof ProceduralTexture2D) { Mesh mesh = (obj.getObject() instanceof Mesh ? (Mesh) obj.getObject() : obj.getObject().convertToTriangleMesh(0.1)); Mapping2D map = (Mapping2D) obj.getObject().getTextureMapping(); if (map instanceof UVMapping && mesh instanceof FacetedMesh && ((UVMapping) map).isPerFaceVertex((FacetedMesh) mesh)) { Vec2 coords[][] = ((UVMapping) map).findFaceTextureCoordinates((FacetedMesh) mesh); for (int i = 0; i < coords.length; i++) for (int j = 0; j < coords[i].length; j++) { if (coords[i][j].x < info.minu) info.minu = coords[i][j].x; if (coords[i][j].x > info.maxu) info.maxu = coords[i][j].x; if (coords[i][j].y < info.minv) info.minv = coords[i][j].y; if (coords[i][j].y > info.maxv) info.maxv = coords[i][j].y; } } else { Vec2 coords[] = map.findTextureCoordinates(mesh); for (int i = 0; i < coords.length; i++) { if (coords[i].x < info.minu) info.minu = coords[i].x; if (coords[i].x > info.maxu) info.maxu = coords[i].x; if (coords[i].y < info.minv) info.minv = coords[i].y; if (coords[i].y > info.maxv) info.maxv = coords[i].y; } } } } /** Create a new name for an image file. */ private String newName() { return baseFilename+(nextID++)+".jpg"; } /** Get the TextureImageInfo (which may be null) for a particular texture. */ public TextureImageInfo getTextureInfo(Texture tex) { return (tex != null ? (TextureImageInfo) textureTable.get(tex) : null); } /** Get an Enumeration of all TextureImageInfos. */ public Enumeration getTextures() { return textureTable.elements(); } /** Write out all of the images for the various textures. */ public void saveImages() throws IOException, InterruptedException { Enumeration e = textureTable.keys(); while (e.hasMoreElements()) { Texture tex = (Texture) e.nextElement(); TextureImageInfo info = (TextureImageInfo) textureTable.get(tex); if ((components&DIFFUSE) != 0) writeComponentImage(info, Texture2D.DIFFUSE_COLOR_COMPONENT, info.diffuseFilename); if ((components&SPECULAR) != 0) writeComponentImage(info, Texture2D.SPECULAR_COLOR_COMPONENT, info.specularFilename); if ((components&HILIGHT) != 0) writeComponentImage(info, Texture2D.HILIGHT_COLOR_COMPONENT, info.hilightFilename); if ((components&TRANSPARENT) != 0) writeComponentImage(info, Texture2D.TRANSPARENT_COLOR_COMPONENT, info.transparentFilename); if ((components&EMISSIVE) != 0) writeComponentImage(info, Texture2D.EMISSIVE_COLOR_COMPONENT, info.emissiveFilename); } } /** Write an image file to disk representating a component of a texture. */ private void writeComponentImage(TextureImageInfo info, int component, String filename) throws IOException, InterruptedException { if (filename == null || !(info.texture instanceof Texture2D)) return; Image img = ((Texture2D) info.texture).createComponentImage(info.minu, info.maxu, info.minv, info.maxv, width, height, component, 0.0, info.paramValue); ImageSaver.saveImage(img, new File(dir, filename), ImageSaver.FORMAT_JPEG, quality); } }

Loading feature diagnosis…

Source regions

Feature contributions

Feature contributions

FeatureValueContribution
(log-odds)
Halstead volumeHow much symbolic information the code contains. It combines the total number of operators and values with the number of distinct ones.10075.729−332.499
Source linesThe number of non-empty source lines.195+78
Byte entropyHow varied the bytes in the source text are. Repeated bytes give a lower value; a more even mixture gives a higher value.4.826−7.24

Intercept 8.87 + feature contributions = -252.869 (log-odds).
Score = sigmoid(-252.869) = 0.

Score0.585

Feature contributions

FeatureValueContribution
(log-odds)
Comment layout frequencyHow frequently the layout switches between lines containing only comments or whitespace and lines containing code.196−5.903
Indentation frequencyHow rapidly indentation changes from line to line.176+5.351
Number layout frequencyHow rapidly the number of numeric values per line changes through the code.176−3.618
Identifier layout (vertical)How rapidly the visual pattern of identifier characters changes from top to bottom.194.871+2.314
Identifier layout (horizontal)How rapidly the visual pattern of identifier characters changes from left to right. It measures spatial frequency, not the meaning of the names.138.964−2.221
Comment layout (horizontal)How rapidly the visual pattern of comment characters changes from left to right.138.995+1.438
Operator visual areaThe share of the code’s visual area occupied by operators such as +, =, and *.0.1−0.027

Intercept 0.07 + feature contributions = -2.596 (log-odds).
Score = sigmoid(-2.596) = 0.069.

Score0.063
Score99
Run 1

The code is structured reasonably well with clear method separation and helpful comments. Javadoc documentations explain purpose well. However, the addObject method is overly long and contains deep nesting with complex conditional logic for handling different texture types. The UV coordinate range calculation has duplicated code in nested loops, reducing clarity. Some lines are excessively long (ternary expressions for filename assignment), making them difficult to read. Action granularity is mostly one action per line, but the conditional assignments pack too much logic into single statements. The reading flow is disrupted by the long if-else chains and nested loops within addObject. While the class has clear intent and good organization at the top level, the complexity in texture handling brings down readability. The use of magic numbers for array indices (output[1], output[5], etc.) also hurts clarity.

Run 2

The code is well-structured and highly readable. It has a clear class purpose, logical organization, and consistent naming conventions. Methods are mostly concise and focused, with one action per line in most cases. Deep nesting is limited, though the UV coordinate calculation loops introduce some nesting (2-3 levels) that slightly reduces flow. The intent of each method and conditional is generally clear, with sensible early returns. A few long lines with multiple conditional expressions (e.g., assigning filenames with nested ternaries) slightly hamper readability, but they remain understandable. Javadoc comments provide useful context. Overall, the code is well-factored and maintainable.

Run 3

The code has a clear class purpose and good documentation, but readability is hampered by several issues. The addObject method is overly long (around 60 lines) and handles too many responsibilities: texture registration, ImageMapTexture setup, ProceduralTexture2D setup, and UV coordinate bounds calculation. The deeply nested conditionals and repetitive bounds-checking loops increase cognitive load. Long ternary assignments on single lines (e.g., the filenames) violate action granularity and hurt readability. Ternary expressions for null checking are concise but reduce clarity. Duplicated min/max update logic appears twice for different coordinate types. The method would benefit from extraction into smaller, focused helper methods. The overall structure and naming are decent, but the density and nesting keep this from scoring higher.

Run 1

Code Structure: Clear class responsibility and sensible separation of filename generation, lookup, and image writing, but addObject combines texture registration with UV-bound calculation. Nesting: Most methods are shallow; addObject has nested type checks, loops, and conditionals that increase reading effort. Clarity of intent: Documentation, descriptive method names, and component constants communicate purpose well, while abbreviated variables, raw collections, casts, and unexplained procedural-output indices obscure details. Code length: Generally reasonable, but repeated filename checks and duplicated UV-bound updates could be extracted into helpers. Action granularity: Mostly one action per line, although chained assignments and filename generation with an increment combine operations. Reading flow: Methods follow a natural progression from collecting textures to exporting images; inconsistent brace indentation, long conditional expressions, and dense casting interrupt that flow.

Run 2

Code Structure: The class has a coherent responsibility and separates naming, lookup, and image writing, but addObject combines texture registration, component detection, and UV-bound calculation. Nesting: Most methods are shallow, while addObject contains several conditional levels and nested loops. Clarity of intent: Documentation, comments, and descriptive method names clarify the workflow; abbreviated variables, raw collections, casts, and unexplained output-array indices obscure details. Code length: Generally reasonable, but repeated component checks and duplicated coordinate-bound updates add avoidable length. Action granularity: Most statements perform one action, though chained assignments, grouped declarations, and an increment embedded in filename construction reduce explicitness. Reading flow: The progression from collecting texture information to exporting images is natural, but inconsistent brace placement, long conditional expressions, and dense formatting interrupt readability.

Run 3

Code Structure: The class has a clear responsibility and separates naming, lookup, and image writing into methods, but addObject combines texture registration and UV-range calculation. Nesting: Most methods are shallow, while addObject contains nested type checks, loops, and conditionals that increase reading effort. Clarity of intent: Documentation, component constants, and descriptive method names explain the purpose well; abbreviated variables and unexplained procedural-output indices obscure details. Code length: Generally reasonable, but repeated filename selection and UV-bound updates could be extracted into helpers. Action granularity: Most lines perform one action, although chained assignments and the increment embedded in filename creation combine operations. Reading flow: Registration, coordinate calculation, and export follow a logical sequence, but inconsistent brace placement, long conditional expressions, raw collections requiring casts, and dense formatting interrupt the flow.