Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Linux Port #9

Merged
merged 5 commits into from
Oct 18, 2021
Merged

Conversation

BusyStudent
Copy link
Contributor

Hi,
I have made a linux port for it,It can be compiled
But when I run the test,the tga file has be exported
the psd file could not be exoported,

***ERROR*** [ImageResources] Image resources section seems to be corrupt, signature does not match "8BIM".
***ERROR*** [ImageResources] Image resources section seems to be corrupt, signature does not match "8BIM".

@MolecularMatters
Copy link
Owner

Hi,

Did you get #8?
That should fix the issue you're seeing.

@BusyStudent
Copy link
Contributor Author

I have #8,but it doesnot fix the issue,
I had fix the error in writing psd,now the psd can be exported in the test

@MolecularMatters
Copy link
Owner

If I understand you correctly, writing PSDs now works, but reading the image resources section is still broken?

@BusyStudent
Copy link
Contributor Author

Yes,But not all image resources sections were broken,only two sections are still broken

@BusyStudent
Copy link
Contributor Author

BusyStudent commented Sep 23, 2021

After debugging
I found that the position read in the function ParseImageResourcesSection was wrong when the error occurred.
He points to 16635 but the correct position is 16636

And this section type is WINDOWS_DEVMODE

const uint32_t signature = fileUtil::ReadFromFileBE<uint32_t>(reader);
if ((signature != util::Key<'8', 'B', 'I', 'M'>::VALUE) && (signature != util::Key<'p', 's', 'd', 'M'>::VALUE))
{
       //reader.m_postiton = 16635 before read
       //But the right postiton is 16636

	PSD_ERROR("ImageResources", "Image resources section seems to be corrupt, signature does not match \"8BIM\".");
	return imageResources;
}

I don’t think the issue come from I/O
Because when I use synchronous I/O this problem still occurred

Reading and writing psd now works normally,except for this secetion

Sorry for my poor english

@MolecularMatters
Copy link
Owner

One byte off sounds like a round-up-to-2/4/8 is missing somewhere.
Looking at ParseImageResourcesSection, the position to read the image resources section comes directly from document->imageResourcesSection.offset, so that value is wrong in this case.

If you look at PsdParseDocument.cpp, the offsets into different sections are all grabbed when creating the document in Create(). I'm not sure if the code has to round up those offsets to the next even value, I'll have to check the PSD spec on that.

One question though: does this happen with the default PSD file that ships with the sample code?
If it does, I would be surprised that this works on Windows, but not on Linux, because the file is the same, which means that the offset has to be the same on both platforms.

@BusyStudent
Copy link
Contributor Author

It does

@MolecularMatters
Copy link
Owner

Ah wait, this is not an off-by-one error.
When reading the offsets into the sections, there is no need to round up or anything. The code fetches the offset from the reader directly using reader.GetPosition().
The correct offset for the image resources section is 34. This is where you'll also find the 8BIM marker in the PSD file.

If your code is pointing at offset 16635, I would think GetPosition() does not work correctly on Linux yet.

@BusyStudent
Copy link
Contributor Author

Emm,SyncFileReader::GetPosition just return m_postion

// ---------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------
void SyncFileReader::Read(void* buffer, uint32_t count)
{
	// do an asynchronous read, wait until it's finished, and update the file position
	File::ReadOperation op = m_file->Read(buffer, count, m_position);
	m_file->WaitForRead(op);

	m_position += count;
}


// ---------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------
void SyncFileReader::Skip(uint64_t count)
{
	m_position += count;
}


// ---------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------
void SyncFileReader::SetPosition(uint64_t position)
{
	m_position = position;
}


// ---------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------
uint64_t SyncFileReader::GetPosition(void) const
{
	return m_position;
}

I donnot know which part was wrong

Reading the section at offset 34 is succeed,
But Reading the section at offset 16635 is failed,the 8BIM marker is on 16636,
Although it is not an important section,it will be skiped bacause the type is WINDOWS_DEVMODE

@MolecularMatters
Copy link
Owner

Apologies, I just noticed that the Windows code also reads from offset 16635, so there's still a bug in there somewhere.
I'll fix this first, so you can try your commits again afterwards.

@MolecularMatters
Copy link
Owner

I just fixed this in 91643c3, can you please give this another try?
If your code now works on Linux, I'll review it today.

@BusyStudent
Copy link
Contributor Author

BusyStudent commented Sep 24, 2021

OK,It works on Linux

@BusyStudent
Copy link
Contributor Author

@MolecularMatters Did you complete the code review?It now works

Comment on lines 367 to 412
#ifdef _WIN32
//In Windows wchar_t is utf16
static_assert(sizeof(wchar_t) == sizeof(uint16_t));
layerName << reinterpret_cast<wchar_t*>(layer->utf16Name);
#else
//In Linux, wchar_t is utf32
//Convert code from https://stackoverflow.com/questions/23919515/how-to-convert-from-utf-16-to-utf-32-on-linux-with-std-library#comment95663809_23920015
//We cannot use C++11,so use macro instead of lambda
#define is_surrogate(uc) ( (uc - 0xd800u) < 2048u )
#define is_high_surrogate(uc) ( (uc & 0xfffffc00) == 0xd800 )
#define is_low_surrogate(uc) ( (uc & 0xfffffc00) == 0xdc00 )
#define surrogate_to_utf32(high,low) ((high << 10) + low - 0x35fdc00)
static_assert(sizeof(wchar_t) == sizeof(uint32_t));

//Begin convert
size_t u16len = 0;
const uint16_t * cur = layer->utf16Name;
while(*cur != uint16_t('\0')){
cur++;
u16len++;
}
//Len it

const uint16_t * const end = layer->utf16Name + u16len;
const uint16_t * input = layer->utf16Name;
while (input < end) {
const uint16_t uc = *input++;
if (!is_surrogate(uc)) {
layerName << wchar_t(uc);
}
else {
if (is_high_surrogate(uc) && input < end && is_low_surrogate(*input)){
layerName << wchar_t(surrogate_to_utf32(uc, *input++));
}
else{
// Error
// Impossible
std::abort();
}
}
}
#undef is_surrogate
#undef is_high_surrogate
#undef is_low_surrogate
#undef surrogate_to_utf32
#endif
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be fine to use C++11 in this part of the sample code, which would probably simplify it a lot.
We could also make it so that when using a pre-C++11 compiler under Linux, the layername simply won't be output, so that the code doesn't require C++11, but rather uses it if available.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could not find the way to convert utf16 to utf32 with std library

#include <cwchar>
#include <cstring>
#include <cstdlib>
#define OutputDebugStringA(S) fputs(S,stderr)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to also put this into a separate file.
Maybe get rid of OutputDebugString altogether and change it into something platform-agnostic, which then calls OutputDebugStringA on Windows, and fputs on Linux?

Copy link
Contributor Author

@BusyStudent BusyStudent Oct 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had put them into PsdDebug.h

Copy link
Owner

@MolecularMatters MolecularMatters left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your effort so far!
I think the code can be improved by paying a bit more attention to details, see my review comments.

@BusyStudent
Copy link
Contributor Author

Ok,I had finished it

@BusyStudent
Copy link
Contributor Author

Did any where need to be changed?

@MolecularMatters
Copy link
Owner

Apologies, this fell off the radar last week.

@MolecularMatters MolecularMatters merged commit 4768e60 into MolecularMatters:master Oct 18, 2021
@MolecularMatters MolecularMatters linked an issue Oct 18, 2021 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Linux support
2 participants