<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Differences of GX::Image::WriteToFile(...) on Windows and MacOS in Archicad C++ API</title>
    <link>https://community.graphisoft.com/t5/Archicad-C-API/Differences-of-GX-Image-WriteToFile-on-Windows-and-MacOS/m-p/398137#M8582</link>
    <description>&lt;P&gt;&lt;SPAN&gt;Hello everyone,&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;We are developing an Archicad Add-On for Windows and MacOS. We are seeing inconsistent behavior of the GX::Image::WriteToFile(...) function between both platforms. On Windows, everything works as expected. On MacOS, we are getting a log entry “error 20: Not a directory” (macOS system error?) from within the Archicad API, followed by a return code -7003.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;The passed path is checked and valid. We can write files to that path directly, so there shouldn’t be any issues with access rights either. The image file is valid too, and we can use the above mentioned function to write it to a location outside the Archicad library. &lt;/SPAN&gt;&lt;SPAN&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;We are currently implementing a workaround where we copy it into the library via IO::FileSystem::Copy(...), but this cannot be the intended logic, right?&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;This occurs with the latest Archicad 27 Technical Preview.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Two questions:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;1.&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN&gt;Are there any differences in the expected behavior of GX::Image::WriteToFile(...) between Windows and MacOS?2.&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN&gt;Where can we find the official documentation for this function and / or class?&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Mon, 16 Sep 2024 12:54:30 GMT</pubDate>
    <dc:creator>DavidKahlEnscape</dc:creator>
    <dc:date>2024-09-16T12:54:30Z</dc:date>
    <item>
      <title>Differences of GX::Image::WriteToFile(...) on Windows and MacOS</title>
      <link>https://community.graphisoft.com/t5/Archicad-C-API/Differences-of-GX-Image-WriteToFile-on-Windows-and-MacOS/m-p/398137#M8582</link>
      <description>&lt;P&gt;&lt;SPAN&gt;Hello everyone,&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;We are developing an Archicad Add-On for Windows and MacOS. We are seeing inconsistent behavior of the GX::Image::WriteToFile(...) function between both platforms. On Windows, everything works as expected. On MacOS, we are getting a log entry “error 20: Not a directory” (macOS system error?) from within the Archicad API, followed by a return code -7003.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;The passed path is checked and valid. We can write files to that path directly, so there shouldn’t be any issues with access rights either. The image file is valid too, and we can use the above mentioned function to write it to a location outside the Archicad library. &lt;/SPAN&gt;&lt;SPAN&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;We are currently implementing a workaround where we copy it into the library via IO::FileSystem::Copy(...), but this cannot be the intended logic, right?&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;This occurs with the latest Archicad 27 Technical Preview.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Two questions:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;1.&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN&gt;Are there any differences in the expected behavior of GX::Image::WriteToFile(...) between Windows and MacOS?2.&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN&gt;Where can we find the official documentation for this function and / or class?&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 16 Sep 2024 12:54:30 GMT</pubDate>
      <guid>https://community.graphisoft.com/t5/Archicad-C-API/Differences-of-GX-Image-WriteToFile-on-Windows-and-MacOS/m-p/398137#M8582</guid>
      <dc:creator>DavidKahlEnscape</dc:creator>
      <dc:date>2024-09-16T12:54:30Z</dc:date>
    </item>
    <item>
      <title>Re: Differences of GX::Image::WriteToFile(...) on Windows and MacOS</title>
      <link>https://community.graphisoft.com/t5/Archicad-C-API/Differences-of-GX-Image-WriteToFile-on-Windows-and-MacOS/m-p/398212#M8585</link>
      <description>&lt;P&gt;Hi,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Theoretically, there shouldn't be any difference between Mac and Windows.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Could you please tell me more about the location you are passing to the function? What does `location.GetStatus()` tell you before you pass it to `WriteToFile()` ? Does the path you are writing to exist?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Best, Akos&lt;/P&gt;</description>
      <pubDate>Thu, 14 Sep 2023 08:14:55 GMT</pubDate>
      <guid>https://community.graphisoft.com/t5/Archicad-C-API/Differences-of-GX-Image-WriteToFile-on-Windows-and-MacOS/m-p/398212#M8585</guid>
      <dc:creator>Akos Somorjai</dc:creator>
      <dc:date>2023-09-14T08:14:55Z</dc:date>
    </item>
    <item>
      <title>Re: Differences of GX::Image::WriteToFile(...) on Windows and MacOS</title>
      <link>https://community.graphisoft.com/t5/Archicad-C-API/Differences-of-GX-Image-WriteToFile-on-Windows-and-MacOS/m-p/398214#M8587</link>
      <description>&lt;P&gt;Hey,&lt;BR /&gt;&lt;BR /&gt;yes, `location.GetStatus()` tells us that it is valid. We currently do IO::FileSystem::Copy(...) to that location as a workaround and it succeeds.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I will post a write-up of the code we have and the states the variables are in later.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Best regards,&lt;BR /&gt;David&lt;/P&gt;</description>
      <pubDate>Thu, 14 Sep 2023 09:05:44 GMT</pubDate>
      <guid>https://community.graphisoft.com/t5/Archicad-C-API/Differences-of-GX-Image-WriteToFile-on-Windows-and-MacOS/m-p/398214#M8587</guid>
      <dc:creator>DavidKahlEnscape</dc:creator>
      <dc:date>2023-09-14T09:05:44Z</dc:date>
    </item>
    <item>
      <title>Re: Differences of GX::Image::WriteToFile(...) on Windows and MacOS</title>
      <link>https://community.graphisoft.com/t5/Archicad-C-API/Differences-of-GX-Image-WriteToFile-on-Windows-and-MacOS/m-p/398244#M8588</link>
      <description>&lt;P&gt;Hello again,&lt;BR /&gt;&lt;BR /&gt;to give a bit more context: we get the path to an image on the user's system and want to write it into the Archicad embedded library. I will first show a snippet of the way we use the Archicad API. Our workaround is also in there but commented out.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="cpp"&gt;    ACResult&amp;lt;IO::Location&amp;gt; CreateEmbeddedImageTest(const GS::uchar_t* sourcePath)
    {
        static const auto enscapeFolder = L("EnscapeTextures");
        API_SpecFolderID folderId = API_EmbeddedProjectLibraryFolderID;
        
        // get project library folder
        IO::Location libFolderLocation;
        if (auto errCode = ACAPI_ProjectSettings_GetSpecFolder(&amp;amp;folderId, &amp;amp;libFolderLocation); errCode != NoError)
        {
            return error(errCode);
        }

        if (auto errCode = IO::Folder { libFolderLocation }.GetStatus(); errCode != NoError)
        {
            return error(errCode);
        }

        // ensure enscape texture sub folder exists
        if (auto errCode = libFolderLocation.AppendToLocal(IO::Name { enscapeFolder }); errCode != NoError)
        {
            return error(errCode);
        }

        if (auto errCode = IO::fileSystem.CreateFolderTree(libFolderLocation); errCode != NoError)
        {
            return error(errCode);
        }

        IO::Folder enscapeTextureFolder { libFolderLocation };
        if (auto errCode = enscapeTextureFolder.GetStatus(); errCode != NoError)
        {
            return error(errCode);
        }

        IO::Location sourceLocation { sourcePath };
        IO::File sourceFile { sourceLocation, IO::File::OnNotFound::Ignore };

        logDebug(GS::UniString::SPrintf("Reading image from location '%T'.", sourceLocation.ToLogText().ToPrintf()));

        if (auto errCode = sourceFile.GetStatus(); errCode != NoError)
        {
            return error(errCode);
        }

        if (sourceFile.IsReadable())
        {
            IO::Name sourceFileName;
            if (auto errCode = sourceLocation.GetLastLocalName(&amp;amp;sourceFileName); errCode != NoError)
            {
                return error(errCode);
            }
            
            IO::Location targetLocation { libFolderLocation, sourceFileName };
            
            logDebug(GS::UniString::SPrintf("Attempting to write image to location '%T'.", targetLocation.ToLogText().ToPrintf()));

            // This call needs to check for == NoError because of "IO::File::OnNotFound::Fail"
            if (auto err = IO::File(targetLocation, IO::File::OnNotFound::Fail).GetStatus(); err == NoError)
            {
                logDebug(GS::UniString::SPrintf("Deleting old image from location '%T'.", targetLocation.ToLogText().ToPrintf()));

                // Delete so that we can create a new file with the same name in the next call
                IO::fileSystem.Delete(targetLocation);
            }

            auto image = GX::Image(sourceLocation);

            // just to show the image is valid...
            logDebug(GS::UniString::SPrintf("Writing image '%T' (H %i x W %i, %i bit) to file...", 
                sourceLocation.ToLogText().ToPrintf(),
                image.GetHeight(),
                image.GetWidth(),
                image.GetColorDepth()));

            // Here, we now use Copy to work around error on Mac, instead of the line below that
            // auto errCode = IO::fileSystem.Copy(sourceLocation, targetLocation);
            auto errCode = image.WriteToFile(targetLocation, image.GetTypeID());

            if (errCode != NoError)
            {
                logDebug(GS::UniString::SPrintf("Failed to write image '%T' to the embedded library.", targetLocation.ToLogText().ToPrintf()));
                return error(errCode);
            }

            API_LibPart libPart {
                .typeID = APILib_PictID,
                .location = &amp;amp;targetLocation,
            };

            if (auto errCode = ACAPI_LibraryPart_Register(&amp;amp;libPart); errCode != NoError)
            {
                return error(errCode);
            }

            return ok(targetLocation);
        }
        else
        {
            return ok(sourceLocation);
        }
    }&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;BR /&gt;This is the log output.&lt;/P&gt;&lt;LI-CODE lang="markup"&gt;15:57:39.645 [1] | DEBUG | Reading image from location '/Users/{username}/Enscape/ImportedTextures/0b593a9043a7a5013eb5b6ce3b56cf0d/Carpet.jpg'.
