/* * Copyright (c) 2023, Nico Weber * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include namespace Gfx::ICC { static ErrorOr encode_header(ByteBuffer& bytes, Profile const& profile) { VERIFY(bytes.size() >= sizeof(ICCHeader)); auto& raw_header = *bit_cast(bytes.data()); raw_header.profile_size = bytes.size(); raw_header.preferred_cmm_type = profile.preferred_cmm_type().value_or(PreferredCMMType { 0 }); raw_header.profile_version_major = profile.version().major_version(); raw_header.profile_version_minor_bugfix = profile.version().minor_and_bugfix_version(); raw_header.profile_version_zero = 0; raw_header.profile_device_class = profile.device_class(); raw_header.data_color_space = profile.data_color_space(); raw_header.profile_connection_space = profile.connection_space(); time_t profile_timestamp = profile.creation_timestamp(); struct tm tm; if (!gmtime_r(&profile_timestamp, &tm)) return Error::from_errno(errno); raw_header.profile_creation_time.year = tm.tm_year + 1900; raw_header.profile_creation_time.month = tm.tm_mon + 1; raw_header.profile_creation_time.day = tm.tm_mday; raw_header.profile_creation_time.hours = tm.tm_hour; raw_header.profile_creation_time.minutes = tm.tm_min; raw_header.profile_creation_time.seconds = tm.tm_sec; raw_header.profile_file_signature = ProfileFileSignature; raw_header.primary_platform = profile.primary_platform().value_or(PrimaryPlatform { 0 }); raw_header.profile_flags = profile.flags().bits(); raw_header.device_manufacturer = profile.device_manufacturer().value_or(DeviceManufacturer { 0 }); raw_header.device_model = profile.device_model().value_or(DeviceModel { 0 }); raw_header.device_attributes = profile.device_attributes().bits(); raw_header.rendering_intent = profile.rendering_intent(); raw_header.pcs_illuminant = profile.pcs_illuminant(); raw_header.profile_creator = profile.creator().value_or(Creator { 0 }); memset(raw_header.reserved, 0, sizeof(raw_header.reserved)); auto id = Profile::compute_id(bytes); static_assert(sizeof(id.data) == sizeof(raw_header.profile_id)); memcpy(raw_header.profile_id, id.data, sizeof(id.data)); return {}; } ErrorOr encode(Profile const& profile) { // Leaves enough room for the profile header and the tag table count. // FIXME: Serialize tag data and write tag table and tag data too. auto bytes = TRY(ByteBuffer::create_zeroed(sizeof(ICCHeader) + sizeof(u32))); TRY(encode_header(bytes, profile)); return bytes; } }