Buscar/Criar uma biblioteca que leia e grave arquivos de imagem em camadas sem perder dados

Criar uma biblioteca que leia e grave arquivos de imagem em camadas sem perder dados

Use ao criar uma biblioteca para imagens em camadas em formato binário. Separa a leitura binária da API do usuário, lê as seções em ordem, guarda dados desconhecidos, refaz os grupos de camadas, testa lendo, gravando e relendo, e automatiza a publicação.

Para usar estas regras de IA
## Instalar só as dependências que a tarefa pede e usar os comandos do projeto Leia a documentação para colaboradores antes de alterar o código. Use o gerenciador de ambientes e os comandos de tarefas do repositório em vez de chamar ferramentas de um ambiente de execução não relacionado. Configure somente os grupos de dependências exigidos pela tarefa: - instale as dependências de desenvolvimento padrão para análise sintática e testes; - adicione o grupo opcional de renderização quando houver composição ou rasterização; - inclua os grupos de documentação somente ao gerar a documentação; - espere que pacotes científicos ou de desenho opcionais não estejam disponíveis em algumas combinações novas de ambiente de execução e sistema operacional. Use os comandos canônicos para: - gerar módulos de extensão compilados e artefatos de distribuição; - executar toda a suíte de testes com cobertura; - executar um único teste pelo identificador do nó; - executar testes sem cobertura ao medir um comportamento específico; - executar verificações de estilo, formatação e tipos estáticos; - gerar a documentação HTML e inspecionar o diretório de saída indicado nela. Não trate as dependências opcionais de renderização como requisitos centrais da análise sintática. Forneça uma instrução clara de instalação quando uma operação opcional for solicitada sem suas dependências. ## Separar a leitura e gravação binária de baixo nível da API do usuário Mantenha a análise sintática binária de baixo nível separada da API de usuário de alto nível. A camada de baixo nível: - lê e grava o formato binário bruto de acordo com sua especificação; - representa cabeçalhos, registros, blocos etiquetados, descritores, recursos de imagem, máscaras, canais e dados de compressão; - expõe os métodos explícitos de serialização `read(fp)` e `write(fp)`; - preserva dados desconhecidos que ainda não podem ser interpretados. A camada de alto nível: - envolve estruturas de documento de baixo nível em interfaces fáceis de usar; - reconstrói árvores de objetos voltadas ao usuário a partir de registros binários planos; - expõe tipos de camada, efeitos, máscaras, renderização e operações de documento; - adia a análise sintática dispendiosa até o acesso aos dados, quando o contrato permitir. O código interno deve importar definições concretas de baixo nível dos módulos que as definem. Os usuários externos devem usar as exportações suportadas do pacote. Não exponha detalhes de representação de baixo nível em métodos públicos sem uma justificativa de compatibilidade. ## Ler e gravar as seções do arquivo em ordem e guardar os dados desconhecidos Trate a ordem das seções, os comprimentos, as assinaturas e as larguras numéricas como parte do contrato do formato de arquivo. Um arquivo de imagem em camadas típico contém cinco seções sequenciais: 1. Um cabeçalho de arquivo de tamanho fixo contendo assinatura, versão, dimensões, canais e modo de cor. 2. Dados do modo de cor, como paletas indexadas. 3. Recursos de imagem, como perfis de cor, guias e miniaturas. 4. Informações de camada e máscara contendo registros de camada, dados de canais e blocos etiquetados. 5. Dados da imagem composta e achatada. Valide tamanhos fixos de cabeçalho, como 26 bytes, quando a especificação exigir. Leia e grave as seções em ordem; não deduza os limites a partir de objetos convenientes na memória. Retorne dos métodos de serialização o número de bytes gravados para que seus chamadores possam verificar o cálculo do tamanho. Preserve cargas desconhecidas como bytes durante a ida e volta em vez de descartá-las. ## Reconstruir os grupos de camadas a partir da lista plana de registros Quando o formato armazenar uma hierarquia como uma lista plana, interprete os registros de limite explícitos em vez de presumir apenas a adjacência. Reconheça os marcadores de início e fim de grupo e reconstrua as relações pai-filho com uma pilha ou uma máquina de estados verificada equivalente. Teste pelo menos: - registros comuns fora de grupos; - um grupo contendo vários filhos; - grupos aninhados; - grupos vazios; - marcadores de limite malformados ou desequilibrados; - a preservação da ordem original dos registros. Mantenha a lista plana de registros de baixo nível disponível para serialização enquanto expõe uma árvore pela API de alto nível. Não permita que a reconstrução da árvore altere registros binários não relacionados. ## Adicionar blocos etiquetados por meio de um registro e manter intactos os que não são suportados Dê às estruturas binárias um contrato-base compartilhado, com leitura no nível da classe e escrita no nível da instância. Componha estruturas complexas recursivamente a partir de primitivas pequenas. Use recursos de classes de dados tipadas de forma consistente para: - inicializadores gerados; - validação de campos; - dicas de tipo; - representações controladas; - conversão previsível em tuplas ou sequências quando necessário. Mantenha os validadores consistentes com as anotações e use um tipo de retorno da própria instância para construtores encadeáveis ou que reconheçam a classe. Para blocos etiquetados extensíveis: - use uma chave de etiqueta de largura fixa e a carga associada; - associe etiquetas conhecidas a classes de tratamento por meio de um registro; - verifique se a etiqueta existe antes de ler seus dados tipados; - mantenha blocos não suportados intactos para gravação posterior; - separe o acesso público de conveniência do acesso interno aos registros. Não registre uma classe de tratamento que consuma bytes que ela não possa gravar novamente de forma fiel. ## Acelerar a compressão e os cálculos de pixels sem quebrar a implementação alternativa Meça os caminhos sensíveis ao desempenho antes de otimizá-los. Use codecs compilados para compressão ou descompressão dispendiosa quando disponíveis, mas mantenha uma implementação alternativa correta em linguagem pura. Use carregamento sob demanda para máscaras, efeitos e dados de canais quando adiar a análise sintática preservar a semântica. Use vetorização de arrays em cálculos extensos de pixels e modos de mesclagem quando ela melhorar o desempenho. Toda otimização deve preservar: - a compatibilidade da saída binária; - o comportamento diante de erros; - resultados determinísticos; - a implementação não otimizada; - o suporte a ambientes onde dependências compiladas ou opcionais não estejam disponíveis. Teste as implementações otimizadas e alternativas com os mesmos dados de teste. Não altere silenciosamente os resultados para ganhar velocidade. ## Testar mudanças lendo, gravando e relendo arquivos, e adicionar dicas de tipo Organize os testes para refletir a estrutura do pacote, separando testes binários de baixo nível dos testes da API de alto nível. Mantenha dados binários de teste representativos em um diretório dedicado e parametrize os testes em vários arquivos. Use a validação de ida e volta como invariante principal: 1. Leia o arquivo binário. 2. Modifique um campo controlado. 3. Grave o arquivo. 4. Leia o resultado novamente. 5. Verifique a mudança pretendida e a preservação dos dados não relacionados. Adicione dicas de tipo adequadas a toda nova assinatura de função. Mantenha os validadores de classes de dados alinhados às anotações. Use o tipo de compatibilidade do projeto para métodos que retornem uma instância da própria classe. Execute testes específicos durante o desenvolvimento e, antes de concluir, a suíte completa pertinente, as verificações de estilo, a formatação e a verificação de tipos. Revise as mudanças de cobertura em vez de usar apenas o percentual de cobertura como prova de correção. ## Publicar pelo fluxo automatizado e dizer claramente o que não é suportado Escolha as versões de lançamento de acordo com o padrão de versionamento documentado do projeto, incluindo as formas final, de pré-lançamento e de pós-lançamento. Resuma no registro de alterações, sob o título da nova versão, as mudanças desde a etiqueta anterior. Use o padrão exato de ramificação de lançamento exigido pela etiquetagem automática. Abra uma solicitação de lançamento para a ramificação principal e faça a mesclagem somente após a aprovação. Deixe a automação configurada etiquetar o commit exato mesclado, gerar as distribuições, criar o lançamento hospedado e publicar no registro de pacotes. Não crie uma etiqueta manual quando o fluxo de lançamento for responsável pela etiquetagem. Garanta que a credencial de automação tenha somente as permissões mínimas necessárias para acionar os fluxos posteriores e nunca a exponha. Antes de afirmar que um recurso funciona, verifique os limites documentados para: - renderização de texto quando não houver um mecanismo de fontes; - operações de ajuste suportadas e não suportadas; - o subconjunto de efeitos de camada implementados; - a extração em contraste com a edição de objetos incorporados; - a preservação sem interpretação de dados desconhecidos. Declare explicitamente o comportamento não suportado em vez de aproximá-lo silenciosamente. Conclua informando os testes executados, os caminhos opcionais não exercitados, os riscos de compatibilidade e qualquer limitação que afete a mudança solicitada.