15:57:39.645 [1] | DEBUG | Attempting to write image to location '/Users/{username}/Library/Application Support/Graphisoft/AutoSave-27/Emb_1037365571/content/EnscapeTextures/Carpet.jpg'.
15:57:39.646 [1] | DEBUG | Writing image '/Users/{username}/Enscape/ImportedTextures/0b593a9043a7a5013eb5b6ce3b56cf0d/Carpet.jpg' (H 1024 x W 1024, 32 bit) to file...
2023-09-14 15:57:39.652013+0200 Archicad[25010:2669540] [Archicad] IIOImageWriteSession:121: cannot create: '/Users/{username}/Library/Application Support/Graphisoft/AutoSave-27/Emb_1037365571/content/EnscapeTextures/.Carpet.jpg-sWPY'
         error = 20 (Not a directory)
15:57:39.652 [1] | DEBUG | Failed to write image '/Users/{username}/Library/Application Support/Graphisoft/AutoSave-27/Emb_1037365571/content/EnscapeTextures/Carpet.jpg' to the embedded library.&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Best regards,&lt;BR /&gt;David&lt;/P&gt;</description>
      <pubDate>Thu, 14 Sep 2023 14:17:31 GMT</pubDate>
      <guid>https://community.graphisoft.com/t5/Archicad-C-API/Differences-of-GX-Image-WriteToFile-on-Windows-and-MacOS/m-p/398244#M8588</guid>
      <dc:creator>DavidKahlEnscape</dc:creator>
      <dc:date>2023-09-14T14:17:31Z</dc:date>
    </item>
    <item>
      <title>Re: Differences of GX::Image::WriteToFile(...) on Windows and MacOS</title>
      <link>https://community.graphisoft.com/t5/Archicad-C-API/Differences-of-GX-Image-WriteToFile-on-Windows-and-MacOS/m-p/398246#M8589</link>
      <description>&lt;P&gt;Edit: Deleted duplicate post.&lt;/P&gt;</description>
      <pubDate>Fri, 15 Sep 2023 07:07:16 GMT</pubDate>
      <guid>https://community.graphisoft.com/t5/Archicad-C-API/Differences-of-GX-Image-WriteToFile-on-Windows-and-MacOS/m-p/398246#M8589</guid>
      <dc:creator>DavidKahlEnscape</dc:creator>
      <dc:date>2023-09-15T07:07:16Z</dc:date>
    </item>
    <item>
      <title>Re: Differences of GX::Image::WriteToFile(...) on Windows and MacOS</title>
      <link>https://community.graphisoft.com/t5/Archicad-C-API/Differences-of-GX-Image-WriteToFile-on-Windows-and-MacOS/m-p/398533#M8596</link>
      <description>&lt;P&gt;Hi David,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The reason why it behaves differently on Mac and Windows is that the underlying mechanism is platform dependent; it uses ImageIO on the Mac.&lt;/P&gt;
&lt;P&gt;From your code it seems that you definitely know that the image you are copying is valid, so it’s OK to use the FileSystem::Copy to move it to the embedded library.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I guess '{username}’ is replaced by a valid user on the test computer...&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I’ll try to reproduce this on my computer later during the week; I’m on an offsite workshop on Monday and Tuesday.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Best, Akos&lt;/P&gt;</description>
      <pubDate>Mon, 18 Sep 2023 06:39:52 GMT</pubDate>
      <guid>https://community.graphisoft.com/t5/Archicad-C-API/Differences-of-GX-Image-WriteToFile-on-Windows-and-MacOS/m-p/398533#M8596</guid>
      <dc:creator>Akos Somorjai</dc:creator>
      <dc:date>2023-09-18T06:39:52Z</dc:date>
    </item>
    <item>
      <title>Re: Differences of GX::Image::WriteToFile(...) on Windows and MacOS</title>
      <link>https://community.graphisoft.com/t5/Archicad-C-API/Differences-of-GX-Image-WriteToFile-on-Windows-and-MacOS/m-p/398541#M8597</link>
      <description>&lt;P&gt;Hi Akos,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;okay, that is good to know that the workaround sounds valid! Still, it would be great if you could reproduce the behavior so that maybe we can end up with one code path on both platforms.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Yes, the developer that created the snippet decided to replace his name with '{username}'. It is a valid user on his machine.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Best regards,&lt;BR /&gt;David&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 18 Sep 2023 08:49:01 GMT</pubDate>
      <guid>https://community.graphisoft.com/t5/Archicad-C-API/Differences-of-GX-Image-WriteToFile-on-Windows-and-MacOS/m-p/398541#M8597</guid>
      <dc:creator>DavidKahlEnscape</dc:creator>
      <dc:date>2023-09-18T08:49:01Z</dc:date>
    </item>
    <item>
      <title>Re: Differences of GX::Image::WriteToFile(...) on Windows and MacOS</title>
      <link>https://community.graphisoft.com/t5/Archicad-C-API/Differences-of-GX-Image-WriteToFile-on-Windows-and-MacOS/m-p/399222#M8610</link>
      <description>&lt;P&gt;Hi David,&lt;BR /&gt;&lt;BR /&gt;You've mentioned, that you can use the function to write outside of the embedded library.&lt;BR /&gt;I've also had issues with writing directly to the embedded library, but in different situations.&lt;BR /&gt;So my initial guess would be that it has more to do with the embedded lib than with the specific write function.&lt;BR /&gt;&lt;BR /&gt;What worked best for me so far was to use &lt;EM&gt;APIEnv_CopyFilesIntoLibraryID&lt;/EM&gt; after deleting the target file first with &lt;EM&gt;APIEnv_DeleteEmbeddedLibItemID.&lt;/EM&gt;&lt;BR /&gt;Something like:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="cpp"&gt;IO::Location targetFile (embeddedLibLoc, fileName);
err = ACAPI_Environment (APIEnv_DeleteEmbeddedLibItemID, &amp;amp;targetFile);
if (err != NoError) { return err; }

GS::Array&amp;lt;IO::Location&amp;gt; filesToCopy{ file.GetLocation () };
bool overwriteIfExists = true;
err = ACAPI_Environment (APIEnv_CopyFilesIntoLibraryID, &amp;amp;embeddedLibLoc,
	&amp;amp;filesToCopy, &amp;amp;overwriteIfExists);
if (err != NoError) { return err; }

err = ACAPI_Automate (APIDo_ReloadLibrariesID);
if (err != NoError) { return err; }&lt;/LI-CODE&gt;
&lt;P&gt;&lt;EM&gt;&amp;nbsp;&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;Best,&lt;BR /&gt;Bernd&lt;/P&gt;</description>
      <pubDate>Fri, 22 Sep 2023 05:23:36 GMT</pubDate>
      <guid>https://community.graphisoft.com/t5/Archicad-C-API/Differences-of-GX-Image-WriteToFile-on-Windows-and-MacOS/m-p/399222#M8610</guid>
      <dc:creator>BerndSchwarzenbacher</dc:creator>
      <dc:date>2023-09-22T05:23:36Z</dc:date>
    </item>
  </channel>
</rss>

